当前位置: 首页 > news >正文

长沙市制作网站网站的会员系统怎么做

长沙市制作网站,网站的会员系统怎么做,郴州seo排名,建筑人才网官网档案查询系列文章目录 UE蓝图 Get节点和源码 UE蓝图 Set节点和源码 UE蓝图 Cast节点和源码 UE蓝图 分支(Branch)节点和源码 UE蓝图 入口(FunctionEntry)节点和源码 UE蓝图 返回结果(FunctionResult)节点和源码 UE蓝图 函数调用(CallFunction)节点和源码 文章目录 系列文章目录一、Call…系列文章目录 UE蓝图 Get节点和源码 UE蓝图 Set节点和源码 UE蓝图 Cast节点和源码 UE蓝图 分支(Branch)节点和源码 UE蓝图 入口(FunctionEntry)节点和源码 UE蓝图 返回结果(FunctionResult)节点和源码 UE蓝图 函数调用(CallFunction)节点和源码 文章目录 系列文章目录一、CallFunction节点功能二、CallFunction节点用法三、CallFunction使用场景1. **事件处理**2. **条件逻辑**3. **延迟操作**4. **数据处理**5. **AI和角色行为**6. **用户输入处理**7. **系统交互**8. **自定义逻辑** 四、实现原理五、相关源码 一、CallFunction节点功能 CallFunction节点用于调用指定的函数或方法。这些函数可以是引擎自带的也可以是用户自定义的。通过CallFunction节点你可以在蓝图中实现复杂的逻辑和交互。 二、CallFunction节点用法 在Unreal EngineUE的蓝图中CallFunction节点用于在运行时调用一个特定的函数。这个节点通常用于执行那些已经定义好但需要在特定条件下触发的函数。以下是CallFunction节点的基本用法 添加CallFunction节点首先你需要在你的蓝图中从“右键菜单” - 在弹出框中输入函数的名字进行检索-选择你要使用的函数添加一个CallFunction节点。 传递参数如果所调用的函数需要参数你需要将这些参数通过连线的方式传递给CallFunction节点的相应输入引脚。参数的类型和顺序必须与函数定义中的一致。 执行函数当蓝图中的逻辑流程到达CallFunction节点时它将执行所选择的函数。这意味着任何与该函数相关联的逻辑或行为都将被执行。 处理返回值如果调用的函数有返回值你可以在CallFunction节点的“Return Value”引脚处获取这个值。然后你可以将这个返回值用于蓝图中的其他逻辑或传递给其他节点。 连接其他节点你可以将CallFunction节点与其他节点连接起来以创建更复杂的逻辑流程。例如你可以使用Sequence节点来确保一系列操作按顺序执行或者使用Parallel节点来同时执行多个操作。 编译和测试完成蓝图编辑后确保编译你的项目并在游戏中测试CallFunction节点的行为以确保它按照预期工作。 三、CallFunction使用场景 UE蓝图中的CallFunction节点有多个使用场景以下是一些常见的例子 1. 事件处理 在UE中事件是蓝图系统的重要组成部分。当某个事件发生时例如用户点击按钮、角色受到伤害等你可以使用CallFunction节点来调用处理该事件的函数。 2. 条件逻辑 根据游戏状态或条件的不同你可能需要调用不同的函数。CallFunction节点可以与Sequence、Parallel、Branch等节点结合使用实现复杂的条件逻辑。 3. 延迟操作 使用CallFunction节点与Delay节点结合可以实现延迟执行某些函数。例如你可能希望在角色死亡后等待一段时间再触发某些行为。 4. 数据处理 当你需要对数据进行处理或转换时可以创建自定义函数来处理这些数据并通过CallFunction节点来调用这些函数。 5. AI和角色行为 在创建AI或角色行为时你可能需要根据角色的状态或环境来调用不同的函数。CallFunction节点是实现这一目标的重要工具。 6. 用户输入处理 处理用户输入如键盘、鼠标或手柄输入时你可以使用CallFunction节点来调用处理这些输入的函数。 7. 系统交互 与游戏系统如音频、物理、渲染等进行交互时你可能需要调用特定的函数来执行某些操作。CallFunction节点提供了一种方便的方式来调用这些函数。 8. 自定义逻辑 除了上述常见场景外CallFunction节点还可以用于任何需要调用自定义函数的场景。你可以创建自己的函数来实现特定的逻辑或行为并通过CallFunction节点来调用它们。 四、实现原理 创建输入引脚 解析函数的注解获取函数的元数据输入输出参数和是否执行节点等创建引脚 函数定义示例如下 /** Modulo (A % B) */UFUNCTION(BlueprintPure, meta(DisplayName % (integer), CompactNodeTitle %, Keywords % modulus), CategoryMath|Integer)static int32 Percent_IntInt(int32 A, int32 B 1);/** Addition (A B) */UFUNCTION(BlueprintPure, meta(DisplayName int int, CompactNodeTitle , Keywords add plus, CommutativeAssociativeBinaryOperator true), CategoryMath|Integer)static int32 Add_IntInt(int32 A, int32 B 1);调用FKCHandler_CallFunction.RegisterNets注册函数引脚 for (UEdGraphPin* Pin : Node-Pins){const bool bIsConnected (Pin-LinkedTo.Num() ! 0);// if this pin could use a default (it doesnt have a connection or default of its own)if (!bIsConnected (Pin-DefaultObject nullptr)){if (DefaultToSelfParamNames.Contains(Pin-PinName) FKismetCompilerUtilities::ValidateSelfCompatibility(Pin, Context)){ensure(Pin-PinType.PinSubCategoryObject ! nullptr);ensure((Pin-PinType.PinCategory UEdGraphSchema_K2::PC_Object) || (Pin-PinType.PinCategory UEdGraphSchema_K2::PC_Interface));FBPTerminal* Term Context.RegisterLiteral(Pin);Term-Type.PinSubCategory UEdGraphSchema_K2::PN_Self;Context.NetMap.Add(Pin, Term);}else if (RequiresSetValue.Contains(Pin-PinName)){CompilerContext.MessageLog.Error(*NSLOCTEXT(KismetCompiler, PinMustHaveConnection_Error, Pin must have a connection).ToString(), Pin);}}}调用Compile编译创建Statement FBlueprintCompiledStatement* LatentStatement nullptr; //遍历需要调用该函数的所有上下文并为每个上下文发出一个调用函数语句 for (FBPTerminal* Target : ContextTerms) {FBlueprintCompiledStatement Statement Context.AppendStatementForNode(Node);Statement.FunctionToCall Function;Statement.FunctionContext Target;Statement.Type KCST_CallFunction;Statement.bIsInterfaceContext IsCalledFunctionFromInterface(Node);Statement.bIsParentContext IsCalledFunctionFinal(Node);Statement.LHS LHSTerm;Statement.RHS RHSTerms;if (!bIsLatent){// Fixup ubergraph callsif (pSrcEventNode){UEdGraphPin* ExecOut CompilerContext.GetSchema()-FindExecutionPin(**pSrcEventNode, EGPD_Output);check(CompilerContext.UbergraphContext);CompilerContext.UbergraphContext-GotoFixupRequestMap.Add(Statement, ExecOut);Statement.UbergraphCallIndex 0;}}else{// Fixup latent functionsif (LatentTargetNode (Target ContextTerms.Last())){check(LatentTargetParamIndex ! INDEX_NONE);Statement.UbergraphCallIndex LatentTargetParamIndex;Context.GotoFixupRequestMap.Add(Statement, ThenExecPin);LatentStatement Statement;}}AdditionalCompiledStatementHandling(Context, Node, Statement);if(Statement.Type KCST_CallFunction Function-HasAnyFunctionFlags(FUNC_Delegate)){CompilerContext.MessageLog.Error(*LOCTEXT(CallingDelegate_Error, is trying to call a delegate function - delegates cannot be called directly).ToString(), Node);// Sanitize the statement, this would have ideally been detected earlier but we need// to run AdditionalCompiledStatementHandling to satisify the DelegateNodeHandler// implementation:Statement.Type KCST_CallDelegate;} }五、相关源码 源码文件 CallFunctionHandler.h CallFunctionHandler.cpp K2Node_CallFunction.h K2Node_CallFunction.cpp 相关类 FKCHandler_CallFunction K2Node_CallFunction /******************************************************************************** UK2Node_CallFunction******************************************************************************/UK2Node_CallFunction::UK2Node_CallFunction(const FObjectInitializer ObjectInitializer): Super(ObjectInitializer), bPinTooltipsValid(false) {OrphanedPinSaveMode ESaveOrphanPinMode::SaveAll; }bool UK2Node_CallFunction::HasDeprecatedReference() const {UFunction* Function GetTargetFunction();return (Function Function-HasMetaData(FBlueprintMetadata::MD_DeprecatedFunction)); }FEdGraphNodeDeprecationResponse UK2Node_CallFunction::GetDeprecationResponse(EEdGraphNodeDeprecationType DeprecationType) const {FEdGraphNodeDeprecationResponse Response Super::GetDeprecationResponse(DeprecationType);if (DeprecationType EEdGraphNodeDeprecationType::NodeHasDeprecatedReference){// TEMP: Do not warn in the case of SpawnActor, as we have a special upgrade path for those nodesif (FunctionReference.GetMemberName() FName(TEXT(BeginSpawningActorFromBlueprint))){Response.MessageType EEdGraphNodeDeprecationMessageType::None;}else{UFunction* Function GetTargetFunction();if (ensureMsgf(Function ! nullptr, TEXT(This node should not be able to report having a deprecated reference if the target function cannot be resolved.))){FString DetailedMessage Function-GetMetaData(FBlueprintMetadata::MD_DeprecationMessage);Response.MessageText FBlueprintEditorUtils::GetDeprecatedMemberUsageNodeWarning(GetUserFacingFunctionName(Function), FText::FromString(DetailedMessage));}}}return Response; }FText UK2Node_CallFunction::GetFunctionContextString() const {FText ContextString;// Dont show target is if no target pin!UEdGraphPin* SelfPin GetDefaultUEdGraphSchema_K2()-FindSelfPin(*this, EGPD_Input);if(SelfPin ! NULL !SelfPin-bHidden){const UFunction* Function GetTargetFunction();UClass* CurrentSelfClass (Function ! NULL) ? Function-GetOwnerClass() : NULL;UClass const* TrueSelfClass CurrentSelfClass;if (CurrentSelfClass CurrentSelfClass-ClassGeneratedBy){TrueSelfClass CurrentSelfClass-GetAuthoritativeClass();}const FText TargetText FBlueprintEditorUtils::GetFriendlyClassDisplayName(TrueSelfClass);FFormatNamedArguments Args;Args.Add(TEXT(TargetName), TargetText);ContextString FText::Format(LOCTEXT(CallFunctionOnDifferentContext, Target is {TargetName}), Args);}return ContextString; }FText UK2Node_CallFunction::GetNodeTitle(ENodeTitleType::Type TitleType) const {FText FunctionName;FText ContextString;FText RPCString;if (UFunction* Function GetTargetFunction()){RPCString UK2Node_Event::GetLocalizedNetString(Function-FunctionFlags, true);FunctionName GetUserFacingFunctionName(Function);ContextString GetFunctionContextString();}else{FunctionName FText::FromName(FunctionReference.GetMemberName());if ((GEditor ! NULL) (GetDefaultUEditorStyleSettings()-bShowFriendlyNames)){FunctionName FText::FromString(FName::NameToDisplayString(FunctionName.ToString(), false));}}if(TitleType ENodeTitleType::FullTitle){FFormatNamedArguments Args;Args.Add(TEXT(FunctionName), FunctionName);Args.Add(TEXT(ContextString), ContextString);Args.Add(TEXT(RPCString), RPCString);if (ContextString.IsEmpty() RPCString.IsEmpty()){return FText::Format(LOCTEXT(CallFunction_FullTitle, {FunctionName}), Args);}else if (ContextString.IsEmpty()){return FText::Format(LOCTEXT(CallFunction_FullTitle_WithRPCString, {FunctionName}\n{RPCString}), Args);}else if (RPCString.IsEmpty()){return FText::Format(LOCTEXT(CallFunction_FullTitle_WithContextString, {FunctionName}\n{ContextString}), Args);}else{return FText::Format(LOCTEXT(CallFunction_FullTitle_WithContextRPCString, {FunctionName}\n{ContextString}\n{RPCString}), Args);}}else{return FunctionName;} }void UK2Node_CallFunction::GetPinHoverText(const UEdGraphPin Pin, FString HoverTextOut) const {if (!bPinTooltipsValid){for (UEdGraphPin* P : Pins){if (!P-PinToolTip.IsEmpty() ExpandAsEnumPins.Contains(P)){continue;}P-PinToolTip.Reset();GeneratePinTooltip(*P);}bPinTooltipsValid true;}return UK2Node::GetPinHoverText(Pin, HoverTextOut); }void UK2Node_CallFunction::AllocateDefaultPins() {InvalidatePinTooltips();UBlueprint* MyBlueprint GetBlueprint();UFunction* Function GetTargetFunction();// favor the skeleton function if possible (in case the signature has // changed, and not yet compiled).if (!FunctionReference.IsSelfContext()){UClass* FunctionClass FunctionReference.GetMemberParentClass(MyBlueprint-GeneratedClass);if (UBlueprintGeneratedClass* BpClassOwner CastUBlueprintGeneratedClass(FunctionClass)){// this function could currently only be a part of some skeleton // class (the blueprint has not be compiled with it yet), so lets // check the skeleton class as well, see if we can pull pin data // from there...UBlueprint* FunctionBlueprint CastCheckedUBlueprint(BpClassOwner-ClassGeneratedBy, ECastCheckedType::NullAllowed);if (FunctionBlueprint){if (UFunction* SkelFunction FindUFieldUFunction(FunctionBlueprint-SkeletonGeneratedClass, FunctionReference.GetMemberName())){Function SkelFunction;}}}}// First try remap tableif (Function NULL){UClass* ParentClass FunctionReference.GetMemberParentClass(GetBlueprintClassFromNode());if (ParentClass ! NULL){if (UFunction* NewFunction FMemberReference::FindRemappedFieldUFunction(ParentClass, FunctionReference.GetMemberName())){// Found a remapped property, update the nodeFunction NewFunction;SetFromFunction(NewFunction);}}}if (Function NULL){// The function no longer exists in the stored scope// Try searching inside all function libraries, in case the function got refactored into one of them.for (TObjectIteratorUClass ClassIt; ClassIt; ClassIt){UClass* TestClass *ClassIt;if (TestClass-IsChildOf(UBlueprintFunctionLibrary::StaticClass())){Function FindUFieldUFunction(TestClass, FunctionReference.GetMemberName());if (Function ! NULL){UClass* OldClass FunctionReference.GetMemberParentClass(GetBlueprintClassFromNode());Message_Note(FText::Format(LOCTEXT(FixedUpFunctionInLibraryFmt, UK2Node_CallFunction: Fixed up function {0}, originally in {1}, now in library {2}.),FText::FromString(FunctionReference.GetMemberName().ToString()),(OldClass ! NULL) ? FText::FromString(*OldClass-GetName()) : LOCTEXT(FixedUpFunctionInLibraryNull, (null)),FText::FromString(TestClass-GetName())).ToString());SetFromFunction(Function);break;}}}}// Now create the pins if we ended up with a valid function to callif (Function ! NULL){CreatePinsForFunctionCall(Function);}FCustomStructureParamHelper::UpdateCustomStructurePins(Function, this);Super::AllocateDefaultPins(); }/** Util to find self pin in an array */ UEdGraphPin* FindSelfPin(TArrayUEdGraphPin* Pins) {for(int32 PinIdx0; PinIdxPins.Num(); PinIdx){if(Pins[PinIdx]-PinName UEdGraphSchema_K2::PN_Self){return Pins[PinIdx];}}return NULL; }void UK2Node_CallFunction::ReallocatePinsDuringReconstruction(TArrayUEdGraphPin* OldPins) {// BEGIN TEMP// We had a bug where the class was being messed up by copy/paste, but the self pin class was still ok. This code fixes up those cases.UFunction* Function GetTargetFunction();if (Function NULL){if (UEdGraphPin* SelfPin FindSelfPin(OldPins)){if (UClass* SelfPinClass CastUClass(SelfPin-PinType.PinSubCategoryObject.Get())){if (UFunction* NewFunction FindUFieldUFunction(SelfPinClass, FunctionReference.GetMemberName())){SetFromFunction(NewFunction);}}}}// END TEMPSuper::ReallocatePinsDuringReconstruction(OldPins);// Connect Execute and Then pins for functions, which became pure.ReconnectPureExecPins(OldPins); }UEdGraphPin* UK2Node_CallFunction::CreateSelfPin(const UFunction* Function) {return FBlueprintNodeStatics::CreateSelfPin(this, Function); }void UK2Node_CallFunction::CreateExecPinsForFunctionCall(const UFunction* Function) {bool bCreateSingleExecInputPin true;bool bCreateThenPin true;ExpandAsEnumPins.Reset();// If not pure, create exec pinsif (!bIsPureFunc){// If we want enum-exec expansion, and it is not disabled, do it nowif(bWantsEnumToExecExpansion){TArrayFName EnumNames;GetExpandEnumPinNames(Function, EnumNames);FProperty* PreviousInput nullptr;for (const FName EnumParamName : EnumNames){FProperty* Prop nullptr;UEnum* Enum nullptr;if (FByteProperty* ByteProp FindFPropertyFByteProperty(Function, EnumParamName)){Prop ByteProp;Enum ByteProp-Enum;}else if (FEnumProperty* EnumProp FindFPropertyFEnumProperty(Function, EnumParamName)){Prop EnumProp;Enum EnumProp-GetEnum();}else if (FBoolProperty* BoolProp FindFPropertyFBoolProperty(Function, EnumParamName)){Prop BoolProp;}if (Prop ! nullptr){const bool bIsFunctionInput !Prop-HasAnyPropertyFlags(CPF_ReturnParm) (!Prop-HasAnyPropertyFlags(CPF_OutParm) ||Prop-HasAnyPropertyFlags(CPF_ReferenceParm));const EEdGraphPinDirection Direction bIsFunctionInput ? EGPD_Input : EGPD_Output;if (bIsFunctionInput){if (PreviousInput){bHasCompilerMessage true;ErrorType EMessageSeverity::Error;ErrorMsg FString::Printf(TEXT(Parameter %s is listed as an ExpandEnumAsExecs input, but %s already was one. Only one is permitted.), *EnumParamName.ToString(), *PreviousInput-GetName());break;}PreviousInput Prop;}if (Enum){// yay, found it! Now create exec pin for eachint32 NumExecs (Enum-NumEnums() - 1);for (int32 ExecIdx 0; ExecIdx NumExecs; ExecIdx){bool const bShouldBeHidden Enum-HasMetaData(TEXT(Hidden), ExecIdx) || Enum-HasMetaData(TEXT(Spacer), ExecIdx);if (!bShouldBeHidden){// Cant use Enum-GetNameByIndex here because it doesnt do namespace manglingconst FString NameStr Enum-GetNameStringByIndex(ExecIdx);UEdGraphPin* CreatedPin nullptr;// todo: really only makes sense if there are multiple outputsif (bIsFunctionInput || EnumNames.Num() 1){CreatedPin CreatePin(Direction, UEdGraphSchema_K2::PC_Exec, *NameStr);}else{CreatedPin CreatePin(Direction, UEdGraphSchema_K2::PC_Exec, *NameStr);CreatedPin-PinFriendlyName FText::FromString(FString::Printf(TEXT((%s) %s), *Prop-GetDisplayNameText().ToString(), *NameStr));}ExpandAsEnumPins.Add(CreatedPin);if (Enum-HasMetaData(TEXT(Tooltip), ExecIdx)){FString EnumTooltip Enum-GetMetaData(TEXT(Tooltip), ExecIdx);if (const UEdGraphSchema_K2* const K2Schema Castconst UEdGraphSchema_K2(GetSchema())){K2Schema-ConstructBasicPinTooltip(*CreatedPin, FText::FromString(EnumTooltip), CreatedPin-PinToolTip);}else{CreatedPin-PinToolTip EnumTooltip;}}}}}else{check(Prop-IsAFBoolProperty());// Create a pin for true and false, note that the order here does not match the// numeric order of bool, but it is more natural to put true first (e.g. to match branch node):ExpandAsEnumPins.Add(CreatePin(Direction, UEdGraphSchema_K2::PC_Exec, TEXT(True)));ExpandAsEnumPins.Add(CreatePin(Direction, UEdGraphSchema_K2::PC_Exec, TEXT(False)));}if (bIsFunctionInput){// If using ExpandEnumAsExec for input, dont want to add a input exec pinbCreateSingleExecInputPin false;}else{// If using ExpandEnumAsExec for output, dont want to add a then pinbCreateThenPin false;}}}}if (bCreateSingleExecInputPin){// Single input exec pinCreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);}if (bCreateThenPin){UEdGraphPin* OutputExecPin CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);// Use completed name for output pins on latent functionsif (Function-HasMetaData(FBlueprintMetadata::MD_Latent)){OutputExecPin-PinFriendlyName FText::FromName(UEdGraphSchema_K2::PN_Completed);}}} }FName UK2Node_CallFunction::GetFunctionName() const {return FunctionReference.GetMemberName(); }void UK2Node_CallFunction::DetermineWantsEnumToExecExpansion(const UFunction* Function) {bWantsEnumToExecExpansion false;if (WantsExecPinsForParams(Function)){TArrayFName EnumNamesToCheck;GetExpandEnumPinNames(Function, EnumNamesToCheck);for (int32 i EnumNamesToCheck.Num() - 1; i 0; --i){const FName EnumParamName EnumNamesToCheck[i];FByteProperty* EnumProp FindFPropertyFByteProperty(Function, EnumParamName);if ((EnumProp ! NULL EnumProp-Enum ! NULL) || FindFPropertyFEnumProperty(Function, EnumParamName)){bWantsEnumToExecExpansion true;EnumNamesToCheck.RemoveAt(i);}else{FBoolProperty* BoolProp FindFPropertyFBoolProperty(Function, EnumParamName);if (BoolProp){bWantsEnumToExecExpansion true;EnumNamesToCheck.RemoveAt(i);}}}if (bWantsEnumToExecExpansion EnumNamesToCheck.Num() 0 !bHasCompilerMessage){bHasCompilerMessage true;ErrorType EMessageSeverity::Warning;if (EnumNamesToCheck.Num() 1){ErrorMsg FText::Format(LOCTEXT(EnumToExecExpansionFailedFmt, Unable to find enum parameter with name {0} to expand for ), FText::FromName(EnumNamesToCheck[0])).ToString();}else{FString ParamNames;for (const FName Name : EnumNamesToCheck){if (!ParamNames.IsEmpty()){ParamNames TEXT(, );}ParamNames Name.ToString();}ErrorMsg FText::Format(LOCTEXT(EnumToExecExpansionFailedMultipleFmt, Unable to find enum parameters for names:\n {{0}} \nto expand for ), FText::FromString(ParamNames)).ToString();}}} }void UK2Node_CallFunction::GetExpandEnumPinNames(const UFunction* Function, TArrayFName EnumNamesToCheck) { EnumNamesToCheck.Reset();// todo: use metadatacache if/when thats accepted.const FString EnumParamString GetAllExecParams(Function);TArrayFString RawGroupings;EnumParamString.ParseIntoArray(RawGroupings, TEXT(,), false);for (FString RawGroup : RawGroupings){RawGroup.TrimStartAndEndInline();TArrayFString IndividualEntries;RawGroup.ParseIntoArray(IndividualEntries, TEXT(|));for (const FString Entry : IndividualEntries){if (Entry.IsEmpty()){continue;}EnumNamesToCheck.Add(*Entry);}} }void UK2Node_CallFunction::GeneratePinTooltip(UEdGraphPin Pin) const {ensure(Pin.GetOwningNode() this);UEdGraphSchema const* Schema GetSchema();check(Schema ! NULL);UEdGraphSchema_K2 const* const K2Schema Castconst UEdGraphSchema_K2(Schema);if (K2Schema NULL){Schema-ConstructBasicPinTooltip(Pin, FText::GetEmpty(), Pin.PinToolTip);return;}// get the class function object associated with this nodeUFunction* Function GetTargetFunction();if (Function NULL){Schema-ConstructBasicPinTooltip(Pin, FText::GetEmpty(), Pin.PinToolTip);return;}GeneratePinTooltipFromFunction(Pin, Function); }bool UK2Node_CallFunction::CreatePinsForFunctionCall(const UFunction* Function) {const UEdGraphSchema_K2* K2Schema GetDefaultUEdGraphSchema_K2();UClass* FunctionOwnerClass Function-GetOuterUClass();bIsInterfaceCall FunctionOwnerClass-HasAnyClassFlags(CLASS_Interface);bIsPureFunc (Function-HasAnyFunctionFlags(FUNC_BlueprintPure) ! false);bIsConstFunc (Function-HasAnyFunctionFlags(FUNC_Const) ! false);DetermineWantsEnumToExecExpansion(Function);// Create input pinsCreateExecPinsForFunctionCall(Function);UEdGraphPin* SelfPin CreateSelfPin(Function);// Renamed self pin to targetSelfPin-PinFriendlyName LOCTEXT(Target, Target);const bool bIsProtectedFunc Function-GetBoolMetaData(FBlueprintMetadata::MD_Protected);const bool bIsStaticFunc Function-HasAllFunctionFlags(FUNC_Static);UEdGraph const* const Graph GetGraph();UBlueprint* BP FBlueprintEditorUtils::FindBlueprintForGraph(Graph);ensure(BP);if (BP ! nullptr){const bool bIsFunctionCompatibleWithSelf BP-SkeletonGeneratedClass-IsChildOf(FunctionOwnerClass);if (bIsStaticFunc){// For static methods, wire up the self to the CDO of the class if its not usif (!bIsFunctionCompatibleWithSelf){UClass* AuthoritativeClass FunctionOwnerClass-GetAuthoritativeClass();SelfPin-DefaultObject AuthoritativeClass-GetDefaultObject();}// Purity doesnt matter with a static function, we can always hide the self pin since we know how to call the methodSelfPin-bHidden true;}else{if (Function-GetBoolMetaData(FBlueprintMetadata::MD_HideSelfPin)){SelfPin-bHidden true;SelfPin-bNotConnectable true;}else{// Hide the self pin if the function is compatible with the blueprint class and pure (the !bIsConstFunc portion should be going away soon too hopefully)SelfPin-bHidden (bIsFunctionCompatibleWithSelf bIsPureFunc !bIsConstFunc);}}}// Build a list of the pins that should be hidden for this function (ones that are automagically filled in by the K2 compiler)TSetFName PinsToHide;TSetFName InternalPins;FBlueprintEditorUtils::GetHiddenPinsForFunction(Graph, Function, PinsToHide, InternalPins);const bool bShowWorldContextPin ((PinsToHide.Num() 0) BP BP-ParentClass BP-ParentClass-HasMetaDataHierarchical(FBlueprintMetadata::MD_ShowWorldContextPin));// Create the inputs and outputsbool bAllPinsGood true;for (TFieldIteratorFProperty PropIt(Function); PropIt (PropIt-PropertyFlags CPF_Parm); PropIt){FProperty* Param *PropIt;const bool bIsFunctionInput !Param-HasAnyPropertyFlags(CPF_ReturnParm) (!Param-HasAnyPropertyFlags(CPF_OutParm) || Param-HasAnyPropertyFlags(CPF_ReferenceParm));const bool bIsRefParam Param-HasAnyPropertyFlags(CPF_ReferenceParm) bIsFunctionInput;const EEdGraphPinDirection Direction bIsFunctionInput ? EGPD_Input : EGPD_Output;UEdGraphNode::FCreatePinParams PinParams;PinParams.bIsReference bIsRefParam;UEdGraphPin* Pin CreatePin(Direction, NAME_None, Param-GetFName(), PinParams);const bool bPinGood (Pin K2Schema-ConvertPropertyToPinType(Param, /*out*/ Pin-PinType));if (bPinGood){// Check for a display name overrideconst FString PinDisplayName Param-GetMetaData(FBlueprintMetadata::MD_DisplayName);if (!PinDisplayName.IsEmpty()){Pin-PinFriendlyName FText::FromString(PinDisplayName);}else if (Function-GetReturnProperty() Param Function-HasMetaData(FBlueprintMetadata::MD_ReturnDisplayName)){Pin-PinFriendlyName Function-GetMetaDataText(FBlueprintMetadata::MD_ReturnDisplayName);}//Flag pin as read only for const reference propertyPin-bDefaultValueIsIgnored Param-HasAllPropertyFlags(CPF_ConstParm | CPF_ReferenceParm) (!Function-HasMetaData(FBlueprintMetadata::MD_AutoCreateRefTerm) || Pin-PinType.IsContainer());const bool bAdvancedPin Param-HasAllPropertyFlags(CPF_AdvancedDisplay);Pin-bAdvancedView bAdvancedPin;if(bAdvancedPin (ENodeAdvancedPins::NoPins AdvancedPinDisplay)){AdvancedPinDisplay ENodeAdvancedPins::Hidden;}FString ParamValue;if (K2Schema-FindFunctionParameterDefaultValue(Function, Param, ParamValue)){K2Schema-SetPinAutogeneratedDefaultValue(Pin, ParamValue);}else{K2Schema-SetPinAutogeneratedDefaultValueBasedOnType(Pin);}if (PinsToHide.Contains(Pin-PinName)){const FString PinNameStr Pin-PinName.ToString();const FString DefaultToSelfMetaValue Function-GetMetaData(FBlueprintMetadata::MD_DefaultToSelf);const FString WorldContextMetaValue Function-GetMetaData(FBlueprintMetadata::MD_WorldContext);bool bIsSelfPin ((PinNameStr DefaultToSelfMetaValue) || (PinNameStr WorldContextMetaValue));if (!bShowWorldContextPin || !bIsSelfPin){Pin-bHidden true;Pin-bNotConnectable InternalPins.Contains(Pin-PinName);}}PostParameterPinCreated(Pin);}bAllPinsGood bAllPinsGood bPinGood;}// If we have enum to exec parameters, set their default value to something valid so we dont get warningsif(bWantsEnumToExecExpansion){TArrayFName EnumNamesToCheck;GetExpandEnumPinNames(Function, EnumNamesToCheck);for (const FName Name : EnumNamesToCheck){UEdGraphPin* EnumParamPin FindPin(Name);if (UEnum* PinEnum (EnumParamPin ? CastUEnum(EnumParamPin-PinType.PinSubCategoryObject.Get()) : NULL)){EnumParamPin-DefaultValue PinEnum-GetNameStringByIndex(0);}}}return bAllPinsGood; }void UK2Node_CallFunction::PostReconstructNode() {Super::PostReconstructNode();InvalidatePinTooltips();// conform pins that are marked as SetParam:ConformContainerPins();FCustomStructureParamHelper::UpdateCustomStructurePins(GetTargetFunction(), this);// Fixup self node, may have been overridden from old self nodeUFunction* Function GetTargetFunction();const bool bIsStaticFunc Function ? Function-HasAllFunctionFlags(FUNC_Static) : false;UEdGraphPin* SelfPin FindPin(UEdGraphSchema_K2::PN_Self);if (bIsStaticFunc SelfPin){// Wire up the self to the CDO of the class if its not usif (UBlueprint* BP GetBlueprint()){UClass* FunctionOwnerClass Function-GetOuterUClass();if (!BP-SkeletonGeneratedClass-IsChildOf(FunctionOwnerClass)){SelfPin-DefaultObject FunctionOwnerClass-GetAuthoritativeClass()-GetDefaultObject();}else{// In case a non-NULL reference was previously serialized on load, ensure that its set to NULL here to match what a new nodes self pin would be initialized as (see CreatePinsForFunctionCall).SelfPin-DefaultObject nullptr;}}}if (UEdGraphPin* TypePickerPin FDynamicOutputHelper::GetTypePickerPin(this)){FDynamicOutputHelper(TypePickerPin).ConformOutputType();}if (IsNodePure()){// Remove any pre-existing breakpoint on this node since pure nodes cannot have breakpointsif (UBreakpoint* ExistingBreakpoint FKismetDebugUtilities::FindBreakpointForNode(GetBlueprint(), this)){// Remove the breakpointFKismetDebugUtilities::StartDeletingBreakpoint(ExistingBreakpoint, GetBlueprint());}} }void UK2Node_CallFunction::NotifyPinConnectionListChanged(UEdGraphPin* Pin) {Super::NotifyPinConnectionListChanged(Pin);// conform pins that are marked as SetParam:ConformContainerPins();if (!ensure(Pin)){return;}FCustomStructureParamHelper::UpdateCustomStructurePins(GetTargetFunction(), this, Pin);// Refresh the node to hide internal-only pins once the [invalid] connection has been brokenif (Pin-bHidden Pin-bNotConnectable Pin-LinkedTo.Num() 0){GetGraph()-NotifyGraphChanged();}if (bIsBeadFunction){if (Pin-LinkedTo.Num() 0){// Commit suicide; bead functions must always have an input and output connectionDestroyNode();}}InvalidatePinTooltips();if(!Pin-IsPendingKill()){FDynamicOutputHelper(Pin).ConformOutputType();} }void UK2Node_CallFunction::PinDefaultValueChanged(UEdGraphPin* Pin) {Super::PinDefaultValueChanged(Pin);InvalidatePinTooltips();FDynamicOutputHelper(Pin).ConformOutputType(); }UFunction* UK2Node_CallFunction::GetTargetFunction() const {if(!FBlueprintCompilationManager::IsGeneratedClassLayoutReady()){// first look in the skeleton class:if(UFunction* SkeletonFn GetTargetFunctionFromSkeletonClass()){return SkeletonFn;}}UFunction* Function FunctionReference.ResolveMemberUFunction(GetBlueprintClassFromNode());return Function; }UFunction* UK2Node_CallFunction::GetTargetFunctionFromSkeletonClass() const {UFunction* TargetFunction nullptr;UClass* ParentClass FunctionReference.GetMemberParentClass( GetBlueprintClassFromNode() );UBlueprint* OwningBP ParentClass ? CastUBlueprint( ParentClass-ClassGeneratedBy ) : nullptr;if( UClass* SkeletonClass OwningBP ? OwningBP-SkeletonGeneratedClass : nullptr ){TargetFunction SkeletonClass-FindFunctionByName( FunctionReference.GetMemberName() );}return TargetFunction; }UEdGraphPin* UK2Node_CallFunction::GetThenPin() const {UEdGraphPin* Pin FindPin(UEdGraphSchema_K2::PN_Then);check(Pin nullptr || Pin-Direction EGPD_Output); // If pin exists, it must be outputreturn Pin; }UEdGraphPin* UK2Node_CallFunction::GetReturnValuePin() const {UEdGraphPin* Pin FindPin(UEdGraphSchema_K2::PN_ReturnValue);check(Pin nullptr || Pin-Direction EGPD_Output); // If pin exists, it must be outputreturn Pin; }bool UK2Node_CallFunction::IsLatentFunction() const {if (UFunction* Function GetTargetFunction()){if (Function-HasMetaData(FBlueprintMetadata::MD_Latent)){return true;}}return false; }bool UK2Node_CallFunction::AllowMultipleSelfs(bool bInputAsArray) const {if (UFunction* Function GetTargetFunction()){return CanFunctionSupportMultipleTargets(Function);}return Super::AllowMultipleSelfs(bInputAsArray); }bool UK2Node_CallFunction::CanFunctionSupportMultipleTargets(UFunction const* Function) {bool const bIsImpure !Function-HasAnyFunctionFlags(FUNC_BlueprintPure);bool const bIsLatent Function-HasMetaData(FBlueprintMetadata::MD_Latent);bool const bHasReturnParam (Function-GetReturnProperty() ! nullptr);return !bHasReturnParam bIsImpure !bIsLatent; }bool UK2Node_CallFunction::CanPasteHere(const UEdGraph* TargetGraph) const {// Basic check for graph compatibility, etc.bool bCanPaste Super::CanPasteHere(TargetGraph);// We check function context for placability only in the base class case; derived classes are typically bound to// specific functions that should always be placeable, but may not always be explicitly callable (e.g. InternalUseOnly).if(bCanPaste GetClass() StaticClass()){const UEdGraphSchema_K2* K2Schema GetDefaultUEdGraphSchema_K2();uint32 AllowedFunctionTypes UEdGraphSchema_K2::EFunctionType::FT_Pure | UEdGraphSchema_K2::EFunctionType::FT_Const | UEdGraphSchema_K2::EFunctionType::FT_Protected;if(K2Schema-DoesGraphSupportImpureFunctions(TargetGraph)){AllowedFunctionTypes | UEdGraphSchema_K2::EFunctionType::FT_Imperative;}UFunction* TargetFunction GetTargetFunction();if( !TargetFunction ){TargetFunction GetTargetFunctionFromSkeletonClass();}if (!TargetFunction){// If the function doesnt exist and it is from self context, then it could be created from a CustomEvent node, that was also pasted (but wasnt compiled yet).bCanPaste FunctionReference.IsSelfContext();}else{bCanPaste K2Schema-CanFunctionBeUsedInGraph(FBlueprintEditorUtils::FindBlueprintForGraphChecked(TargetGraph)-GeneratedClass, TargetFunction, TargetGraph, AllowedFunctionTypes, false);}}return bCanPaste; }bool UK2Node_CallFunction::IsActionFilteredOut(FBlueprintActionFilter const Filter) {bool bIsFilteredOut false;for(UEdGraph* TargetGraph : Filter.Context.Graphs){bIsFilteredOut | !CanPasteHere(TargetGraph);}if(const UFunction* TargetFunction GetTargetFunction()){const bool bIsProtected (TargetFunction-FunctionFlags FUNC_Protected) ! 0;const bool bIsPrivate (TargetFunction-FunctionFlags FUNC_Private) ! 0;const UClass* OwningClass TargetFunction-GetOwnerClass();if( (bIsProtected || bIsPrivate) !FBlueprintEditorUtils::IsNativeSignature(TargetFunction) OwningClass){OwningClass OwningClass-GetAuthoritativeClass();// we can filter private and protected blueprints that are unrelated:bool bAccessibleInAll true;for (const UBlueprint* Blueprint : Filter.Context.Blueprints){UClass* AuthoritativeClass Blueprint-GeneratedClass;if(!AuthoritativeClass){continue;}if(bIsPrivate){bAccessibleInAll bAccessibleInAll AuthoritativeClass OwningClass;}else if(bIsProtected){bAccessibleInAll bAccessibleInAll AuthoritativeClass-IsChildOf(OwningClass);}}if(!bAccessibleInAll){bIsFilteredOut true;}}}return bIsFilteredOut; }static FLinearColor GetPalletteIconColor(UFunction const* Function) {bool const bIsPure (Function ! nullptr) Function-HasAnyFunctionFlags(FUNC_BlueprintPure);if (bIsPure){return GetDefaultUGraphEditorSettings()-PureFunctionCallNodeTitleColor;}return GetDefaultUGraphEditorSettings()-FunctionCallNodeTitleColor; }FSlateIcon UK2Node_CallFunction::GetPaletteIconForFunction(UFunction const* Function, FLinearColor OutColor) {static const FName NativeMakeFunc(TEXT(NativeMakeFunc));static const FName NativeBrakeFunc(TEXT(NativeBreakFunc));if (Function Function-HasMetaData(NativeMakeFunc)){static FSlateIcon Icon(EditorStyle, GraphEditor.MakeStruct_16x);return Icon;}else if (Function Function-HasMetaData(NativeBrakeFunc)){static FSlateIcon Icon(EditorStyle, GraphEditor.BreakStruct_16x);return Icon;}// Check to see if the function is calling an function that could be an event, display the event icon instead.else if (Function UEdGraphSchema_K2::FunctionCanBePlacedAsEvent(Function)){static FSlateIcon Icon(EditorStyle, GraphEditor.Event_16x);return Icon;}else{OutColor GetPalletteIconColor(Function);static FSlateIcon Icon(EditorStyle, Kismet.AllClasses.FunctionIcon);return Icon;} }FLinearColor UK2Node_CallFunction::GetNodeTitleColor() const {return GetPalletteIconColor(GetTargetFunction()); }FText UK2Node_CallFunction::GetTooltipText() const {FText Tooltip;UFunction* Function GetTargetFunction();if (Function nullptr){return FText::Format(LOCTEXT(CallUnknownFunction, Call unknown function {0}), FText::FromName(FunctionReference.GetMemberName()));}else if (CachedTooltip.IsOutOfDate(this)){FText BaseTooltip FText::FromString(GetDefaultTooltipForFunction(Function));FFormatNamedArguments Args;Args.Add(TEXT(DefaultTooltip), BaseTooltip);if (Function-HasAllFunctionFlags(FUNC_BlueprintAuthorityOnly)){Args.Add(TEXT(ClientString),NSLOCTEXT(K2Node, ServerFunction, Authority Only. This function will only execute on the server.));// FText::Format() is slow, so we cache this to save on performanceCachedTooltip.SetCachedText(FText::Format(LOCTEXT(CallFunction_SubtitledTooltip, {DefaultTooltip}\n\n{ClientString}), Args), this);}else if (Function-HasAllFunctionFlags(FUNC_BlueprintCosmetic)){Args.Add(TEXT(ClientString),NSLOCTEXT(K2Node, ClientFunction, Cosmetic. This event is only for cosmetic, non-gameplay actions.));// FText::Format() is slow, so we cache this to save on performanceCachedTooltip.SetCachedText(FText::Format(LOCTEXT(CallFunction_SubtitledTooltip, {DefaultTooltip}\n\n{ClientString}), Args), this);} else{CachedTooltip.SetCachedText(BaseTooltip, this);}}return CachedTooltip; }void UK2Node_CallFunction::GeneratePinTooltipFromFunction(UEdGraphPin Pin, const UFunction* Function) {if (Pin.bWasTrashed){return;}// figure what tag we should be parsing for (is this a return-val pin, or a parameter?)FString ParamName;FString TagStr TEXT(param);const bool bReturnPin Pin.PinName UEdGraphSchema_K2::PN_ReturnValue;if (bReturnPin){TagStr TEXT(return);}else{ParamName Pin.PinName.ToString();}// grab the the functions comment block for us to parseFString FunctionToolTipText Function-GetToolTipText().ToString();int32 CurStrPos INDEX_NONE;int32 FullToolTipLen FunctionToolTipText.Len();// parse the full function tooltip text, looking for tag linesdo {CurStrPos FunctionToolTipText.Find(TagStr, ESearchCase::IgnoreCase, ESearchDir::FromStart, CurStrPos);if (CurStrPos INDEX_NONE) // if the tag wasnt found{break;}// advance past the tagCurStrPos TagStr.Len();// handle people having done returns instead of returnif (bReturnPin CurStrPos FullToolTipLen FunctionToolTipText[CurStrPos] TEXT(s)){CurStrPos;}// advance past whitespacewhile(CurStrPos FullToolTipLen FChar::IsWhitespace(FunctionToolTipText[CurStrPos])){CurStrPos;}// if this is a parameter pinif (!ParamName.IsEmpty()){FString TagParamName;// copy the parameter namewhile (CurStrPos FullToolTipLen !FChar::IsWhitespace(FunctionToolTipText[CurStrPos])){TagParamName.AppendChar(FunctionToolTipText[CurStrPos]);}// if this param tag doesnt match the param were looking forif (TagParamName ! ParamName){continue;}}// advance past whitespace (get to the meat of the comment)// since many doxygen style param use the format param param name - comment we also strip - if it is before we get to any other non-whitespacewhile(CurStrPos FullToolTipLen (FChar::IsWhitespace(FunctionToolTipText[CurStrPos]) || FunctionToolTipText[CurStrPos] -)){CurStrPos;}FString ParamDesc;// collect the param/return-val descriptionwhile (CurStrPos FullToolTipLen FunctionToolTipText[CurStrPos] ! TEXT()){// advance past newlinewhile(CurStrPos FullToolTipLen FChar::IsLinebreak(FunctionToolTipText[CurStrPos])){CurStrPos;// advance past whitespace at the start of a new linewhile(CurStrPos FullToolTipLen FChar::IsWhitespace(FunctionToolTipText[CurStrPos])){CurStrPos;}// replace the newline with a single spaceif(CurStrPos FullToolTipLen !FChar::IsLinebreak(FunctionToolTipText[CurStrPos])){ParamDesc.AppendChar(TEXT( ));}}if (CurStrPos FullToolTipLen FunctionToolTipText[CurStrPos] ! TEXT()){ParamDesc.AppendChar(FunctionToolTipText[CurStrPos]);}}// trim any trailing whitespace from the descriptive textParamDesc.TrimEndInline();// if we came up with a valid description for the param/return-valif (!ParamDesc.IsEmpty()){Pin.PinToolTip ParamDesc;break; // we found a match, so theres no need to continue}} while (CurStrPos FullToolTipLen);// If we have no parameter or return value descriptions the full description will be relevant in describing the return value:if( bReturnPin Pin.PinToolTip.IsEmpty() FunctionToolTipText.Find(TEXT(param)) INDEX_NONE FunctionToolTipText.Find(TEXT(return)) INDEX_NONE){// for the return pin, default to using the function description if no return tag was provided:Pin.PinToolTip Function-GetToolTipText().ToString();}GetDefaultUEdGraphSchema_K2()-ConstructBasicPinTooltip(Pin, FText::FromString(Pin.PinToolTip), Pin.PinToolTip); }FText UK2Node_CallFunction::GetUserFacingFunctionName(const UFunction* Function) {FText ReturnDisplayName;if (Function ! NULL){if (GEditor GetDefaultUEditorStyleSettings()-bShowFriendlyNames){ReturnDisplayName Function-GetDisplayNameText();}else{static const FString Namespace TEXT(UObjectDisplayNames);const FString Key Function-GetFullGroupName(false);ReturnDisplayName Function-GetMetaDataText(TEXT(DisplayName), Namespace, Key);}}return ReturnDisplayName; }FString UK2Node_CallFunction::GetDefaultTooltipForFunction(const UFunction* Function) {FString Tooltip;if (Function ! NULL){Tooltip Function-GetToolTipText().ToString();}if (!Tooltip.IsEmpty()){// Strip off the doxygen nastinessstatic const FString DoxygenParam(TEXT(param));static const FString DoxygenReturn(TEXT(return));static const FString DoxygenSee(TEXT(see));static const FString TooltipSee(TEXT(See:));static const FString DoxygenNote(TEXT(note));static const FString TooltipNote(TEXT(Note:));Tooltip.Split(DoxygenParam, Tooltip, nullptr, ESearchCase::IgnoreCase, ESearchDir::FromStart);Tooltip.Split(DoxygenReturn, Tooltip, nullptr, ESearchCase::IgnoreCase, ESearchDir::FromStart);Tooltip.ReplaceInline(*DoxygenSee, *TooltipSee);Tooltip.ReplaceInline(*DoxygenNote, *TooltipNote);Tooltip.TrimStartAndEndInline();UClass* CurrentSelfClass (Function ! NULL) ? Function-GetOwnerClass() : NULL;UClass const* TrueSelfClass CurrentSelfClass;if (CurrentSelfClass CurrentSelfClass-ClassGeneratedBy){TrueSelfClass CurrentSelfClass-GetAuthoritativeClass();}FText TargetDisplayText (TrueSelfClass ! NULL) ? TrueSelfClass-GetDisplayNameText() : LOCTEXT(None, None);FFormatNamedArguments Args;Args.Add(TEXT(TargetName), TargetDisplayText);Args.Add(TEXT(Tooltip), FText::FromString(Tooltip));return FText::Format(LOCTEXT(CallFunction_Tooltip, {Tooltip}\n\nTarget is {TargetName}), Args).ToString();}else{return GetUserFacingFunctionName(Function).ToString();} }FText UK2Node_CallFunction::GetDefaultCategoryForFunction(const UFunction* Function, const FText BaseCategory) {FText NodeCategory BaseCategory;if( Function-HasMetaData(FBlueprintMetadata::MD_FunctionCategory) ){FText FuncCategory;// If we are not showing friendly names, return the metadata stored, without localizationif( GEditor !GetDefaultUEditorStyleSettings()-bShowFriendlyNames ){FuncCategory FText::FromString(Function-GetMetaData(FBlueprintMetadata::MD_FunctionCategory));}else{// Look for localized metadataFuncCategory FObjectEditorUtils::GetCategoryText(Function);// If the result is culture invariant, force it into a display stringif (FuncCategory.IsCultureInvariant()){FuncCategory FText::FromString(FName::NameToDisplayString(FuncCategory.ToString(), false));}}// Combine with the BaseCategory to form the full category, delimited by |if (!FuncCategory.IsEmpty() !NodeCategory.IsEmpty()){NodeCategory FText::Format(FText::FromString(TEXT({0}|{1})), NodeCategory, FuncCategory);}else if (NodeCategory.IsEmpty()){NodeCategory FuncCategory;}}return NodeCategory; }FText UK2Node_CallFunction::GetKeywordsForFunction(const UFunction* Function) {// If the friendly name and real function name do not match add the real function name friendly name as a keyword.FString Keywords;if( Function-GetName() ! GetUserFacingFunctionName(Function).ToString() ){Keywords Function-GetName();}if (ShouldDrawCompact(Function)){Keywords.AppendChar(TEXT( ));Keywords GetCompactNodeTitle(Function);}FText MetadataKeywords Function-GetMetaDataText(FBlueprintMetadata::MD_FunctionKeywords, TEXT(UObjectKeywords), Function-GetFullGroupName(false));FText ResultKeywords;if (!MetadataKeywords.IsEmpty()){FFormatNamedArguments Args;Args.Add(TEXT(Name), FText::FromString(Keywords));Args.Add(TEXT(MetadataKeywords), MetadataKeywords);ResultKeywords FText::Format(FText::FromString({Name} {MetadataKeywords}), Args);}else{ResultKeywords FText::FromString(Keywords);}return ResultKeywords; }void UK2Node_CallFunction::SetFromFunction(const UFunction* Function) {if (Function ! NULL){bIsPureFunc Function-HasAnyFunctionFlags(FUNC_BlueprintPure);bIsConstFunc Function-HasAnyFunctionFlags(FUNC_Const);DetermineWantsEnumToExecExpansion(Function);FunctionReference.SetFromFieldUFunction(Function, GetBlueprintClassFromNode());} }FString UK2Node_CallFunction::GetDocumentationLink() const {UClass* ParentClass NULL;if (FunctionReference.IsSelfContext()){if (HasValidBlueprint()){UFunction* Function FindUFieldUFunction(GetBlueprint()-GeneratedClass, FunctionReference.GetMemberName());if (Function ! NULL){ParentClass Function-GetOwnerClass();}} }else {ParentClass FunctionReference.GetMemberParentClass(GetBlueprintClassFromNode());}if (ParentClass ! NULL){return FString::Printf(TEXT(Shared/GraphNodes/Blueprint/%s%s), ParentClass-GetPrefixCPP(), *ParentClass-GetName());}return FString(Shared/GraphNodes/Blueprint/UK2Node_CallFunction); }FString UK2Node_CallFunction::GetDocumentationExcerptName() const {return FunctionReference.GetMemberName().ToString(); }FString UK2Node_CallFunction::GetDescriptiveCompiledName() const {return FString(TEXT(CallFunc_)) FunctionReference.GetMemberName().ToString(); }bool UK2Node_CallFunction::ShouldDrawCompact(const UFunction* Function) {return (Function ! NULL) Function-HasMetaData(FBlueprintMetadata::MD_CompactNodeTitle); }bool UK2Node_CallFunction::ShouldDrawCompact() const {UFunction* Function GetTargetFunction();return ShouldDrawCompact(Function); }bool UK2Node_CallFunction::ShouldDrawAsBead() const {return bIsBeadFunction; }bool UK2Node_CallFunction::ShouldShowNodeProperties() const {// Show node properties if this corresponds to a function graphif (FunctionReference.GetMemberName() ! NAME_None HasValidBlueprint()){return FindObjectUEdGraph(GetBlueprint(), *(FunctionReference.GetMemberName().ToString())) ! NULL;}return false; }FString UK2Node_CallFunction::GetCompactNodeTitle(const UFunction* Function) {static const FString ProgrammerMultiplicationSymbol TEXT(*);static const FString CommonMultiplicationSymbol TEXT(\xD7);static const FString ProgrammerDivisionSymbol TEXT(/);static const FString CommonDivisionSymbol TEXT(\xF7);static const FString ProgrammerConversionSymbol TEXT(-);static const FString CommonConversionSymbol TEXT(\x2022);const FString OperatorTitle Function-GetMetaData(FBlueprintMetadata::MD_CompactNodeTitle);if (!OperatorTitle.IsEmpty()){if (OperatorTitle ProgrammerMultiplicationSymbol){return CommonMultiplicationSymbol;}else if (OperatorTitle ProgrammerDivisionSymbol){return CommonDivisionSymbol;}else if (OperatorTitle ProgrammerConversionSymbol){return CommonConversionSymbol;}else{return OperatorTitle;}}return Function-GetName(); }FText UK2Node_CallFunction::GetCompactNodeTitle() const {UFunction* Function GetTargetFunction();if (Function ! NULL){return FText::FromString(GetCompactNodeTitle(Function));}else{return Super::GetCompactNodeTitle();} }void UK2Node_CallFunction::GetRedirectPinNames(const UEdGraphPin Pin, TArrayFString RedirectPinNames) const {Super::GetRedirectPinNames(Pin, RedirectPinNames);if (RedirectPinNames.Num() 0){const FString OldPinName RedirectPinNames[0];// first add functionname.paramRedirectPinNames.Add(FString::Printf(TEXT(%s.%s), *FunctionReference.GetMemberName().ToString(), *OldPinName));// if there is class, also add an option for class.functionname.paramUClass* FunctionClass FunctionReference.GetMemberParentClass(GetBlueprintClassFromNode());while (FunctionClass){RedirectPinNames.Add(FString::Printf(TEXT(%s.%s.%s), *FunctionClass-GetName(), *FunctionReference.GetMemberName().ToString(), *OldPinName));FunctionClass FunctionClass-GetSuperClass();}} }void UK2Node_CallFunction::FixupSelfMemberContext() {UBlueprint* Blueprint FBlueprintEditorUtils::FindBlueprintForNode(this);auto IsBlueprintOfType [Blueprint](UClass* ClassType)-bool{bool bIsChildOf Blueprint (Blueprint-GeneratedClass ! nullptr) Blueprint-GeneratedClass-IsChildOf(ClassType);if (!bIsChildOf Blueprint (Blueprint-SkeletonGeneratedClass)){bIsChildOf Blueprint-SkeletonGeneratedClass-IsChildOf(ClassType);}return bIsChildOf;};UClass* MemberClass FunctionReference.GetMemberParentClass();if (FunctionReference.IsSelfContext()){// if there is a function that matches the reference in the new context// and there are no connections to the self pin, we just want to call// that functionUEdGraphPin* SelfPin GetDefaultUEdGraphSchema_K2()-FindSelfPin(*this, EGPD_Input);if (!FunctionReference.ResolveMemberUFunction(Blueprint) || (SelfPin SelfPin-HasAnyConnections())){if (MemberClass nullptr){// the self pin may have type information stored on itif (SelfPin){MemberClass CastUClass(SelfPin-PinType.PinSubCategoryObject.Get());}}// if we happened to retain the ParentClass for a self reference // (unlikely), then we know where this node came from... lets keep it// referencing that functionif (MemberClass ! nullptr){if (!IsBlueprintOfType(MemberClass)){FunctionReference.SetExternalMember(FunctionReference.GetMemberName(), MemberClass);}}// else, there is nothing we can do... the node will produce an error later during compilation}}else if (MemberClass ! nullptr){if (IsBlueprintOfType(MemberClass)){FunctionReference.SetSelfMember(FunctionReference.GetMemberName());}} }void UK2Node_CallFunction::PostPasteNode() {Super::PostPasteNode();FixupSelfMemberContext();if (UFunction* Function GetTargetFunction()){if (Pins.Num() 0){// After pasting we need to go through and ensure the hidden the self pins is correct in case the source blueprint had different metadataTSetFName PinsToHide;FBlueprintEditorUtils::GetHiddenPinsForFunction(GetGraph(), Function, PinsToHide);const bool bShowWorldContextPin ((PinsToHide.Num() 0) GetBlueprint()-ParentClass-HasMetaDataHierarchical(FBlueprintMetadata::MD_ShowWorldContextPin));const FString DefaultToSelfMetaValue Function-GetMetaData(FBlueprintMetadata::MD_DefaultToSelf);const FString WorldContextMetaValue Function-GetMetaData(FBlueprintMetadata::MD_WorldContext);const UEdGraphSchema_K2* K2Schema GetDefaultUEdGraphSchema_K2();for (int32 PinIndex 0; PinIndex Pins.Num(); PinIndex){UEdGraphPin* Pin Pins[PinIndex];const FString PinNameStr Pin-PinName.ToString();const bool bIsSelfPin ((PinNameStr DefaultToSelfMetaValue) || (PinNameStr WorldContextMetaValue));const bool bPinShouldBeHidden ((Pin-SubPins.Num() 0) || (PinsToHide.Contains(Pin-PinName) (!bShowWorldContextPin || !bIsSelfPin)));if (bPinShouldBeHidden !Pin-bHidden){Pin-BreakAllPinLinks();K2Schema-SetPinAutogeneratedDefaultValueBasedOnType(Pin);}Pin-bHidden bPinShouldBeHidden;}}} }void UK2Node_CallFunction::PostDuplicate(bool bDuplicateForPIE) {Super::PostDuplicate(bDuplicateForPIE);if (!bDuplicateForPIE (!this-HasAnyFlags(RF_Transient))){FixupSelfMemberContext();} }void UK2Node_CallFunction::ValidateNodeDuringCompilation(class FCompilerResultsLog MessageLog) const {Super::ValidateNodeDuringCompilation(MessageLog);const UBlueprint* Blueprint GetBlueprint();UFunction *Function GetTargetFunction();if (Function NULL){FString OwnerName;if (Blueprint ! nullptr){OwnerName Blueprint-GetName();if (UClass* FuncOwnerClass FunctionReference.GetMemberParentClass(Blueprint-GeneratedClass)){OwnerName FuncOwnerClass-GetName();}}FString const FunctName FunctionReference.GetMemberName().ToString();FText const WarningFormat LOCTEXT(FunctionNotFoundFmt, Could not find a function named \{0}\ in {1}.\nMake sure {2} has been compiled for );MessageLog.Error(*FText::Format(WarningFormat, FText::FromString(FunctName), FText::FromString(OwnerName), FText::FromString(OwnerName)).ToString(), this);}else if (WantsExecPinsForParams(Function) bWantsEnumToExecExpansion false){// will technically not have a properly formatted output for multiple params... but /shrug. const FString EnumParamName GetAllExecParams(Function);MessageLog.Warning(*FText::Format(LOCTEXT(EnumToExecExpansionFailedFmt, Unable to find enum parameter with name {0} to expand for ), FText::FromString(EnumParamName)).ToString(), this);}const UClass* BlueprintClass Blueprint ? Blueprint-ParentClass : nullptr;const bool bIsEditorOnlyBlueprintBaseClass !BlueprintClass || IsEditorOnlyObject(BlueprintClass);// This error is disabled while we figure out how we can identify uncooked only// blueprints that want to make use of uncooked only APIs:#if 0const bool bIsUncookedOnlyFunction Function Function-GetOutermost()-HasAllPackagesFlags(PKG_UncookedOnly);if ( bIsUncookedOnlyFunction // Only allow calls to uncooked only functions from editor only/uncooked only// contexts:!( GetOutermost()-HasAnyPackageFlags(PKG_UncookedOnly|PKG_EditorOnly) ||bIsEditorOnlyBlueprintBaseClass )){MessageLog.Error(*LOCTEXT(UncookedOnlyError, Attempting to call uncooked only function in runtime blueprint).ToString(), this);}#endif //0// Ensure that editor module BP exposed UFunctions can only be called in blueprints for which the base class is also part of an editor module// Also check for functions wrapped in WITH_EDITOR if (Function Blueprint (IsEditorOnlyObject(Function) || Function-HasAnyFunctionFlags(FUNC_EditorOnly))){ if (!bIsEditorOnlyBlueprintBaseClass){FString const FunctName Function-GetName();FText const WarningFormat LOCTEXT(EditorFunctionFmt, Cannot use the editor function \{0}\ in this runtime Blueprint. Only for use in Editor Utility Blueprints and Blutilities.);MessageLog.Error(*FText::Format(WarningFormat, FText::FromString(FunctName)).ToString(), this);}}if (Function){// enforce UnsafeDuringActorConstruction keywordif (Function-HasMetaData(FBlueprintMetadata::MD_UnsafeForConstructionScripts)){// emit warning if we are in a construction scriptUEdGraph const* const Graph GetGraph();bool bNodeIsInConstructionScript UEdGraphSchema_K2::IsConstructionScript(Graph);if (bNodeIsInConstructionScript false){// IsConstructionScript() can return false if graph was cloned from the construction script// in that case, check the function entryTArrayconst UK2Node_FunctionEntry* EntryPoints;Graph-GetNodesOfClass(EntryPoints);if (EntryPoints.Num() 1){UK2Node_FunctionEntry const* const Node EntryPoints[0];if (Node){UFunction* const SignatureFunction Node-FunctionReference.ResolveMemberUFunction(Node-GetBlueprintClassFromNode());bNodeIsInConstructionScript SignatureFunction (SignatureFunction-GetFName() UEdGraphSchema_K2::FN_UserConstructionScript);}}}if ( bNodeIsInConstructionScript ){MessageLog.Warning(*LOCTEXT(FunctionUnsafeDuringConstruction, Function is unsafe to call in a construction script.).ToString(), this);}}// enforce WorldContext restrictionsconst bool bInsideBpFuncLibrary Blueprint (BPTYPE_FunctionLibrary Blueprint-BlueprintType);if (!bInsideBpFuncLibrary Function-HasMetaData(FBlueprintMetadata::MD_WorldContext) !Function-HasMetaData(FBlueprintMetadata::MD_CallableWithoutWorldContext)){check(Blueprint);UClass* ParentClass Blueprint-ParentClass;check(ParentClass);if (ParentClass !FBlueprintEditorUtils::ImplementsGetWorld(Blueprint) !ParentClass-HasMetaDataHierarchical(FBlueprintMetadata::MD_ShowWorldContextPin)){MessageLog.Warning(*LOCTEXT(FunctionUnsafeInContext, Function is unsafe to call from blueprints of class .).ToString(), this, ParentClass);}}if(Blueprint !FBlueprintEditorUtils::IsNativeSignature(Function)){// enforce protected function restrictionconst bool bCanTreatAsError Blueprint-GetLinkerCustomVersion(FFrameworkObjectVersion::GUID) FFrameworkObjectVersion::EnforceBlueprintFunctionVisibility;const bool bIsProtected (Function-FunctionFlags FUNC_Protected) ! 0;const bool bFuncBelongsToSubClass Blueprint-SkeletonGeneratedClass-IsChildOf(Function-GetOuterUClass());if (bIsProtected !bFuncBelongsToSubClass){if(bCanTreatAsError){MessageLog.Error(*LOCTEXT(FunctionProtectedAccessed, Function is protected and cant be accessed outside of its hierarchy.).ToString(), this);}else{MessageLog.Note(*LOCTEXT(FunctionProtectedAccessedNote, Function is protected and cant be accessed outside of its hierarchy - this will be an error if the asset is resaved.).ToString(), this);}}// enforce private function restrictionconst bool bIsPrivate (Function-FunctionFlags FUNC_Private) ! 0;const bool bFuncBelongsToClass bFuncBelongsToSubClass (Blueprint-SkeletonGeneratedClass Function-GetOuterUClass());if (bIsPrivate !bFuncBelongsToClass){if(bCanTreatAsError){MessageLog.Error(*LOCTEXT(FunctionPrivateAccessed, Function is private and cant be accessed outside of its defined class .).ToString(), this, Function-GetOuterUClass());}else{MessageLog.Note(*LOCTEXT(FunctionPrivateAccessedNote, Function is private and cant be accessed outside of its defined class - this will be an error if the asset is resaved.).ToString(), this, Function-GetOuterUClass());}}}}FDynamicOutputHelper::VerifyNode(this, MessageLog);for (UEdGraphPin* Pin : Pins){if (Pin Pin-PinType.bIsWeakPointer !Pin-PinType.IsContainer()){const FString ErrorString FText::Format(LOCTEXT(WeakPtrNotSupportedErrorFmt, Weak pointers are not supported as function parameters. Pin {0} ),FText::FromString(Pin-GetName())).ToString();MessageLog.Error(*ErrorString, this);}} }void UK2Node_CallFunction::Serialize(FArchive Ar) {Super::Serialize(Ar);Ar.UsingCustomVersion(FReleaseObjectVersion::GUID);if (Ar.IsLoading()){if (Ar.UE4Ver() VER_UE4_SWITCH_CALL_NODE_TO_USE_MEMBER_REFERENCE){UFunction* Function FindUFieldUFunction(CallFunctionClass_DEPRECATED, CallFunctionName_DEPRECATED);const bool bProbablySelfCall (CallFunctionClass_DEPRECATED NULL) || ((Function ! NULL) (Function-GetOuterUClass()-ClassGeneratedBy GetBlueprint()));FunctionReference.SetDirect(CallFunctionName_DEPRECATED, FGuid(), CallFunctionClass_DEPRECATED, bProbablySelfCall);}if(Ar.UE4Ver() VER_UE4_K2NODE_REFERENCEGUIDS){FGuid FunctionGuid;if (UBlueprint::GetGuidFromClassByFieldNameUFunction(GetBlueprint()-GeneratedClass, FunctionReference.GetMemberName(), FunctionGuid)){const bool bSelf FunctionReference.IsSelfContext();FunctionReference.SetDirect(FunctionReference.GetMemberName(), FunctionGuid, (bSelf ? NULL : FunctionReference.GetMemberParentClass((UClass*)NULL)), bSelf);}}// Consider the CPF_UObjectWrapper flag on native function call parameters and return values.if (Ar.CustomVer(FReleaseObjectVersion::GUID) FReleaseObjectVersion::PinTypeIncludesUObjectWrapperFlag){if (UFunction* TargetFunction GetTargetFunction()){if (TargetFunction-IsNative()){for (TFieldIteratorFProperty PropIt(TargetFunction); PropIt (PropIt-PropertyFlags CPF_Parm); PropIt){if (UEdGraphPin* Pin FindPin(PropIt-GetFName())){if (const FMapProperty* MapProperty CastFieldFMapProperty(*PropIt)){if (MapProperty-KeyProp MapProperty-KeyProp-HasAllPropertyFlags(CPF_UObjectWrapper)){Pin-PinType.bIsUObjectWrapper 1;}if (MapProperty-ValueProp MapProperty-ValueProp-HasAllPropertyFlags(CPF_UObjectWrapper)){Pin-PinType.PinValueType.bTerminalIsUObjectWrapper true;}}else if (const FSetProperty* SetProperty CastFieldFSetProperty(*PropIt)){if (SetProperty-ElementProp SetProperty-ElementProp-HasAllPropertyFlags(CPF_UObjectWrapper)){Pin-PinType.PinValueType.bTerminalIsUObjectWrapper true;}}else if(const FArrayProperty* ArrayProperty CastFieldFArrayProperty(*PropIt)){if(ArrayProperty-Inner ArrayProperty-Inner-HasAllPropertyFlags(CPF_UObjectWrapper)){Pin-PinType.PinValueType.bTerminalIsUObjectWrapper true;}}else if (PropIt-HasAllPropertyFlags(CPF_UObjectWrapper)){Pin-PinType.bIsUObjectWrapper 1;}}}}}}if (!Ar.IsObjectReferenceCollector()){// Dont validate the enabled state if the user has explicitly set it. Also skip validation if were just duplicating this node.const bool bIsDuplicating (Ar.GetPortFlags() PPF_Duplicate) ! 0;if (!bIsDuplicating !HasUserSetTheEnabledState()){if (const UFunction* Function GetTargetFunction()){// Enable as development-only if specified in metadata. This way existing functions that have the metadata added to them will get their enabled state fixed up on load.if (GetDesiredEnabledState() ENodeEnabledState::Enabled Function-HasMetaData(FBlueprintMetadata::MD_DevelopmentOnly)){SetEnabledState(ENodeEnabledState::DevelopmentOnly, /*bUserAction*/ false);}// Ensure that if the metadata is removed, we also fix up the enabled state to avoid leaving it set as development-only in that case.else if (GetDesiredEnabledState() ENodeEnabledState::DevelopmentOnly !Function-HasMetaData(FBlueprintMetadata::MD_DevelopmentOnly)){SetEnabledState(ENodeEnabledState::Enabled, /*bUserAction*/ false);}}}}} }void UK2Node_CallFunction::PostPlacedNewNode() {Super::PostPlacedNewNode();// Try re-setting the function given our new parent scope, in case it turns an external to an internal, or vis versaFunctionReference.RefreshGivenNewSelfScopeUFunction(GetBlueprintClassFromNode());// Set the node to development only if the function specifies thatcheck(!HasUserSetTheEnabledState());if (const UFunction* Function GetTargetFunction()){if (Function-HasMetaData(FBlueprintMetadata::MD_DevelopmentOnly)){SetEnabledState(ENodeEnabledState::DevelopmentOnly, /*bUserAction*/ false);}} }FNodeHandlingFunctor* UK2Node_CallFunction::CreateNodeHandler(FKismetCompilerContext CompilerContext) const {return new FKCHandler_CallFunction(CompilerContext); }void UK2Node_CallFunction::ExpandNode(class FKismetCompilerContext CompilerContext, UEdGraph* SourceGraph) {Super::ExpandNode(CompilerContext, SourceGraph);const UEdGraphSchema_K2* Schema CompilerContext.GetSchema();UFunction* Function GetTargetFunction();// connect DefaultToSelf and WorldContext inside static functions to proper self if (SourceGraph Schema-IsStaticFunctionGraph(SourceGraph) Function){TArrayUK2Node_FunctionEntry* EntryPoints;SourceGraph-GetNodesOfClass(EntryPoints);if (1 ! EntryPoints.Num()){CompilerContext.MessageLog.Warning(*FText::Format(LOCTEXT(WrongEntryPointsNumFmt, {0} entry points found while expanding node ), EntryPoints.Num()).ToString(), this);}else if (UEdGraphPin* BetterSelfPin EntryPoints[0]-GetAutoWorldContextPin()){const FString DefaultToSelfMetaValue Function-GetMetaData(FBlueprintMetadata::MD_DefaultToSelf);const FString WorldContextMetaValue Function-GetMetaData(FBlueprintMetadata::MD_WorldContext);struct FStructConnectHelper{static void Connect(const FString PinName, UK2Node* Node, UEdGraphPin* BetterSelf, const UEdGraphSchema_K2* InSchema, FCompilerResultsLog MessageLog){UEdGraphPin* Pin Node-FindPin(PinName);if (!PinName.IsEmpty() Pin !Pin-LinkedTo.Num()){const bool bConnected InSchema-TryCreateConnection(Pin, BetterSelf);if (!bConnected){MessageLog.Warning(*LOCTEXT(DefaultToSelfNotConnected, DefaultToSelf pin from node cannot be connected to ).ToString(), Pin, Node, BetterSelf);}}}};FStructConnectHelper::Connect(DefaultToSelfMetaValue, this, BetterSelfPin, Schema, CompilerContext.MessageLog);if (!Function-HasMetaData(FBlueprintMetadata::MD_CallableWithoutWorldContext)){FStructConnectHelper::Connect(WorldContextMetaValue, this, BetterSelfPin, Schema, CompilerContext.MessageLog);}}}// If we have an enum param that is expanded, we handle that firstif(bWantsEnumToExecExpansion){if(Function){TArrayFName EnumNamesToCheck;GetExpandEnumPinNames(Function, EnumNamesToCheck);bool bAlreadyHandleInput false;UEdGraphPin* OutMainExecutePin nullptr;UK2Node_ExecutionSequence* SpawnedSequenceNode nullptr;int32 OutSequenceIndex 0;const auto LinkIntoOutputChain [OutMainExecutePin, SpawnedSequenceNode, OutSequenceIndex, CompilerContext, this, SourceGraph, Schema](UK2Node* Node){if (!OutMainExecutePin){// Create normal exec output -- only once though.OutMainExecutePin CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);}else{// set up a sequence so we can call one after another.if (!SpawnedSequenceNode){SpawnedSequenceNode CompilerContext.SpawnIntermediateNodeUK2Node_ExecutionSequence(this, SourceGraph);SpawnedSequenceNode-AllocateDefaultPins();CompilerContext.MovePinLinksToIntermediate(*OutMainExecutePin, *SpawnedSequenceNode-GetThenPinGivenIndex(OutSequenceIndex));Schema-TryCreateConnection(OutMainExecutePin, SpawnedSequenceNode-Pins[0]);}}// Hook up execution to the branch nodeif (!SpawnedSequenceNode){Schema-TryCreateConnection(OutMainExecutePin, Node-GetExecPin());}else{UEdGraphPin* SequenceOutput SpawnedSequenceNode-GetThenPinGivenIndex(OutSequenceIndex);if (!SequenceOutput){SpawnedSequenceNode-AddInputPin();SequenceOutput SpawnedSequenceNode-GetThenPinGivenIndex(OutSequenceIndex);}Schema-TryCreateConnection(SequenceOutput, Node-GetExecPin());OutSequenceIndex;}};for (const FName EnumParamName : EnumNamesToCheck){UEnum* Enum nullptr;if (FByteProperty* ByteProp FindFPropertyFByteProperty(Function, EnumParamName)){Enum ByteProp-Enum;}else if (FEnumProperty* EnumProp FindFPropertyFEnumProperty(Function, EnumParamName)){Enum EnumProp-GetEnum();}UEdGraphPin* EnumParamPin FindPin(EnumParamName);if (Enum EnumParamPin){// Expanded as input execs pinsif (EnumParamPin-Direction EGPD_Input){if (bAlreadyHandleInput){CompilerContext.MessageLog.Error(TEXT( Already provided an input enum parameter for ExpandEnumAsExecs. Only one is permitted.), this);return;}bAlreadyHandleInput true;// Create normal exec inputUEdGraphPin* ExecutePin CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);// Create temp enum variableUK2Node_TemporaryVariable* TempEnumVarNode CompilerContext.SpawnIntermediateNodeUK2Node_TemporaryVariable(this, SourceGraph);TempEnumVarNode-VariableType.PinCategory UEdGraphSchema_K2::PC_Byte;TempEnumVarNode-VariableType.PinSubCategoryObject Enum;TempEnumVarNode-AllocateDefaultPins();// Get the output pinUEdGraphPin* TempEnumVarOutput TempEnumVarNode-GetVariablePin();// Connect temp enum variable to (hidden) enum pinSchema-TryCreateConnection(TempEnumVarOutput, EnumParamPin);// Now we want to iterate over other exec inputs...for (int32 PinIdx Pins.Num() - 1; PinIdx 0; PinIdx--){UEdGraphPin* Pin Pins[PinIdx];if (Pin ! NULL Pin ! ExecutePin Pin-Direction EGPD_Input Pin-PinType.PinCategory UEdGraphSchema_K2::PC_Exec){// Create node to set the temp enum varUK2Node_AssignmentStatement* AssignNode CompilerContext.SpawnIntermediateNodeUK2Node_AssignmentStatement(this, SourceGraph);AssignNode-AllocateDefaultPins();// Move connections from fake enum exec pint to this assignment nodeCompilerContext.MovePinLinksToIntermediate(*Pin, *AssignNode-GetExecPin());// Connect this to out temp enum varSchema-TryCreateConnection(AssignNode-GetVariablePin(), TempEnumVarOutput);// Connect exec output to real exec pinSchema-TryCreateConnection(AssignNode-GetThenPin(), ExecutePin);// set the literal enum value to set toAssignNode-GetValuePin()-DefaultValue Pin-PinName.ToString();// Finally remove this cosmetic exec pinPins[PinIdx]-MarkPendingKill();Pins.RemoveAt(PinIdx);}}}// Expanded as output execs pinselse if (EnumParamPin-Direction EGPD_Output){// Create a SwitchEnum node to switch on the output enumUK2Node_SwitchEnum* SwitchEnumNode CompilerContext.SpawnIntermediateNodeUK2Node_SwitchEnum(this, SourceGraph);UEnum* EnumObject CastUEnum(EnumParamPin-PinType.PinSubCategoryObject.Get());SwitchEnumNode-SetEnum(EnumObject);SwitchEnumNode-AllocateDefaultPins();LinkIntoOutputChain(SwitchEnumNode);// Connect (hidden) enum pin to switch nodes selection pinSchema-TryCreateConnection(EnumParamPin, SwitchEnumNode-GetSelectionPin());// Now we want to iterate over other exec outputs corresponding to the enum.// the first pins created are the ExpandEnumAsExecs pins, and theyre all made at the same time.for (int32 PinIdx Enum-NumEnums() - 2; PinIdx 0; PinIdx--){UEdGraphPin* Pin Pins[PinIdx];if (Pin Pin ! OutMainExecutePin Pin-Direction EGPD_Output Pin-PinType.PinCategory UEdGraphSchema_K2::PC_Exec){if (UEdGraphPin* FoundPin SwitchEnumNode-FindPin(Pin-PinName)){if (!FoundPin-LinkedTo.Contains(Pin)){// Move connections from fake enum exec pin to this switch nodeCompilerContext.MovePinLinksToIntermediate(*Pin, *FoundPin);// Finally remove this cosmetic exec pinPins[PinIdx]-MarkPendingKill();Pins.RemoveAt(PinIdx);}}// Have passed the relevant entries... no more work to do here.else{break;}}}}}else if(EnumParamPin !EnumParamPin-PinType.IsContainer() EnumParamPin-PinType.PinCategory UEdGraphSchema_K2::PC_Boolean){if (EnumParamPin-Direction EGPD_Input){// Create normal exec inputUEdGraphPin* ExecutePin CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);// Create temp bool variableUK2Node_TemporaryVariable* TempBoolVarNode CompilerContext.SpawnIntermediateNodeUK2Node_TemporaryVariable(this, SourceGraph);TempBoolVarNode-VariableType.PinCategory UEdGraphSchema_K2::PC_Boolean;TempBoolVarNode-AllocateDefaultPins();// Get the output pinUEdGraphPin* TempBoolVarOutput TempBoolVarNode-GetVariablePin();// Connect temp enum variable to (hidden) bool pinSchema-TryCreateConnection(TempBoolVarOutput, EnumParamPin);// create a true entry and a false:const auto CreateAssignNode [Schema, CompilerContext, this, SourceGraph, TempBoolVarOutput, ExecutePin](UEdGraphPin* FakePin, const TCHAR* DefaultValue){UK2Node_AssignmentStatement* AssignNode CompilerContext.SpawnIntermediateNodeUK2Node_AssignmentStatement(this, SourceGraph);AssignNode-AllocateDefaultPins();// Move connections from fake enum exec pint to this assignment nodeCompilerContext.MovePinLinksToIntermediate(*FakePin, *AssignNode-GetExecPin());// Connect this to out temp enum varSchema-TryCreateConnection(AssignNode-GetVariablePin(), TempBoolVarOutput);// Connect exec output to real exec pinSchema-TryCreateConnection(AssignNode-GetThenPin(), ExecutePin);// set the literal enum value to set toAssignNode-GetValuePin()-DefaultValue DefaultValue;};UEdGraphPin* TruePin FindPinChecked(TEXT(True), EEdGraphPinDirection::EGPD_Input);UEdGraphPin* FalsePin FindPinChecked(TEXT(False), EEdGraphPinDirection::EGPD_Input);CreateAssignNode(TruePin, TEXT(True));CreateAssignNode(FalsePin, TEXT(False));// remove fake false/true nodes:RemovePin(TruePin);RemovePin(FalsePin);}else if (EnumParamPin-Direction EGPD_Output){// Create a Branch node to switch on the output bool:UK2Node_IfThenElse* IfElseNode CompilerContext.SpawnIntermediateNodeUK2Node_IfThenElse(this, SourceGraph);IfElseNode-AllocateDefaultPins();LinkIntoOutputChain(IfElseNode);// Connect (hidden) bool pin to branch nodeSchema-TryCreateConnection(EnumParamPin, IfElseNode-GetConditionPin());UEdGraphPin* TruePin FindPinChecked(TEXT(True), EEdGraphPinDirection::EGPD_Output);UEdGraphPin* FalsePin FindPinChecked(TEXT(False), EEdGraphPinDirection::EGPD_Output);// move true connection to branch node:CompilerContext.MovePinLinksToIntermediate(*TruePin, *IfElseNode-GetThenPin());// move false connection to branch node:CompilerContext.MovePinLinksToIntermediate(*FalsePin, *IfElseNode-GetElsePin());// remove fake false/true nodes:RemovePin(TruePin);RemovePin(FalsePin);}}}}}// AUTO CREATED REFS{if ( Function ){TArrayFString AutoCreateRefTermPinNames;const bool bHasAutoCreateRefTerms Function-HasMetaData(FBlueprintMetadata::MD_AutoCreateRefTerm);if ( bHasAutoCreateRefTerms ){CompilerContext.GetSchema()-GetAutoEmitTermParameters(Function, AutoCreateRefTermPinNames);}for (UEdGraphPin* Pin : Pins){const bool bIsRefInputParam Pin Pin-PinType.bIsReference (Pin-Direction EGPD_Input) !CompilerContext.GetSchema()-IsMetaPin(*Pin);if (!bIsRefInputParam){continue;}const bool bHasConnections Pin-LinkedTo.Num() 0;const bool bCreateDefaultValRefTerm bHasAutoCreateRefTerms !bHasConnections AutoCreateRefTermPinNames.Contains(Pin-PinName.ToString());if (bCreateDefaultValRefTerm){const bool bHasDefaultValue !Pin-DefaultValue.IsEmpty() || Pin-DefaultObject || !Pin-DefaultTextValue.IsEmpty();// copy defaults as default values can be reset when the pin is connectedconst FString DefaultValue Pin-DefaultValue;UObject* DefaultObject Pin-DefaultObject;const FText DefaultTextValue Pin-DefaultTextValue;bool bMatchesDefaults Pin-DoesDefaultValueMatchAutogenerated();UEdGraphPin* ValuePin InnerHandleAutoCreateRef(this, Pin, CompilerContext, SourceGraph, bHasDefaultValue);if ( ValuePin ){if (bMatchesDefaults){// Use the latest code to set default valueSchema-SetPinAutogeneratedDefaultValueBasedOnType(ValuePin);}else{ValuePin-DefaultValue DefaultValue;ValuePin-DefaultObject DefaultObject;ValuePin-DefaultTextValue DefaultTextValue;}}}// since EX_Self does not produce an addressable (referenceable) FProperty, we need to shim// in a auto-ref term in its place (this emulates how UHT generates a local value for // native functions; hence the IsNative() check)else if (bHasConnections Pin-LinkedTo[0]-PinType.PinSubCategory UEdGraphSchema_K2::PSC_Self Pin-PinType.bIsConst !Function-IsNative()){InnerHandleAutoCreateRef(this, Pin, CompilerContext, SourceGraph, /*bForceAssignment */true);}}}}// Then we go through and expand out array iteration if necessaryconst bool bAllowMultipleSelfs AllowMultipleSelfs(true);UEdGraphPin* MultiSelf Schema-FindSelfPin(*this, EEdGraphPinDirection::EGPD_Input);if(bAllowMultipleSelfs MultiSelf !MultiSelf-PinType.IsArray()){const bool bProperInputToExpandForEach (1 MultiSelf-LinkedTo.Num()) (nullptr ! MultiSelf-LinkedTo[0]) (MultiSelf-LinkedTo[0]-PinType.IsArray());if(bProperInputToExpandForEach){CallForEachElementInArrayExpansion(this, MultiSelf, CompilerContext, SourceGraph);}} }UEdGraphPin* UK2Node_CallFunction::InnerHandleAutoCreateRef(UK2Node* Node, UEdGraphPin* Pin, FKismetCompilerContext CompilerContext, UEdGraph* SourceGraph, bool bForceAssignment) {const bool bAddAssigment !Pin-PinType.IsContainer() bForceAssignment;// ADD LOCAL VARIABLEUK2Node_TemporaryVariable* LocalVariable CompilerContext.SpawnIntermediateNodeUK2Node_TemporaryVariable(Node, SourceGraph);LocalVariable-VariableType Pin-PinType;LocalVariable-VariableType.bIsReference false;LocalVariable-AllocateDefaultPins();if (!bAddAssigment){if (!CompilerContext.GetSchema()-TryCreateConnection(LocalVariable-GetVariablePin(), Pin)){CompilerContext.MessageLog.Error(*LOCTEXT(AutoCreateRefTermPin_NotConnected, AutoCreateRefTerm Expansion: Pin cannot be connected to ).ToString(), LocalVariable-GetVariablePin(), Pin);return nullptr;}}// ADD ASSIGMENTelse{// TODO connect to dest..UK2Node_PureAssignmentStatement* AssignDefaultValue CompilerContext.SpawnIntermediateNodeUK2Node_PureAssignmentStatement(Node, SourceGraph);AssignDefaultValue-AllocateDefaultPins();const bool bVariableConnected CompilerContext.GetSchema()-TryCreateConnection(AssignDefaultValue-GetVariablePin(), LocalVariable-GetVariablePin());UEdGraphPin* AssignInputPit AssignDefaultValue-GetValuePin();const bool bPreviousInputSaved AssignInputPit CompilerContext.MovePinLinksToIntermediate(*Pin, *AssignInputPit).CanSafeConnect();const bool bOutputConnected CompilerContext.GetSchema()-TryCreateConnection(AssignDefaultValue-GetOutputPin(), Pin);if (!bVariableConnected || !bOutputConnected || !bPreviousInputSaved){CompilerContext.MessageLog.Error(*LOCTEXT(AutoCreateRefTermPin_AssignmentError, AutoCreateRefTerm Expansion: Assignment Error ).ToString(), AssignDefaultValue);return nullptr;}CompilerContext.GetSchema()-SetPinAutogeneratedDefaultValueBasedOnType(AssignDefaultValue-GetValuePin());return AssignInputPit;}return nullptr; }void UK2Node_CallFunction::CallForEachElementInArrayExpansion(UK2Node* Node, UEdGraphPin* MultiSelf, FKismetCompilerContext CompilerContext, UEdGraph* SourceGraph) {const UEdGraphSchema_K2* Schema CompilerContext.GetSchema();check(Node MultiSelf SourceGraph Schema);const bool bProperInputToExpandForEach (1 MultiSelf-LinkedTo.Num()) (NULL ! MultiSelf-LinkedTo[0]) (MultiSelf-LinkedTo[0]-PinType.IsArray());ensure(bProperInputToExpandForEach);UEdGraphPin* ThenPin Node-FindPinChecked(UEdGraphSchema_K2::PN_Then);// Create int IteratorUK2Node_TemporaryVariable* IteratorVar CompilerContext.SpawnIntermediateNodeUK2Node_TemporaryVariable(Node, SourceGraph);IteratorVar-VariableType.PinCategory UEdGraphSchema_K2::PC_Int;IteratorVar-AllocateDefaultPins();// Initialize iteratorUK2Node_AssignmentStatement* InteratorInitialize CompilerContext.SpawnIntermediateNodeUK2Node_AssignmentStatement(Node, SourceGraph);InteratorInitialize-AllocateDefaultPins();InteratorInitialize-GetValuePin()-DefaultValue TEXT(0);Schema-TryCreateConnection(IteratorVar-GetVariablePin(), InteratorInitialize-GetVariablePin());CompilerContext.MovePinLinksToIntermediate(*Node-GetExecPin(), *InteratorInitialize-GetExecPin());// Do loop branchUK2Node_IfThenElse* Branch CompilerContext.SpawnIntermediateNodeUK2Node_IfThenElse(Node, SourceGraph);Branch-AllocateDefaultPins();Schema-TryCreateConnection(InteratorInitialize-GetThenPin(), Branch-GetExecPin());CompilerContext.MovePinLinksToIntermediate(*ThenPin, *Branch-GetElsePin());// Do loop conditionUK2Node_CallFunction* Condition CompilerContext.SpawnIntermediateNodeUK2Node_CallFunction(Node, SourceGraph); Condition-SetFromFunction(UKismetMathLibrary::StaticClass()-FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UKismetMathLibrary, Less_IntInt)));Condition-AllocateDefaultPins();Schema-TryCreateConnection(Condition-GetReturnValuePin(), Branch-GetConditionPin());Schema-TryCreateConnection(Condition-FindPinChecked(TEXT(A)), IteratorVar-GetVariablePin());// Array sizeUK2Node_CallArrayFunction* ArrayLength CompilerContext.SpawnIntermediateNodeUK2Node_CallArrayFunction(Node, SourceGraph); ArrayLength-SetFromFunction(UKismetArrayLibrary::StaticClass()-FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UKismetArrayLibrary, Array_Length)));ArrayLength-AllocateDefaultPins();CompilerContext.CopyPinLinksToIntermediate(*MultiSelf, *ArrayLength-GetTargetArrayPin());ArrayLength-PinConnectionListChanged(ArrayLength-GetTargetArrayPin());Schema-TryCreateConnection(Condition-FindPinChecked(TEXT(B)), ArrayLength-GetReturnValuePin());// Get ElementUK2Node_CallArrayFunction* GetElement CompilerContext.SpawnIntermediateNodeUK2Node_CallArrayFunction(Node, SourceGraph); GetElement-SetFromFunction(UKismetArrayLibrary::StaticClass()-FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UKismetArrayLibrary, Array_Get)));GetElement-AllocateDefaultPins();CompilerContext.CopyPinLinksToIntermediate(*MultiSelf, *GetElement-GetTargetArrayPin());GetElement-PinConnectionListChanged(GetElement-GetTargetArrayPin());Schema-TryCreateConnection(GetElement-FindPinChecked(TEXT(Index)), IteratorVar-GetVariablePin());// Iterator incrementUK2Node_CallFunction* Increment CompilerContext.SpawnIntermediateNodeUK2Node_CallFunction(Node, SourceGraph); Increment-SetFromFunction(UKismetMathLibrary::StaticClass()-FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UKismetMathLibrary, Add_IntInt)));Increment-AllocateDefaultPins();Schema-TryCreateConnection(Increment-FindPinChecked(TEXT(A)), IteratorVar-GetVariablePin());Increment-FindPinChecked(TEXT(B))-DefaultValue TEXT(1);// Iterator assignedUK2Node_AssignmentStatement* IteratorAssign CompilerContext.SpawnIntermediateNodeUK2Node_AssignmentStatement(Node, SourceGraph);IteratorAssign-AllocateDefaultPins();Schema-TryCreateConnection(IteratorAssign-GetVariablePin(), IteratorVar-GetVariablePin());Schema-TryCreateConnection(IteratorAssign-GetValuePin(), Increment-GetReturnValuePin());Schema-TryCreateConnection(IteratorAssign-GetThenPin(), Branch-GetExecPin());// Connect pins from intermediate nodes back in to the original nodeSchema-TryCreateConnection(Branch-GetThenPin(), Node-GetExecPin());Schema-TryCreateConnection(ThenPin, IteratorAssign-GetExecPin());Schema-TryCreateConnection(GetElement-FindPinChecked(TEXT(Item)), MultiSelf); }FName UK2Node_CallFunction::GetCornerIcon() const {if (const UFunction* Function GetTargetFunction()){if (Function-HasAllFunctionFlags(FUNC_BlueprintAuthorityOnly)){return TEXT(Graph.Replication.AuthorityOnly); }else if (Function-HasAllFunctionFlags(FUNC_BlueprintCosmetic)){return TEXT(Graph.Replication.ClientEvent);}else if(Function-HasMetaData(FBlueprintMetadata::MD_Latent)){return TEXT(Graph.Latent.LatentIcon);}}return Super::GetCornerIcon(); }FSlateIcon UK2Node_CallFunction::GetIconAndTint(FLinearColor OutColor) const {return GetPaletteIconForFunction(GetTargetFunction(), OutColor); }bool UK2Node_CallFunction::ReconnectPureExecPins(TArrayUEdGraphPin* OldPins) {if (IsNodePure()){// look for an old exec pinUEdGraphPin* PinExec nullptr;for (int32 PinIdx 0; PinIdx OldPins.Num(); PinIdx){if (OldPins[PinIdx]-PinName UEdGraphSchema_K2::PN_Execute){PinExec OldPins[PinIdx];break;}}if (PinExec){PinExec-SetSavePinIfOrphaned(false); // look for old then pinUEdGraphPin* PinThen nullptr;for (int32 PinIdx 0; PinIdx OldPins.Num(); PinIdx){if (OldPins[PinIdx]-PinName UEdGraphSchema_K2::PN_Then){PinThen OldPins[PinIdx];break;}}if (PinThen){PinThen-SetSavePinIfOrphaned(false);// reconnect all incoming links to old exec pin to the far end of the old then pin.if (PinThen-LinkedTo.Num() 0){UEdGraphPin* PinThenLinked PinThen-LinkedTo[0];while (PinExec-LinkedTo.Num() 0){UEdGraphPin* PinExecLinked PinExec-LinkedTo[0];PinExecLinked-BreakLinkTo(PinExec);PinExecLinked-MakeLinkTo(PinThenLinked);}return true;}}}}return false; }void UK2Node_CallFunction::InvalidatePinTooltips() {bPinTooltipsValid false; }void UK2Node_CallFunction::ConformContainerPins() {// helper functions for type propagation:const auto TryReadTypeToPropagate [](UEdGraphPin* Pin, bool bOutPropagated, FEdGraphTerminalType TypeToPropagete){if (Pin !bOutPropagated){if (Pin-HasAnyConnections() || !Pin-DoesDefaultValueMatchAutogenerated() ){bOutPropagated true;if (Pin-LinkedTo.Num() ! 0){TypeToPropagete Pin-LinkedTo[0]-GetPrimaryTerminalType();}else{TypeToPropagete Pin-GetPrimaryTerminalType();}}}};const auto TryReadValueTypeToPropagate [](UEdGraphPin* Pin, bool bOutPropagated, FEdGraphTerminalType TypeToPropagete){if (Pin !bOutPropagated){if (Pin-LinkedTo.Num() ! 0 || !Pin-DoesDefaultValueMatchAutogenerated()){bOutPropagated true;if (Pin-LinkedTo.Num() ! 0){TypeToPropagete Pin-LinkedTo[0]-PinType.PinValueType;}else{TypeToPropagete Pin-PinType.PinValueType;}}}};const UEdGraphSchema_K2* Schema CastCheckedUEdGraphSchema_K2(GetSchema());const auto TryPropagateType [Schema](UEdGraphPin* Pin, const FEdGraphTerminalType TerminalType, bool bTypeIsAvailable){if(Pin){if(bTypeIsAvailable){const FEdGraphTerminalType PrimaryType Pin-GetPrimaryTerminalType();if( PrimaryType.TerminalCategory ! TerminalType.TerminalCategory ||PrimaryType.TerminalSubCategory ! TerminalType.TerminalSubCategory ||PrimaryType.TerminalSubCategoryObject ! TerminalType.TerminalSubCategoryObject){// terminal type changed:if (Pin-SubPins.Num() 0 Pin-PinType.PinCategory ! UEdGraphSchema_K2::PC_Wildcard){Schema-RecombinePin(Pin-SubPins[0]);}Pin-PinType.PinCategory TerminalType.TerminalCategory;Pin-PinType.PinSubCategory TerminalType.TerminalSubCategory;Pin-PinType.PinSubCategoryObject TerminalType.TerminalSubCategoryObject;// Also propagate the CPF_UObjectWrapper flag, which will be set for wrapped object ptr types (e.g. TSubclassOf).Pin-PinType.bIsUObjectWrapper TerminalType.bTerminalIsUObjectWrapper;// Reset default valuesif (!Schema-IsPinDefaultValid(Pin, Pin-DefaultValue, Pin-DefaultObject, Pin-DefaultTextValue).IsEmpty()){Schema-ResetPinToAutogeneratedDefaultValue(Pin, false);}}}else{// reset to wildcard:if (Pin-SubPins.Num() 0){Schema-RecombinePin(Pin-SubPins[0]);}Pin-PinType.PinCategory UEdGraphSchema_K2::PC_Wildcard;Pin-PinType.PinSubCategory NAME_None;Pin-PinType.PinSubCategoryObject nullptr;Pin-PinType.bIsUObjectWrapper false;Schema-ResetPinToAutogeneratedDefaultValue(Pin, false);}}};const auto TryPropagateValueType [](UEdGraphPin* Pin, const FEdGraphTerminalType TerminalType, bool bTypeIsAvailable){if (Pin){if (bTypeIsAvailable){Pin-PinType.PinValueType.TerminalCategory TerminalType.TerminalCategory;Pin-PinType.PinValueType.TerminalSubCategory TerminalType.TerminalSubCategory;Pin-PinType.PinValueType.TerminalSubCategoryObject TerminalType.TerminalSubCategoryObject;}else{Pin-PinType.PinValueType.TerminalCategory UEdGraphSchema_K2::PC_Wildcard;Pin-PinType.PinValueType.TerminalSubCategory NAME_None;Pin-PinType.PinValueType.TerminalSubCategoryObject nullptr;}}};const UFunction* TargetFunction GetTargetFunction();if (TargetFunction nullptr){return;}// find any pins marked as SetParamconst FString SetPinMetaData TargetFunction-GetMetaData(FBlueprintMetadata::MD_SetParam);// useless copies/allocates in this code, could be an optimization target...TArrayFString SetParamPinGroups;{SetPinMetaData.ParseIntoArray(SetParamPinGroups, TEXT(,), true);}for (FString Entry : SetParamPinGroups){// split the group:TArrayFString GroupEntries;Entry.ParseIntoArray(GroupEntries, TEXT(|), true);// resolve pinsTArrayUEdGraphPin* ResolvedPins;for(UEdGraphPin* Pin : Pins){if (GroupEntries.Contains(Pin-GetName())){ResolvedPins.Add(Pin);}}// if nothing is connected (or non-default), reset to wildcard// else, find the first type and propagate to everyone else::bool bReadyToPropagatSetType false;FEdGraphTerminalType TypeToPropagate;for (UEdGraphPin* Pin : ResolvedPins){TryReadTypeToPropagate(Pin, bReadyToPropagatSetType, TypeToPropagate);if(bReadyToPropagatSetType){break;}}for (UEdGraphPin* Pin : ResolvedPins){TryPropagateType( Pin, TypeToPropagate, bReadyToPropagatSetType );}}const FString MapPinMetaData TargetFunction-GetMetaData(FBlueprintMetadata::MD_MapParam);const FString MapKeyPinMetaData TargetFunction-GetMetaData(FBlueprintMetadata::MD_MapKeyParam);const FString MapValuePinMetaData TargetFunction-GetMetaData(FBlueprintMetadata::MD_MapValueParam);if(!MapPinMetaData.IsEmpty() || !MapKeyPinMetaData.IsEmpty() || !MapValuePinMetaData.IsEmpty() ){// if the map pin has a connection infer from that, otherwise use the information on the key param and value param:bool bReadyToPropagateKeyType false;FEdGraphTerminalType KeyTypeToPropagate;bool bReadyToPropagateValueType false;FEdGraphTerminalType ValueTypeToPropagate;UEdGraphPin* MapPin MapPinMetaData.IsEmpty() ? nullptr : FindPin(MapPinMetaData);UEdGraphPin* MapKeyPin MapKeyPinMetaData.IsEmpty() ? nullptr : FindPin(MapKeyPinMetaData);UEdGraphPin* MapValuePin MapValuePinMetaData.IsEmpty() ? nullptr : FindPin(MapValuePinMetaData);TryReadTypeToPropagate(MapPin, bReadyToPropagateKeyType, KeyTypeToPropagate);TryReadValueTypeToPropagate(MapPin, bReadyToPropagateValueType, ValueTypeToPropagate);TryReadTypeToPropagate(MapKeyPin, bReadyToPropagateKeyType, KeyTypeToPropagate);TryReadTypeToPropagate(MapValuePin, bReadyToPropagateValueType, ValueTypeToPropagate);TryPropagateType(MapPin, KeyTypeToPropagate, bReadyToPropagateKeyType);TryPropagateType(MapKeyPin, KeyTypeToPropagate, bReadyToPropagateKeyType);TryPropagateValueType(MapPin, ValueTypeToPropagate, bReadyToPropagateValueType);TryPropagateType(MapValuePin, ValueTypeToPropagate, bReadyToPropagateValueType);} }FText UK2Node_CallFunction::GetToolTipHeading() const {FText Heading Super::GetToolTipHeading();struct FHeadingBuilder{FHeadingBuilder(FText InitialHeading) : ConstructedHeading(InitialHeading) {}void Append(FText HeadingAddOn){if (ConstructedHeading.IsEmpty()){ConstructedHeading HeadingAddOn;}else {ConstructedHeading FText::Format(FText::FromString({0}\n{1}), HeadingAddOn, ConstructedHeading);}}FText ConstructedHeading;};FHeadingBuilder HeadingBuilder(Super::GetToolTipHeading());if (const UFunction* Function GetTargetFunction()){if (Function-HasAllFunctionFlags(FUNC_BlueprintAuthorityOnly)){HeadingBuilder.Append(LOCTEXT(ServerOnlyFunc, Server Only)); }if (Function-HasAllFunctionFlags(FUNC_BlueprintCosmetic)){HeadingBuilder.Append(LOCTEXT(ClientOnlyFunc, Client Only));}if(Function-HasMetaData(FBlueprintMetadata::MD_Latent)){HeadingBuilder.Append(LOCTEXT(LatentFunc, Latent));}}return HeadingBuilder.ConstructedHeading; }void UK2Node_CallFunction::GetNodeAttributes( TArrayTKeyValuePairFString, FString OutNodeAttributes ) const {UFunction* TargetFunction GetTargetFunction();const FString TargetFunctionName TargetFunction ? TargetFunction-GetName() : TEXT( InvalidFunction );OutNodeAttributes.Add( TKeyValuePairFString, FString( TEXT( Type ), TEXT( Function ) ));OutNodeAttributes.Add( TKeyValuePairFString, FString( TEXT( Class ), GetClass()-GetName() ));OutNodeAttributes.Add( TKeyValuePairFString, FString( TEXT( Name ), TargetFunctionName )); }FText UK2Node_CallFunction::GetMenuCategory() const {UFunction* TargetFunction GetTargetFunction();if (TargetFunction ! nullptr){return GetDefaultCategoryForFunction(TargetFunction, FText::GetEmpty());}return FText::GetEmpty(); }bool UK2Node_CallFunction::HasExternalDependencies(TArrayclass UStruct** OptionalOutput) const {UFunction* Function GetTargetFunction();const UClass* SourceClass Function ? Function-GetOwnerClass() : nullptr;const UBlueprint* SourceBlueprint GetBlueprint();bool bResult (SourceClass ! nullptr) (SourceClass-ClassGeneratedBy ! SourceBlueprint);if (bResult OptionalOutput){OptionalOutput-AddUnique(Function);}// All structures, that are required for the BP compilation, should be gatheredfor (UEdGraphPin* Pin : Pins){UStruct* DepStruct Pin ? CastUStruct(Pin-PinType.PinSubCategoryObject.Get()) : nullptr;UClass* DepClass CastUClass(DepStruct);if (DepClass (DepClass-ClassGeneratedBy SourceBlueprint)){//Dont include selfcontinue;}if (DepStruct !DepStruct-IsNative()){if (OptionalOutput){OptionalOutput-AddUnique(DepStruct);}bResult true;}}const bool bSuperResult Super::HasExternalDependencies(OptionalOutput);return bSuperResult || bResult; }UEdGraph* UK2Node_CallFunction::GetFunctionGraph(const UEdGraphNode* OutGraphNode) const {OutGraphNode nullptr;// Search for the Blueprint owner of the function graph, climbing up through the Blueprint hierarchyUClass* MemberParentClass FunctionReference.GetMemberParentClass(GetBlueprintClassFromNode());if(MemberParentClass ! nullptr){UBlueprintGeneratedClass* ParentClass CastUBlueprintGeneratedClass(MemberParentClass);if(ParentClass ! nullptr ParentClass-ClassGeneratedBy ! nullptr){UBlueprint* Blueprint CastUBlueprint(ParentClass-ClassGeneratedBy);while(Blueprint ! nullptr){UEdGraph* TargetGraph nullptr;const FName FunctionName FunctionReference.GetMemberName();for (UEdGraph* const Graph : Blueprint-FunctionGraphs) {if (Graph-GetFName() FunctionName){TargetGraph Graph;break;}}if (!TargetGraph){for (const FBPInterfaceDescription Interface : Blueprint-ImplementedInterfaces){for (UEdGraph* const Graph : Interface.Graphs){if (Graph-GetFName() FunctionName){TargetGraph Graph;break;}}if (TargetGraph){break;}}}if((TargetGraph ! nullptr) !TargetGraph-HasAnyFlags(RF_Transient)){// Found the function graph in a Blueprint, return that graphreturn TargetGraph;}else{// Did not find the function call as a graph, it may be a custom eventUK2Node_CustomEvent* CustomEventNode nullptr;TArrayUK2Node_CustomEvent* CustomEventNodes;FBlueprintEditorUtils::GetAllNodesOfClass(Blueprint, CustomEventNodes);for (UK2Node_CustomEvent* const CustomEvent : CustomEventNodes){if(CustomEvent-CustomFunctionName FunctionReference.GetMemberName()){OutGraphNode CustomEvent;return CustomEvent-GetGraph();}}}ParentClass CastUBlueprintGeneratedClass(Blueprint-ParentClass);Blueprint ParentClass ! nullptr ? CastUBlueprint(ParentClass-ClassGeneratedBy) : nullptr;}}}return nullptr; }bool UK2Node_CallFunction::IsStructureWildcardProperty(const UFunction* Function, const FName PropertyName) {if (Function !PropertyName.IsNone()){TArrayFString Names;FCustomStructureParamHelper::FillCustomStructureParameterNames(Function, Names);if (Names.Contains(PropertyName.ToString())){return true;}}return false; }bool UK2Node_CallFunction::IsWildcardProperty(const UFunction* InFunction, const FProperty* InProperty) {if (InProperty){return FEdGraphUtilities::IsSetParam(InFunction, InProperty-GetFName()) || FEdGraphUtilities::IsMapParam(InFunction, InProperty-GetFName());}return false; }void UK2Node_CallFunction::AddSearchMetaDataInfo(TArraystruct FSearchTagDataPair OutTaggedMetaData) const {Super::AddSearchMetaDataInfo(OutTaggedMetaData);if (UFunction* TargetFunction GetTargetFunction()){OutTaggedMetaData.Add(FSearchTagDataPair(FFindInBlueprintSearchTags::FiB_NativeName, FText::FromString(TargetFunction-GetName())));} }TSharedPtrSWidget UK2Node_CallFunction::CreateNodeImage() const {// For set, map and array functions we have a cool icon. This helps users quickly// identify container types:if (UFunction* TargetFunction GetTargetFunction()){UEdGraphPin* NodeImagePin FEdGraphUtilities::FindArrayParamPin(TargetFunction, this);NodeImagePin NodeImagePin ? NodeImagePin : FEdGraphUtilities::FindSetParamPin(TargetFunction, this);NodeImagePin NodeImagePin ? NodeImagePin : FEdGraphUtilities::FindMapParamPin(TargetFunction, this);if(NodeImagePin){// Find the first array param pin and bind that to our array image:return SPinTypeSelector::ConstructPinTypeImage(NodeImagePin);}}return TSharedPtrSWidget(); }UObject* UK2Node_CallFunction::GetJumpTargetForDoubleClick() const {// If there is an event node, jump to it, otherwise jump to the function graphconst UEdGraphNode* ResultEventNode nullptr;UEdGraph* FunctionGraph GetFunctionGraph(/*out*/ ResultEventNode);if (ResultEventNode ! nullptr){return const_castUEdGraphNode*(ResultEventNode);}else{return FunctionGraph;} }bool UK2Node_CallFunction::CanJumpToDefinition() const {const UFunction* TargetFunction GetTargetFunction();const bool bNativeFunction (TargetFunction ! nullptr) (TargetFunction-IsNative());return bNativeFunction || (GetJumpTargetForDoubleClick() ! nullptr); }void UK2Node_CallFunction::JumpToDefinition() const {// For native functions, try going to the function definition in C if availableif (UFunction* TargetFunction GetTargetFunction()){if (TargetFunction-IsNative()){// First try the nice way that will get to the right line numberbool bSucceeded false;const bool bNavigateToNativeFunctions GetDefaultUBlueprintEditorSettings()-bNavigateToNativeFunctionsFromCallNodes;if(bNavigateToNativeFunctions) {if(FSourceCodeNavigation::CanNavigateToFunction(TargetFunction)){bSucceeded FSourceCodeNavigation::NavigateToFunction(TargetFunction);}// Failing that, fall back to the older method which will still get the file open assuming it existsif (!bSucceeded){FString NativeParentClassHeaderPath;const bool bFileFound FSourceCodeNavigation::FindClassHeaderPath(TargetFunction, NativeParentClassHeaderPath) (IFileManager::Get().FileSize(*NativeParentClassHeaderPath) ! INDEX_NONE);if (bFileFound){const FString AbsNativeParentClassHeaderPath FPaths::ConvertRelativePathToFull(NativeParentClassHeaderPath);bSucceeded FSourceCodeNavigation::OpenSourceFile(AbsNativeParentClassHeaderPath);}}}else{ // Inform user that the function is native, give them opportunity to enable navigation to native// functions:FNotificationInfo Info(LOCTEXT(NavigateToNativeDisabled, Navigation to Native (c) Functions Disabled));Info.ExpireDuration 10.0f;Info.CheckBoxState bNavigateToNativeFunctions ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;Info.CheckBoxStateChanged FOnCheckStateChanged::CreateStatic([](ECheckBoxState NewState){const FScopedTransaction Transaction(LOCTEXT(ChangeNavigateToNativeFunctionsFromCallNodes, Change Navigate to Native Functions from Call Nodes Setting));UBlueprintEditorSettings* MutableEditorSetings GetMutableDefaultUBlueprintEditorSettings();MutableEditorSetings-Modify();MutableEditorSetings-bNavigateToNativeFunctionsFromCallNodes (NewState ECheckBoxState::Checked) ? true : false;MutableEditorSetings-SaveConfig();});Info.CheckBoxText LOCTEXT(EnableNavigationToNative, Navigate to Native Functions from Blueprint Call Nodes?);FSlateNotificationManager::Get().AddNotification(Info);}return;}}// Otherwise, fall back to the inherited behavior which should go to the function entry nodeSuper::JumpToDefinition(); }FString UK2Node_CallFunction::GetPinMetaData(FName InPinName, FName InKey) {FString MetaData Super::GetPinMetaData(InPinName, InKey);// If theres no metadata directly on the pin then check for metadata on the functionif (MetaData.IsEmpty()){if (UFunction* Function GetTargetFunction()){// Find the corresponding property for the pinif (FProperty* Property Function-FindPropertyByName(InPinName)){MetaData Property-GetMetaData(InKey);}}}return MetaData; }bool UK2Node_CallFunction::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString OutReason) const {bool bIsDisallowed Super::IsConnectionDisallowed(MyPin, OtherPin, OutReason);if (!bIsDisallowed MyPin ! nullptr){if (MyPin-bNotConnectable){bIsDisallowed true;OutReason LOCTEXT(PinConnectionDisallowed, This parameter is for internal use only.).ToString();}else if (UFunction* TargetFunction GetTargetFunction()){const bool bIsObjectType (MyPin-PinType.PinCategory UEdGraphSchema_K2::PC_Object ||MyPin-PinType.PinCategory UEdGraphSchema_K2::PC_SoftObject) (OtherPin-PinType.PinCategory UEdGraphSchema_K2::PC_Object ||OtherPin-PinType.PinCategory UEdGraphSchema_K2::PC_SoftObject);if (// Strictly speaking this first check is not needed, but by not disabling the connection here we get a better reason later:( OtherPin-PinType.IsContainer() // make sure we dont allow connections of mismatched container types (e.g. maps to arrays) (OtherPin-PinType.ContainerType ! MyPin-PinType.ContainerType) ((FEdGraphUtilities::IsSetParam(TargetFunction, MyPin-PinName) !MyPin-PinType.IsSet()) ||(FEdGraphUtilities::IsMapParam(TargetFunction, MyPin-PinName) !MyPin-PinType.IsMap()) ||(FEdGraphUtilities::IsArrayDependentParam(TargetFunction, MyPin-PinName) !MyPin-PinType.IsArray())))){bIsDisallowed true;OutReason LOCTEXT(PinSetConnectionDisallowed, Containers of containers are not supported - consider wrapping a container in a Structure object).ToString();}// Do not allow exec pins to be connected to a wildcard if this is a container functionelse if(MyPin-PinType.PinCategory UEdGraphSchema_K2::PC_Wildcard OtherPin-PinType.PinCategory UEdGraphSchema_K2::PC_Exec){bIsDisallowed true;OutReason LOCTEXT(PinExecConnectionDisallowed, Cannot create a container of Exec pins.).ToString();}else if (bIsObjectType MyPin-Direction EGPD_Input MyPin-PinType.IsContainer() OtherPin-PinType.IsContainer()){// Check that we can actually connect the dependent pins to this new arrayconst UEdGraphSchema_K2* K2Schema CastUEdGraphSchema_K2(GetSchema());// Gather all pins that would be dependent on on the container typeTArrayUEdGraphPin* DependentPins;{for (UEdGraphPin* Pin : Pins){if (Pin-Direction EGPD_Input Pin ! MyPin FEdGraphUtilities::IsDynamicContainerParam(TargetFunction, Pin-PinName)){DependentPins.Add(Pin);}}}for (UEdGraphPin* Pin : DependentPins){// If the pins are both containers, then ArePinTypesCompatible will fail incorrectly.if (OtherPin-PinType.ContainerType ! Pin-PinType.ContainerType){continue;}UClass* Context nullptr;UBlueprint* Blueprint GetBlueprint();if (Blueprint){Context Blueprint-GeneratedClass;}const bool ConnectResponse K2Schema-ArePinTypesCompatible(Pin-PinType, OtherPin-PinType, Context, /* bIgnoreArray */ true);if (!ConnectResponse){// For sets, we have to check if the other pin is a valid child that can actually // be connected in cases like the Union functionUStruct const* OutputObject (OtherPin-PinType.PinSubCategory UEdGraphSchema_K2::PSC_Self) ? Context : CastUStruct(OtherPin-PinType.PinSubCategoryObject.Get());UStruct const* InputObject (Pin-PinType.PinSubCategory UEdGraphSchema_K2::PSC_Self) ? Context : CastUStruct(Pin-PinType.PinSubCategoryObject.Get());if (OtherPin-PinType.IsSet() OutputObject InputObject OutputObject-IsChildOf(InputObject)){bIsDisallowed false;}else{// Display the necessary tooltip on the pin hover, and log it if we are compilingFFormatNamedArguments MessageArgs;MessageArgs.Add(TEXT(PinAType), UEdGraphSchema_K2::TypeToText(Pin-PinType));MessageArgs.Add(TEXT(PinBType), UEdGraphSchema_K2::TypeToText(OtherPin-PinType));UBlueprint* BP GetBlueprint();UEdGraph* OwningGraph GetGraph();OutReason FText::Format(LOCTEXT(DefaultPinIncompatibilityMessage, {PinAType} is not compatible with {PinBType}.), MessageArgs).ToString();return true;}}}}}}return bIsDisallowed; }
http://www.pierceye.com/news/127951/

相关文章:

  • 沈阳网站推广公司西安网站设计师
  • 网站建设费用计入什么二级科目企业门户网站建设的必要性
  • 宁夏水利厅建设管理处网站大连网站制作431
  • 泰安最好网站建设公司威海房地产网站建设
  • 公司网站建设网站说出网站建设流程
  • wordpress门户网站模板下载大专计算机专业主要学什么
  • 专业的微商城网站建设农产品网站建设计划书
  • 软件网站开发公司广告公司创意取名
  • 工业设计东莞网站建设个人网站备案网站名称
  • 网站只能用ip访问网站吗导航网站 win8风格
  • 用ps可以做网站吗制作一个网站流程
  • 做网站支付系统难度做灯笼手工简单做法
  • 合肥珍岛公司做网站推广怎么样用excel做网站
  • 大连网站建设开源广告制作行业
  • 安阳河南网站建设wordpress 建立导航
  • 电子商务网站建设 考卷wordpress替换头像
  • 石家庄的网站的公司手机wordpress加载图片慢
  • 建企业网站教程wordpress网站被黑
  • 饮料网站建设市场分析什么是seo网站优化
  • 滑动网站国家级示范建设网站
  • 做一门户网站价格个人网站制作模板图片
  • 做网站需要审核资质吗wordpress 防恶意注册
  • 怎么不花钱建网站无人售货机
  • 可以做空股票的网站thinkphp网站开发
  • 给别人做网站怎么赚钱吗专业网络推广软件
  • SOHO英文网站制作晋江网站制作
  • 启东住房和城乡建设局网站邢台网站制作报价多少钱
  • 佛山网站建设seo优化做英文的小说网站有哪些
  • 安顺建设局网站官网哪里有响应式网站企业
  • 唯品会一家做特卖的网站国家商标查询官方网站