void IGameplayCueInterface::HandleGameplayCue(AActor *Self, FGameplayTag GameplayCueTag, EGameplayCueEvent::Type EventType, FGameplayCueParameters Parameters) { SCOPE_CYCLE_COUNTER(STAT_GameplayCueInterface_HandleGameplayCue); // Look up a custom function for this gameplay tag. UClass* Class = Self->GetClass(); IGameplayTagsModule& GameplayTagsModule = IGameplayTagsModule::Get(); FGameplayTagContainer TagAndParentsContainer = GameplayTagsModule.GetGameplayTagsManager().RequestGameplayTagParents(GameplayCueTag); Parameters.OriginalTag = GameplayCueTag; //Find entry for the class FGameplayCueTagFunctionList& GameplayTagFunctionList = PerClassGameplayTagToFunctionMap.FindOrAdd(Class); TArray<FCueNameAndUFunction>* FunctionList = GameplayTagFunctionList.Find(GameplayCueTag); if (FunctionList == NULL) { //generate new function list FunctionList = &GameplayTagFunctionList.Add(GameplayCueTag); for (auto InnerTagIt = TagAndParentsContainer.CreateConstIterator(); InnerTagIt; ++InnerTagIt) { UFunction* Func = NULL; FName CueName = InnerTagIt->GetTagName(); Func = Class->FindFunctionByName(CueName, EIncludeSuperFlag::IncludeSuper); // If the handler calls ForwardGameplayCueToParent, keep calling functions until one consumes the cue and doesn't forward it while (Func) { FCueNameAndUFunction NewCueFunctionPair; NewCueFunctionPair.Tag = *InnerTagIt; NewCueFunctionPair.Func = Func; FunctionList->Add(NewCueFunctionPair); Func = Func->GetSuperFunction(); } // Native functions cant be named with ".", so look for them with _. FName NativeCueFuncName = *CueName.ToString().Replace(TEXT("."), TEXT("_")); Func = Class->FindFunctionByName(NativeCueFuncName, EIncludeSuperFlag::IncludeSuper); while (Func) { FCueNameAndUFunction NewCueFunctionPair; NewCueFunctionPair.Tag = *InnerTagIt; NewCueFunctionPair.Func = Func; FunctionList->Add(NewCueFunctionPair); Func = Func->GetSuperFunction(); } } } //Iterate through all functions in the list until we should no longer continue check(FunctionList); bool bShouldContinue = true; for (int32 FunctionIndex = 0; bShouldContinue && (FunctionIndex < FunctionList->Num()); ++FunctionIndex) { FCueNameAndUFunction& CueFunctionPair = FunctionList->GetData()[FunctionIndex]; UFunction* Func = CueFunctionPair.Func; Parameters.MatchedTagName = CueFunctionPair.Tag; // Reset the forward parameter now, so we can check it after function bForwardToParent = false; IGameplayCueInterface::DispatchBlueprintCustomHandler(Self, Func, EventType, Parameters); bShouldContinue = bForwardToParent; } if (bShouldContinue) { TArray<UGameplayCueSet*> Sets; GetGameplayCueSets(Sets); for (UGameplayCueSet* Set : Sets) { bShouldContinue = Set->HandleGameplayCue(Self, GameplayCueTag, EventType, Parameters); if (!bShouldContinue) { break; } } } if (bShouldContinue) { Parameters.MatchedTagName = GameplayCueTag; GameplayCueDefaultHandler(EventType, Parameters); } }
void UConsole::BuildRuntimeAutoCompleteList(bool bForce) { #if !UE_BUILD_SHIPPING if (!bForce) { // unless forced delay updating until needed bIsRuntimeAutoCompleteUpToDate = false; return; } // clear the existing tree //@todo - probably only need to rebuild the tree + partial command list on level load for (int32 Idx = 0; Idx < AutoCompleteTree.ChildNodes.Num(); Idx++) { FAutoCompleteNode *Node = AutoCompleteTree.ChildNodes[Idx]; delete Node; } AutoCompleteTree.ChildNodes.Empty(); const UConsoleSettings* ConsoleSettings = GetDefault<UConsoleSettings>(); // copy the manual list first AutoCompleteList.Empty(); AutoCompleteList.AddZeroed(ConsoleSettings->ManualAutoCompleteList.Num()); for (int32 Idx = 0; Idx < ConsoleSettings->ManualAutoCompleteList.Num(); Idx++) { AutoCompleteList[Idx] = ConsoleSettings->ManualAutoCompleteList[Idx]; } // console variables { IConsoleManager::Get().ForEachConsoleObject( FConsoleObjectVisitor::CreateStatic< TArray<struct FAutoCompleteCommand>& >( &FConsoleVariableAutoCompleteVisitor::OnConsoleVariable, AutoCompleteList ) ); } // iterate through script exec functions and append to the list int32 ScriptExecCnt = 0; for (TObjectIterator<UFunction> It; It; ++It) { UFunction *Func = *It; // Determine whether or not this is a level script event that we can call (must be defined in the level script actor and not in parent, and has no return value) const UClass* FuncOuter = Cast<UClass>(Func->GetOuter()); const bool bIsLevelScriptFunction = FuncOuter && (FuncOuter->IsChildOf(ALevelScriptActor::StaticClass())) && (FuncOuter != ALevelScriptActor::StaticClass()) && (Func->ReturnValueOffset == MAX_uint16) && (Func->GetSuperFunction() == NULL); // exec functions that either have no parent, level script events, or are in the global state (filtering some unnecessary dupes) if ( (Func->HasAnyFunctionFlags(FUNC_Exec) && (Func->GetSuperFunction() == NULL || FuncOuter)) || bIsLevelScriptFunction) { FString FuncName = Func->GetName(); if(FDefaultValueHelper::HasWhitespaces(FuncName)) { FuncName = FString::Printf(TEXT("\"%s\""), *FuncName); } if( bIsLevelScriptFunction ) { FuncName = FString(TEXT("ce ")) + FuncName; } int32 NewIdx = AutoCompleteList.AddZeroed(1); AutoCompleteList[NewIdx].Command = FuncName; // build a help string // append each property (and it's type) to the help string for (TFieldIterator<UProperty> PropIt(Func); PropIt && (PropIt->PropertyFlags & CPF_Parm); ++PropIt) { UProperty *Prop = *PropIt; FuncName = FString::Printf(TEXT("%s %s[%s]"),*FuncName,*Prop->GetName(),*Prop->GetCPPType()); } AutoCompleteList[NewIdx].Desc = FuncName; ScriptExecCnt++; } } // enumerate maps TArray<FString> Packages; for (int32 PathIdx = 0; PathIdx < ConsoleSettings->AutoCompleteMapPaths.Num(); ++PathIdx) { FPackageName::FindPackagesInDirectory(Packages, FString::Printf(TEXT("%s%s"), *FPaths::GameDir(), *ConsoleSettings->AutoCompleteMapPaths[PathIdx])); } // also include maps in this user's developer dir FPackageName::FindPackagesInDirectory(Packages, FPaths::GameUserDeveloperDir()); for (int32 PackageIndex = 0; PackageIndex < Packages.Num(); PackageIndex++) { FString Pkg = Packages[PackageIndex]; int32 ExtIdx = Pkg.Find(*FPackageName::GetMapPackageExtension(),ESearchCase::IgnoreCase, ESearchDir::FromEnd); FString MapName; if (ExtIdx != INDEX_NONE && Pkg.Split(TEXT("/"),NULL,&MapName,ESearchCase::CaseSensitive, ESearchDir::FromEnd)) { // try to peel off the extension FString TrimmedMapName; if (!MapName.Split(TEXT("."),&TrimmedMapName,NULL,ESearchCase::CaseSensitive, ESearchDir::FromEnd)) { TrimmedMapName = MapName; } int32 NewIdx; // put _P maps at the front so that they match early, since those are generally the maps we want to actually open if (TrimmedMapName.EndsWith(TEXT("_P"))) { NewIdx = 0; AutoCompleteList.InsertZeroed(0,3); } else { NewIdx = AutoCompleteList.AddZeroed(3); } AutoCompleteList[NewIdx].Command = FString::Printf(TEXT("open %s"),*TrimmedMapName); AutoCompleteList[NewIdx].Desc = FString::Printf(TEXT("open %s"),*TrimmedMapName); AutoCompleteList[NewIdx+1].Command = FString::Printf(TEXT("travel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+1].Desc = FString::Printf(TEXT("travel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+2].Command = FString::Printf(TEXT("servertravel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+2].Desc = FString::Printf(TEXT("servertravel %s"),*TrimmedMapName); //MapNames.AddItem(Pkg); } } // misc commands { int32 NewIdx = AutoCompleteList.AddZeroed(1); AutoCompleteList[NewIdx].Command = FString(TEXT("open 127.0.0.1")); AutoCompleteList[NewIdx].Desc = FString(TEXT("open 127.0.0.1 (opens connection to localhost)")); } #if STATS // stat commands { const TSet<FName>& StatGroupNames = FStatGroupGameThreadNotifier::Get().StatGroupNames; int32 NewIdx = AutoCompleteList.AddZeroed(StatGroupNames.Num()); for (const FName& StatGroupName : StatGroupNames) { FString Command = FString(TEXT("Stat ")); Command += StatGroupName.ToString().RightChop(sizeof("STATGROUP_") - 1); AutoCompleteList[NewIdx].Command = Command; AutoCompleteList[NewIdx].Desc = FString(); NewIdx++; } } #endif // build the magic tree! for (int32 ListIdx = 0; ListIdx < AutoCompleteList.Num(); ListIdx++) { FString Command = AutoCompleteList[ListIdx].Command.ToLower(); FAutoCompleteNode *Node = &AutoCompleteTree; for (int32 Depth = 0; Depth < Command.Len(); Depth++) { int32 Char = Command[Depth]; int32 FoundNodeIdx = INDEX_NONE; TArray<FAutoCompleteNode*> &NodeList = Node->ChildNodes; for (int32 NodeIdx = 0; NodeIdx < NodeList.Num(); NodeIdx++) { if (NodeList[NodeIdx]->IndexChar == Char) { FoundNodeIdx = NodeIdx; Node = NodeList[FoundNodeIdx]; NodeList[FoundNodeIdx]->AutoCompleteListIndices.Add(ListIdx); break; } } if (FoundNodeIdx == INDEX_NONE) { FAutoCompleteNode *NewNode = new FAutoCompleteNode(Char); NewNode->AutoCompleteListIndices.Add(ListIdx); Node->ChildNodes.Add(NewNode); Node = NewNode; } } } bIsRuntimeAutoCompleteUpToDate = true; //PrintNode(&AutoCompleteTree); #endif }