void ANUTActor::ExecuteOnServer(UObject* InTargetObj, FString InTargetFunc) { if (InTargetObj != NULL && InTargetFunc.Len() > 0) { // Only static functions can be used, so verify this is referencing a static function FName TargetFuncName = *InTargetFunc; UFunction* TargetFuncObj = InTargetObj->FindFunction(TargetFuncName); if (FString(TargetFuncName.ToString()).StartsWith(TEXT("UnitTestServer_"), ESearchCase::CaseSensitive)) { if (TargetFuncObj != NULL) { if (TargetFuncObj->HasAnyFunctionFlags(FUNC_Static)) { UObject* TargetObjCDO = (InTargetObj->HasAnyFlags(EObjectFlags::RF_ClassDefaultObject) ? InTargetObj : InTargetObj->GetClass()->GetDefaultObject()); // Now that we've verified it's a static function, change the delegate object to the class default object // (as that is where static function must be executed, as there is no serverside unit test instance), // and then send it to the server TempDelegate.BindUFunction(TargetObjCDO, TargetFuncName); UDelegateProperty* DelProp = FindField<UDelegateProperty>(GetClass(), TEXT("TempDelegate")); FString DelString; DelProp->ExportTextItem(DelString, DelProp->ContainerPtrToValuePtr<uint8>(this), NULL, this, 0, NULL); ServerExecute(DelString); } else { UE_LOG(LogUnitTest, Log, TEXT("ExecuteOnServer: Only static functions can be passed to the server.")); } } else { UE_LOG(LogUnitTest, Log, TEXT("ExecuteOnServer: Could not locate InTarget function.")); } } else { UE_LOG(LogUnitTest, Log, TEXT("ExecuteOnServer: Target functions must be prefixed 'UnitTestServer_FuncName'")); } } else { UE_LOG(LogUnitTest, Log, TEXT("ExecuteOnServer: Target not specified")); } }
void UK2Node_Message::AllocateDefaultPins() { UFunction* MessageNodeFunction = GetTargetFunction(); // since we have branching logic in ExpandNode(), this has to be an impure // node with exec pins // // @TODO: make it so we can have impure message nodes using a custom // FNodeHandlingFunctor, instead of ExpandNode() if (MessageNodeFunction && MessageNodeFunction->HasAnyFunctionFlags(FUNC_BlueprintPure)) { // Input - Execution Pin CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, TEXT(""), NULL, false, false, UEdGraphSchema_K2::PN_Execute); // Output - Execution Pin CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, TEXT(""), NULL, false, false, UEdGraphSchema_K2::PN_Then); } Super::AllocateDefaultPins(); }
void UK2Node_LatentAbilityCall::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const { // these nested loops are combing over the same classes/functions the // FBlueprintActionDatabase does; ideally we save on perf and fold this in // with FBlueprintActionDatabase, but we want to keep the modules separate for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (!Class->IsChildOf<UAbilityTask>() || Class->HasAnyClassFlags(CLASS_Abstract)) { continue; } for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt) { UFunction* Function = *FuncIt; if (!Function->HasAnyFunctionFlags(FUNC_Static)) { continue; } // to keep from needlessly instantiating a UBlueprintNodeSpawner, first // check to make sure that the registrar is looking for actions of this type // (could be regenerating actions for a specific asset, and therefore the // registrar would only accept actions corresponding to that asset) if (!ActionRegistrar.IsOpenForRegistration(Function)) { continue; } UObjectProperty* ReturnProperty = Cast<UObjectProperty>(Function->GetReturnProperty()); // see if the function is a static factory method for online proxies bool const bIsProxyFactoryMethod = (ReturnProperty != nullptr) && ReturnProperty->PropertyClass->IsChildOf<UAbilityTask>(); if (bIsProxyFactoryMethod) { UBlueprintNodeSpawner* NodeSpawner = UBlueprintFunctionNodeSpawner::Create(Function); check(NodeSpawner != nullptr); NodeSpawner->NodeClass = GetClass(); auto CustomizeAcyncNodeLambda = [](UEdGraphNode* NewNode, bool bIsTemplateNode, TWeakObjectPtr<UFunction> FunctionPtr) { UK2Node_LatentAbilityCall* AsyncTaskNode = CastChecked<UK2Node_LatentAbilityCall>(NewNode); if (FunctionPtr.IsValid()) { UFunction* Func = FunctionPtr.Get(); UObjectProperty* ReturnProp = CastChecked<UObjectProperty>(Func->GetReturnProperty()); AsyncTaskNode->ProxyFactoryFunctionName = Func->GetFName(); AsyncTaskNode->ProxyFactoryClass = Func->GetOuterUClass(); AsyncTaskNode->ProxyClass = ReturnProp->PropertyClass; } }; TWeakObjectPtr<UFunction> FunctionPtr = Function; NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(CustomizeAcyncNodeLambda, FunctionPtr); // @TODO: since this can't be folded into FBlueprintActionDatabase, we // need a way to associate these spawners with a certain class ActionRegistrar.AddBlueprintAction(Function, NodeSpawner); } } } }
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 }