int32 UGameplayTagsManager::InsertTagIntoNodeArray(FName Tag, TWeakPtr<FGameplayTagNode> ParentNode, TArray< TSharedPtr<FGameplayTagNode> >& NodeArray, FText CategoryDescription) { int32 InsertionIdx = INDEX_NONE; // See if the tag is already in the array for (int32 CurIdx = 0; CurIdx < NodeArray.Num(); ++CurIdx) { if (NodeArray[CurIdx].IsValid() && NodeArray[CurIdx].Get()->GetSimpleTag() == Tag) { InsertionIdx = CurIdx; break; } } // Insert the tag at the end of the array if not already found if (InsertionIdx == INDEX_NONE) { TSharedPtr<FGameplayTagNode> TagNode = MakeShareable(new FGameplayTagNode(Tag, ParentNode, CategoryDescription)); InsertionIdx = NodeArray.Add(TagNode); FGameplayTag GameplayTag = FGameplayTag(TagNode->GetCompleteTag()); GameplayTagMap.Add(TagNode->GetCompleteTag(), GameplayTag); GameplayTagNodeMap.Add(GameplayTag, TagNode); } return InsertionIdx; }
UGameplayTagReponseTable::UGameplayTagReponseTable(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { // Make an empty tag query. We will actually fill the tag out prior to evaluating the query with ::MakeQuery FGameplayTagContainer Container; Container.AddTagFast(FGameplayTag()); Query = FGameplayEffectQuery::MakeQuery_MatchAllOwningTags(Container); }
FGameplayTag UGameplayTagsManager::RequestGameplayTag(FName TagName, bool ErrorIfNotFound) const { const FGameplayTag* Tag = GameplayTagMap.Find(TagName); if (!Tag) { if (ErrorIfNotFound) { ensureMsgf(false, TEXT("Requested Tag %s was not found. Check tag data table."), *TagName.ToString()); } return FGameplayTag(); } return *Tag; }
FGameplayTag UGameplayTagsManager::RequestGameplayTagDirectParent(const FGameplayTag& GameplayTag) const { const TSharedPtr<FGameplayTagNode>* GameplayTagNode = GameplayTagNodeMap.Find(GameplayTag); if (GameplayTagNode) { TSharedPtr<FGameplayTagNode> Parent = (*GameplayTagNode)->GetParentTagNode().Pin(); if (Parent.IsValid()) { const FGameplayTag* Tag = GameplayTagNodeMap.FindKey(Parent); if (Tag) { return *Tag; } } } return FGameplayTag(); }
void UGameplayTagsManager::ConstructGameplayTagTree() { if (!GameplayRootTag.IsValid()) { GameplayRootTag = MakeShareable(new FGameplayTagNode()); { #if STATS FString PerfMessage = FString::Printf(TEXT("UGameplayTagsManager::ConstructGameplayTagTree: Construct from data asset")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif for (auto It(GameplayTagTables.CreateIterator()); It; It++) { if (*It) { PopulateTreeFromDataTable(*It); } } } if (ShouldImportTagsFromINI()) { #if STATS FString PerfMessage = FString::Printf(TEXT("UGameplayTagsManager::ConstructGameplayTagTree: ImportINI")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif // Update path: Check for old tags in DefaultEngine.ini (we'll push them to the UGameplayTagSettings class). TArray<FString> EngineConfigTags; GConfig->GetArray(TEXT("/Script/GameplayTags.GameplayTagsSettings"), TEXT("GameplayTags"), EngineConfigTags, GEngineIni); if (EngineConfigTags.Num() > 0) { UGameplayTagsSettings* MutableDefault = GetMutableDefault<UGameplayTagsSettings>(); if (MutableDefault->GameplayTags.Num() == 0) { MutableDefault->GameplayTags.Append(EngineConfigTags); } } // Load any GameplayTagSettings from config (their default object) for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (!Class->IsChildOf<UGameplayTagsSettings>() || Class->HasAnyClassFlags(CLASS_Abstract)) { continue; } #if WITH_EDITOR Class->GetDefaultObject<UGameplayTagsSettings>()->SortTags(); #endif for (FString TagStr : Class->GetDefaultObject<UGameplayTagsSettings>()->GameplayTags) { FGameplayTagTableRow TableRow; TableRow.Tag = TagStr; AddTagTableRow(TableRow); } } GameplayRootTag->GetChildTagNodes().Sort(FCompareFGameplayTagNodeByTag()); } if (ShouldUseFastReplication()) { #if STATS FString PerfMessage = FString::Printf(TEXT("UGameplayTagsManager::ConstructGameplayTagTree: Reconstruct NetIndex")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif ConstructNetIndex(); } { #if STATS FString PerfMessage = FString::Printf(TEXT("UGameplayTagsManager::ConstructGameplayTagTree: GameplayTagTreeChangedEvent.Broadcast")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif GameplayTagTreeChangedEvent.Broadcast(); } // Update the TagRedirects map TagRedirects.Empty(); FConfigSection* PackageRedirects = GConfig->GetSectionPrivate(TEXT("/Script/Engine.Engine"), false, true, GEngineIni); for (FConfigSection::TIterator It(*PackageRedirects); It; ++It) { if (It.Key() == TEXT("GameplayTagRedirects")) { FName OldTagName = NAME_None; FName NewTagName; if (FParse::Value(*It.Value(), TEXT("OldTagName="), OldTagName)) { if (FParse::Value(*It.Value(), TEXT("NewTagName="), NewTagName)) { if (ensureMsgf(!TagRedirects.Contains(OldTagName), TEXT("Old tag %s is being redirected to more than one tag. Please remove all the redirections except for one."), *OldTagName.ToString())) { FGameplayTag OldTag = RequestGameplayTag(OldTagName, false); //< This only succeeds if OldTag is in the Table! if (OldTag.IsValid()) { UE_LOG(LogGameplayTags, Warning, TEXT("Old tag (%s) which is being redirected still exists in the table! Generally you should " TEXT("remove the old tags from the table when you are redirecting to new tags, or else users will ") TEXT("still be able to add the old tags to containers.")), *OldTagName.ToString() ); } FGameplayTag NewTag = (NewTagName != NAME_None) ? RequestGameplayTag(NewTagName, false) : FGameplayTag(); if (!NewTag.IsValid() && NewTagName != NAME_None) { UE_LOG(LogGameplayTags, Warning, TEXT("Invalid new tag %s! Cannot replace old tag %s."), *NewTagName.ToString(), *OldTagName.ToString()); } else { // Populate the map TagRedirects.Add(OldTagName, NewTag); } } } } } } }