UE蓝图 入口(FunctionEntry)节点和源码

系列文章目录

UE蓝图 Get节点和源码
UE蓝图 Set节点和源码
UE蓝图 Cast节点和源码
UE蓝图 分支(Branch)节点和源码
UE蓝图 入口(FunctionEntry)节点和源码


文章目录

  • 系列文章目录
  • 一、FunctionEntry节点功能
  • 二、入口节点用法
      • 1. 创建函数
      • 2. 命名函数
      • 3. 定义参数
      • 4. 编写函数逻辑
      • 5. 连接节点
      • 6. 返回值
      • 7. 调用函数
  • 三、使用场景
      • 1. 游戏逻辑处理
      • 2. 用户界面交互
      • 3. 系统功能实现
      • 4. 物理和碰撞处理
      • 5. 人工智能和机器学习
      • 6. 网络和多人游戏
      • 7. 工具和功能扩展
  • 四、实现过程
  • 五、相关源码


一、FunctionEntry节点功能

在UE(Unreal Engine)蓝图中,K2Node_FunctionEntry 是UE蓝图中函数或宏的入口节点,通常被称为“函数入口节点”或“FunctionEntry”。这个节点是一个事件节点,它标志着函数或宏的开始执行。当这个函数或宏被调用时,FunctionEntry 节点会被激活,从而触发函数或宏内部的逻辑执行。
在这里插入图片描述

K2Node_FunctionEntry 节点通常位于函数或宏的开始位置,并且只有一个指向函数或宏内部节点的白色箭头。当函数或宏被激活时,FunctionEntry 节点会按照连接流的顺序执行后续的节点。这意味着在函数或宏被调用后,首先会执行FunctionEntry 节点,然后按照连接关系依次执行后续的节点,直到函数或宏执行完毕。

二、入口节点用法

UE蓝图中的FunctionEntry节点是函数的起点,用于定义函数的行为和逻辑。以下是关于FunctionEntry节点用法的详细解释:
在这里插入图片描述

1. 创建函数

首先,在蓝图中创建一个新函数。这通常通过在蓝图编辑器中右键单击并选择“添加新函数”来完成。

2. 命名函数

为新函数提供一个有意义的名称,这将帮助你在后续的编程过程中更容易地识别和管理函数。

3. 定义参数

FunctionEntry节点中,你可以定义函数的输入和输出参数。输入参数是传递给函数的数据,而输出参数是函数处理完数据后返回的结果。

4. 编写函数逻辑

FunctionEntry节点下方,你可以开始添加执行函数所需的逻辑节点。这些节点可以是变量设置、条件判断、循环执行等。

5. 连接节点

使用白色箭头将节点连接起来,以定义数据流的顺序。例如,你可能将一个变量的值传递给一个运算节点,然后将运算结果传递给另一个节点。

6. 返回值

如果函数有输出参数或返回值,确保在函数的最后部分正确设置这些值。这样,当函数执行完毕时,调用者可以接收这些值。

7. 调用函数

要在蓝图的其他部分调用这个函数,你需要使用Call Function节点。将Call Function节点的输出连接到FunctionEntry节点,这样当Call Function节点被激活时,它将触发函数的执行。

三、使用场景

一些常见的FunctionEntry节点应用场景:

1. 游戏逻辑处理

在游戏开发中,FunctionEntry节点常被用于处理游戏逻辑,如玩家控制、敌人行为、碰撞检测等。通过将游戏逻辑分解为不同的函数,可以使代码更加清晰,便于调试和维护。

2. 用户界面交互

在创建用户界面(UI)时,FunctionEntry节点可以用于处理用户输入和界面交互。例如,当玩家点击一个按钮时,可以调用一个函数来处理相应的点击事件,如打开一个新的菜单或执行某个动作。

3. 系统功能实现

FunctionEntry节点也可以用于实现游戏中的各种系统功能,如保存和加载游戏进度、处理游戏设置、管理资源等。通过将这些功能分解为独立的函数,可以提高代码的可重用性和可维护性。

4. 物理和碰撞处理

在物理模拟和碰撞检测方面,FunctionEntry节点可以用于实现物理引擎的各种功能,如刚体运动、碰撞响应等。通过将物理模拟的逻辑分解为不同的函数,可以提高代码的可读性和性能。

5. 人工智能和机器学习

在涉及人工智能(AI)和机器学习(ML)的应用中,FunctionEntry节点可以用于实现复杂的算法和逻辑。例如,在路径规划、决策树、神经网络等方面,通过将算法分解为不同的函数,可以更容易地实现和调试这些高级功能。

6. 网络和多人游戏

在网络游戏和多人在线游戏中,FunctionEntry节点可以用于处理网络通信、玩家同步、状态更新等逻辑。通过将网络相关的逻辑分解为独立的函数,可以简化代码结构,提高游戏的稳定性和可扩展性。

7. 工具和功能扩展

此外,FunctionEntry节点还可以用于创建自定义的工具和功能扩展。例如,开发者可以创建自己的函数来处理特定的任务,如资源生成、场景编辑、调试工具等。

四、实现过程

  • 创建输入输出引脚
void UK2Node_FunctionEntry::AllocateDefaultPins()
{// Update our default values before copying them into pinsUpdateLoadedDefaultValues();CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);// Find any pins inherited from parentif (UFunction* Function = FunctionReference.ResolveMember<UFunction>(GetBlueprintClassFromNode())){CreatePinsForFunctionEntryExit(Function, /*bIsFunctionEntry=*/ true);}Super::AllocateDefaultPins();if (FFunctionEntryHelper::RequireWorldContextParameter(this) && ensure(!FindPin(FFunctionEntryHelper::GetWorldContextPinName()))){UEdGraphPin* WorldContextPin = CreatePin(EGPD_Output,UEdGraphSchema_K2::PC_Object,UObject::StaticClass(),FFunctionEntryHelper::GetWorldContextPinName());WorldContextPin->bHidden = true;}
}
  • 调用FKCHandler_FunctionEntry.RegisterNets注册Net

  • 调用Compile编译创建Statement

UK2Node_FunctionEntry* EntryNode = CastChecked<UK2Node_FunctionEntry>(Node);
if (EntryNode->FunctionReference.GetMemberName() == UEdGraphSchema_K2::FN_ExecuteUbergraphBase)
{UEdGraphPin* EntryPointPin = Node->FindPin(UEdGraphSchema_K2::PN_EntryPoint);FBPTerminal** pTerm = Context.NetMap.Find(EntryPointPin);if ((EntryPointPin != nullptr) && (pTerm != nullptr)){FBlueprintCompiledStatement& ComputedGotoStatement = Context.AppendStatementForNode(Node);ComputedGotoStatement.Type = KCST_ComputedGoto;ComputedGotoStatement.LHS = *pTerm;}
}
else
{// Generate the output impulse from this nodeGenerateSimpleThenGoto(Context, *Node);
}

五、相关源码

源码文件:
K2Node_FunctionEntry.h
K2Node_FunctionEntry.cpp
相关类:
FKCHandler_FunctionEntry
K2Node_FunctionEntry


class FKCHandler_FunctionEntry : public FNodeHandlingFunctor
{
public:FKCHandler_FunctionEntry(FKismetCompilerContext& InCompilerContext): FNodeHandlingFunctor(InCompilerContext){}void RegisterFunctionInput(FKismetFunctionContext& Context, UEdGraphPin* Net, UFunction* Function){// This net is a parameter into the functionFBPTerminal* Term = new FBPTerminal();Context.Parameters.Add(Term);Term->CopyFromPin(Net, Net->PinName);// Flag pass by reference parameters specially//@TODO: Still doesn't handle/allow users to declare new pass by reference, this only helps inherited functionsif( Function ){if (FProperty* ParentProperty = FindFProperty<FProperty>(Function, Net->PinName)){if (ParentProperty->HasAnyPropertyFlags(CPF_ReferenceParm)){Term->bPassedByReference = true;}}}Context.NetMap.Add(Net, Term);}virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override{UK2Node_FunctionEntry* EntryNode = CastChecked<UK2Node_FunctionEntry>(Node);UFunction* Function = EntryNode->FunctionReference.ResolveMember<UFunction>(EntryNode->GetBlueprintClassFromNode());// if this function has a predefined signature (like for inherited/overridden // functions), then we want to make sure to account for the output // parameters - this is normally handled by the FunctionResult node, but // we're not guaranteed that one is connected to the entry node if (Function && Function->HasAnyFunctionFlags(FUNC_HasOutParms)){const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();for (TFieldIterator<FProperty> ParamIt(Function, EFieldIteratorFlags::ExcludeSuper); ParamIt; ++ParamIt){FProperty* ParamProperty = *ParamIt;// mirrored from UK2Node_FunctionResult::CreatePinsForFunctionEntryExit()const bool bIsFunctionInput = !ParamProperty->HasAnyPropertyFlags(CPF_OutParm) || ParamProperty->HasAnyPropertyFlags(CPF_ReferenceParm);if (bIsFunctionInput){// continue;}FEdGraphPinType ParamType;if (K2Schema->ConvertPropertyToPinType(ParamProperty, ParamType)){FString ParamName = ParamProperty->GetName();bool bTermExists = false;// check to see if this terminal already exists (most // likely added by a FunctionResult node) - if so, then // we don't need to add it ourselvesfor (const FBPTerminal& ResultTerm : Context.Results){if (ResultTerm.Name == ParamName && ResultTerm.Type == ParamType){bTermExists = true;break;}}if (!bTermExists){// create a terminal that represents a output param // for this function; if there is a FunctionResult // node wired into our function graph, know that it// will first check to see if this already exists // for it to use (rather than creating one of its own)FBPTerminal* ResultTerm = new FBPTerminal();Context.Results.Add(ResultTerm);ResultTerm->Name = ParamName;ResultTerm->Type = ParamType;ResultTerm->bPassedByReference = ParamType.bIsReference;ResultTerm->SetContextTypeStruct(ParamType.PinCategory == UEdGraphSchema_K2::PC_Struct && Cast<UScriptStruct>(ParamType.PinSubCategoryObject.Get()));}}}}for (UEdGraphPin* Pin : Node->Pins){if (Pin->ParentPin == nullptr && !CompilerContext.GetSchema()->IsMetaPin(*Pin)){UEdGraphPin* Net = FEdGraphUtilities::GetNetFromPin(Pin);if (Context.NetMap.Find(Net) == nullptr){// New net, resolve the term that will be used to construct itFBPTerminal* Term = nullptr;check(Net->Direction == EGPD_Output);RegisterFunctionInput(Context, Pin, Function);}}}}virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override{UK2Node_FunctionEntry* EntryNode = CastChecked<UK2Node_FunctionEntry>(Node);//check(EntryNode->SignatureName != NAME_None);if (EntryNode->FunctionReference.GetMemberName() == UEdGraphSchema_K2::FN_ExecuteUbergraphBase){UEdGraphPin* EntryPointPin = Node->FindPin(UEdGraphSchema_K2::PN_EntryPoint);FBPTerminal** pTerm = Context.NetMap.Find(EntryPointPin);if ((EntryPointPin != nullptr) && (pTerm != nullptr)){FBlueprintCompiledStatement& ComputedGotoStatement = Context.AppendStatementForNode(Node);ComputedGotoStatement.Type = KCST_ComputedGoto;ComputedGotoStatement.LHS = *pTerm;}else{CompilerContext.MessageLog.Error(*LOCTEXT("NoEntryPointPin_Error", "Expected a pin named EntryPoint on @@").ToString(), Node);}}else{// Generate the output impulse from this nodeGenerateSimpleThenGoto(Context, *Node);}}virtual bool RequiresRegisterNetsBeforeScheduling() const override{return true;}
};struct FFunctionEntryHelper
{static const FName& GetWorldContextPinName(){static const FName WorldContextPinName(TEXT("__WorldContext"));return WorldContextPinName;}static bool RequireWorldContextParameter(const UK2Node_FunctionEntry* Node){const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();return K2Schema->IsStaticFunctionGraph(Node->GetGraph());}
};UK2Node_FunctionEntry::UK2Node_FunctionEntry(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer)
{// Enforce const-correctness by defaultbEnforceConstCorrectness = true;bUpdatedDefaultValuesOnLoad = false;bCanRenameNode = bIsEditable;
}void UK2Node_FunctionEntry::PreSave(const class ITargetPlatform* TargetPlatform)
{Super::PreSave(TargetPlatform);const UBlueprint* Blueprint = HasValidBlueprint() ? GetBlueprint() : nullptr;if (Blueprint && LocalVariables.Num() > 0){// Forcibly fixup defaults before we saveUpdateLoadedDefaultValues(true);}
}void UK2Node_FunctionEntry::PostLoad()
{Super::PostLoad();if (GIsEditor){// In the editor, we need to handle processing function default values at load time so they get picked up properly by the cooker// This normally won't do anything because it gets called during the duplicate save during BP compilation, but if compilation gets skipped we need to make sure they get updatedUpdateLoadedDefaultValues();}
}void UK2Node_FunctionEntry::Serialize(FArchive& Ar)
{Super::Serialize(Ar);Ar.UsingCustomVersion(FBlueprintsObjectVersion::GUID);if (Ar.IsSaving()){		if (Ar.IsObjectReferenceCollector() || Ar.Tell() < 0){// If this is explicitly a reference collector, or it's a save with no backing archive, then we want to use the function variable cache if it exists// It's not safe to regenerate the cache at this point as we could be in GIsSavingif (FunctionVariableCache.IsValid() && FunctionVariableCache->IsValid()){UStruct* Struct = const_cast<UStruct*>(FunctionVariableCache->GetStruct());Struct->SerializeBin(Ar, FunctionVariableCache->GetStructMemory());// Copy back into defaults as they may have changedUpdateDefaultsFromVariableStruct(FunctionVariableCache->GetStruct(), FunctionVariableCache->GetStructMemory());}}}else if (Ar.IsLoading()){if (Ar.CustomVer(FFrameworkObjectVersion::GUID) < FFrameworkObjectVersion::LocalVariablesBlueprintVisible){for (FBPVariableDescription& LocalVariable : LocalVariables){LocalVariable.PropertyFlags |= CPF_BlueprintVisible;}}if (Ar.UE4Ver() < VER_UE4_BLUEPRINT_ENFORCE_CONST_IN_FUNCTION_OVERRIDES|| ((Ar.CustomVer(FFrameworkObjectVersion::GUID) < FFrameworkObjectVersion::EnforceConstInAnimBlueprintFunctionGraphs) && GetBlueprint()->IsA<UAnimBlueprint>())){// Allow legacy implementations to violate const-correctnessbEnforceConstCorrectness = false;}if (Ar.CustomVer(FBlueprintsObjectVersion::GUID) < FBlueprintsObjectVersion::CleanBlueprintFunctionFlags){// Flags we explicitly use ExtraFlags for (at the time this fix was made)://     FUNC_Public, FUNC_Protected, FUNC_Private, //     FUNC_Static, FUNC_Const,//     FUNC_BlueprintPure, FUNC_BlueprintCallable, FUNC_BlueprintEvent, FUNC_BlueprintAuthorityOnly,//     FUNC_Net, FUNC_NetMulticast, FUNC_NetServer, FUNC_NetClient, FUNC_NetReliable// // FUNC_Exec, FUNC_Event, & FUNC_BlueprintCosmetic are all inherited // in FKismetCompilerContext::PrecompileFunction()static const uint32 InvalidExtraFlagsMask = FUNC_Final | FUNC_RequiredAPI | FUNC_BlueprintCosmetic |FUNC_NetRequest | FUNC_Exec | FUNC_Native | FUNC_Event | FUNC_NetResponse | FUNC_MulticastDelegate |FUNC_Delegate | FUNC_HasOutParms | FUNC_HasDefaults | FUNC_DLLImport | FUNC_NetValidate;ExtraFlags &= ~InvalidExtraFlagsMask;}if (Ar.CustomVer(FFrameworkObjectVersion::GUID) < FFrameworkObjectVersion::ChangeAssetPinsToString){const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();// Prior to this version, changing the type of a local variable would lead to corrupt default value stringsfor (FBPVariableDescription& LocalVar : LocalVariables){FString UseDefaultValue;UObject* UseDefaultObject = nullptr;FText UseDefaultText;if (!LocalVar.DefaultValue.IsEmpty()){K2Schema->GetPinDefaultValuesFromString(LocalVar.VarType, this, LocalVar.DefaultValue, UseDefaultValue, UseDefaultObject, UseDefaultText);FString ErrorMessage;if (!K2Schema->DefaultValueSimpleValidation(LocalVar.VarType, LocalVar.VarName, UseDefaultValue, UseDefaultObject, UseDefaultText, &ErrorMessage)){const UBlueprint* Blueprint = GetBlueprint();UE_LOG(LogBlueprint, Log, TEXT("Clearing invalid default value for local variable %s on blueprint %s: %s"), *LocalVar.VarName.ToString(), Blueprint ? *Blueprint->GetName() : TEXT("Unknown"), *ErrorMessage);LocalVar.DefaultValue.Reset();}}}}}
}FText UK2Node_FunctionEntry::GetNodeTitle(ENodeTitleType::Type TitleType) const
{UEdGraph* Graph = GetGraph();FGraphDisplayInfo DisplayInfo;Graph->GetSchema()->GetGraphDisplayInformation(*Graph, DisplayInfo);return DisplayInfo.DisplayName;
}void UK2Node_FunctionEntry::OnRenameNode(const FString& NewName)
{// Note: RenameGraph() will handle the rename operation for this node as well.FBlueprintEditorUtils::RenameGraph(GetGraph(), NewName);
}TSharedPtr<class INameValidatorInterface> UK2Node_FunctionEntry::MakeNameValidator() const
{if (CustomGeneratedFunctionName.IsNone()){FText TextName = GetNodeTitle(ENodeTitleType::Type::EditableTitle);return MakeShareable(new FKismetNameValidator(GetBlueprint(), *TextName.ToString()));}else{return MakeShareable(new FKismetNameValidator(GetBlueprint(), CustomGeneratedFunctionName));}
}bool UK2Node_FunctionEntry::GetCanRenameNode() const
{UEdGraph* const Graph = GetGraph();return (Graph && (Graph->bAllowDeletion || Graph->bAllowRenaming) && (bCanRenameNode || bIsEditable));
}void UK2Node_FunctionEntry::AllocateDefaultPins()
{// Update our default values before copying them into pinsUpdateLoadedDefaultValues();CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);// Find any pins inherited from parentif (UFunction* Function = FunctionReference.ResolveMember<UFunction>(GetBlueprintClassFromNode())){CreatePinsForFunctionEntryExit(Function, /*bIsFunctionEntry=*/ true);}Super::AllocateDefaultPins();if (FFunctionEntryHelper::RequireWorldContextParameter(this) && ensure(!FindPin(FFunctionEntryHelper::GetWorldContextPinName()))){UEdGraphPin* WorldContextPin = CreatePin(EGPD_Output,UEdGraphSchema_K2::PC_Object,UObject::StaticClass(),FFunctionEntryHelper::GetWorldContextPinName());WorldContextPin->bHidden = true;}
}UEdGraphPin* UK2Node_FunctionEntry::GetAutoWorldContextPin() const
{return FindPin(FFunctionEntryHelper::GetWorldContextPinName());
}void UK2Node_FunctionEntry::RemoveOutputPin(UEdGraphPin* PinToRemove)
{UK2Node_FunctionEntry* OwningSeq = Cast<UK2Node_FunctionEntry>( PinToRemove->GetOwningNode() );if (OwningSeq){PinToRemove->MarkPendingKill();OwningSeq->Pins.Remove(PinToRemove);}
}bool UK2Node_FunctionEntry::CanCreateUserDefinedPin(const FEdGraphPinType& InPinType, EEdGraphPinDirection InDesiredDirection, FText& OutErrorMessage)
{bool bResult = Super::CanCreateUserDefinedPin(InPinType, InDesiredDirection, OutErrorMessage);if (bResult){if(InDesiredDirection == EGPD_Input){OutErrorMessage = LOCTEXT("AddInputPinError", "Cannot add input pins to function entry node!");bResult = false;}}return bResult;
}UEdGraphPin* UK2Node_FunctionEntry::CreatePinFromUserDefinition(const TSharedPtr<FUserPinInfo> NewPinInfo)
{// Make sure that if this is an exec node we are allowed one.const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();if (NewPinInfo->PinType.PinCategory == UEdGraphSchema_K2::PC_Exec && !CanModifyExecutionWires()){return nullptr;}UEdGraphPin* NewPin = CreatePin(EGPD_Output, NewPinInfo->PinType, NewPinInfo->PinName);Schema->SetPinAutogeneratedDefaultValue(NewPin, NewPinInfo->PinDefaultValue);return NewPin;
}TSharedPtr<FStructOnScope> UK2Node_FunctionEntry::GetFunctionVariableCache(bool bForceRefresh)
{if (bForceRefresh && FunctionVariableCache.IsValid()){// On force refresh, delete old one if it existsFunctionVariableCache.Reset();}if (!FunctionVariableCache.IsValid() || !FunctionVariableCache->IsValid()){if (UFunction* const Function = FindSignatureFunction()){if (LocalVariables.Num() > 0){FunctionVariableCache = MakeShared<FStructOnScope>(Function);FunctionVariableCache->SetPackage(GetOutermost());RefreshFunctionVariableCache();}}}return FunctionVariableCache;
}bool UK2Node_FunctionEntry::RefreshFunctionVariableCache()
{GetFunctionVariableCache(false);if (FunctionVariableCache.IsValid()){// Update the cache if it was createdreturn UpdateVariableStructFromDefaults(FunctionVariableCache->GetStruct(), FunctionVariableCache->GetStructMemory());}return false;
}bool UK2Node_FunctionEntry::UpdateLoadedDefaultValues(bool bForceRefresh)
{// If we don't have a cache or it's force refresh, create oneif (!bUpdatedDefaultValuesOnLoad || bForceRefresh){GetFunctionVariableCache(bForceRefresh);bUpdatedDefaultValuesOnLoad = true;if (FunctionVariableCache.IsValid()){// Now copy back into the default value stringsreturn UpdateDefaultsFromVariableStruct(FunctionVariableCache->GetStruct(), FunctionVariableCache->GetStructMemory());}else{// No variable cache createdreturn true;}}return false;
}void UK2Node_FunctionEntry::ClearCachedBlueprintData(UBlueprint* Blueprint)
{FunctionVariableCache.Reset();
}bool UK2Node_FunctionEntry::UpdateVariableStructFromDefaults(const UStruct* VariableStruct, uint8* VariableStructData)
{const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();if (!VariableStruct || !VariableStructData){return false;}for (FBPVariableDescription& LocalVariable : LocalVariables){if (!LocalVariable.DefaultValue.IsEmpty()){FProperty* PinProperty = VariableStruct->FindPropertyByName(LocalVariable.VarName);if (PinProperty && (!PinProperty->HasAnyPropertyFlags(CPF_OutParm) || PinProperty->HasAnyPropertyFlags(CPF_ReferenceParm))){FEdGraphPinType PinType;K2Schema->ConvertPropertyToPinType(PinProperty, /*out*/ PinType);if (PinType != LocalVariable.VarType){//UE_LOG(LogBlueprint, Log, TEXT("Pin type for local variable %s does not match type on struct %s during UpdateVariableStructFromDefaults, ignoring old default"), *LocalVariable.VarName.ToString(), *VariableStruct->GetName());}else{FBlueprintEditorUtils::PropertyValueFromString(PinProperty, LocalVariable.DefaultValue, VariableStructData, this);}}else{//UE_LOG(LogBlueprint, Log, TEXT("Could not find local variable property %s on struct %s during UpdateVariableStructFromDefaults"), *LocalVariable.VarName.ToString(), *VariableStruct->GetName());}}}return true;
}bool UK2Node_FunctionEntry::UpdateDefaultsFromVariableStruct(const UStruct* VariableStruct, uint8* VariableStructData)
{const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();if (!VariableStruct || !VariableStructData){return false;}for (FBPVariableDescription& LocalVariable : LocalVariables){if (!LocalVariable.DefaultValue.IsEmpty()){// We don't want to write out fields that were empty before, as they were guaranteed to not have actual real dataFProperty* PinProperty = VariableStruct->FindPropertyByName(LocalVariable.VarName);if (PinProperty && (!PinProperty->HasAnyPropertyFlags(CPF_OutParm) || PinProperty->HasAnyPropertyFlags(CPF_ReferenceParm))){FEdGraphPinType PinType;K2Schema->ConvertPropertyToPinType(PinProperty, /*out*/ PinType);if (PinType != LocalVariable.VarType){//UE_LOG(LogBlueprint, Log, TEXT("Pin type for local variable %s does not match type on struct %s during UpdateDefaultsFromVariableStruct, ignoring old default"), *LocalVariable.VarName.ToString(), *VariableStruct->GetName());}else{FString NewValue;FBlueprintEditorUtils::PropertyValueToString(PinProperty, VariableStructData, NewValue, this);if (NewValue != LocalVariable.DefaultValue){LocalVariable.DefaultValue = NewValue;}}}else{//UE_LOG(LogBlueprint, Log, TEXT("Could not find local variable property %s on struct %s during UpdateDefaultsFromVariableStruct"), *LocalVariable.VarName.ToString(), *VariableStruct->GetName());}}}return true;
}FNodeHandlingFunctor* UK2Node_FunctionEntry::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
{return new FKCHandler_FunctionEntry(CompilerContext);
}void UK2Node_FunctionEntry::GetRedirectPinNames(const UEdGraphPin& Pin, TArray<FString>& RedirectPinNames) const
{Super::GetRedirectPinNames(Pin, RedirectPinNames);if(RedirectPinNames.Num() > 0){const FString OldPinName = RedirectPinNames[0];// first add functionname.paramconst FName SignatureName = FunctionReference.GetMemberName();RedirectPinNames.Add(FString::Printf(TEXT("%s.%s"), *SignatureName.ToString(), *OldPinName));// if there is class, also add an option for class.functionname.paramif(UClass const* SignatureClass = FunctionReference.GetMemberParentClass()){RedirectPinNames.Add(FString::Printf(TEXT("%s.%s.%s"), *SignatureClass->GetName(), *SignatureName.ToString(), *OldPinName));}}
}bool UK2Node_FunctionEntry::HasDeprecatedReference() const
{// We only show deprecated for inherited functionsif (UFunction* const Function = FunctionReference.ResolveMember<UFunction>(GetBlueprintClassFromNode())){return Function->HasMetaData(FBlueprintMetadata::MD_DeprecatedFunction);}else{return MetaData.bIsDeprecated;}
}FEdGraphNodeDeprecationResponse UK2Node_FunctionEntry::GetDeprecationResponse(EEdGraphNodeDeprecationType DeprecationType) const
{FEdGraphNodeDeprecationResponse Response = Super::GetDeprecationResponse(DeprecationType);if (DeprecationType == EEdGraphNodeDeprecationType::NodeHasDeprecatedReference){// Only warn on non-editable (i.e. override) usage.if (!IsEditable()){UFunction* const Function = FunctionReference.ResolveMember<UFunction>(GetBlueprintClassFromNode());if (ensureMsgf(Function != nullptr, TEXT("This node should not be able to report having a deprecated reference if the override function cannot be resolved."))){FText FunctionName = FText::FromName(FunctionReference.GetMemberName());FText DetailedMessage = FText::FromString(Function->GetMetaData(FBlueprintMetadata::MD_DeprecationMessage));Response.MessageText = FBlueprintEditorUtils::GetDeprecatedMemberUsageNodeWarning(FunctionName, DetailedMessage);}}else{// Allow the function to be marked as deprecated in the class that defines it without warning, but use a note to visually indicate that the definition itself has been deprecated.Response.MessageType = EEdGraphNodeDeprecationMessageType::Note;Response.MessageText = LOCTEXT("DeprecatedFunctionMessage", "@@: This function has been marked as deprecated. It can be safely deleted if all references have been replaced or removed.");}}return Response;
}FText UK2Node_FunctionEntry::GetTooltipText() const
{if (UFunction* const Function = FindSignatureFunction()){return FText::FromString(UK2Node_CallFunction::GetDefaultTooltipForFunction(Function));}return Super::GetTooltipText();
}void UK2Node_FunctionEntry::FindDiffs(UEdGraphNode* OtherNode, struct FDiffResults& Results)
{Super::FindDiffs(OtherNode, Results);UK2Node_FunctionEntry* OtherFunction = Cast<UK2Node_FunctionEntry>(OtherNode);if (OtherFunction){if (ExtraFlags != OtherFunction->ExtraFlags){FDiffSingleResult Diff;Diff.Diff = EDiffType::NODE_PROPERTY;Diff.Node1 = this;Diff.Node2 = OtherNode;Diff.DisplayString = LOCTEXT("DIF_FunctionFlags", "Function flags have changed");Diff.DisplayColor = FLinearColor(0.25f, 0.71f, 0.85f);Results.Add(Diff);}if (!FKismetUserDeclaredFunctionMetadata::StaticStruct()->CompareScriptStruct(&MetaData, &OtherFunction->MetaData, 0)){FDiffSingleResult Diff;Diff.Diff = EDiffType::NODE_PROPERTY;Diff.Node1 = this;Diff.Node2 = OtherNode;Diff.DisplayString = LOCTEXT("DIF_FunctionMetadata", "Function metadata has changed");Diff.DisplayColor = FLinearColor(0.25f, 0.71f, 0.85f);Results.Add(Diff);}bool bLocalVarsDiffer = (LocalVariables.Num() != OtherFunction->LocalVariables.Num());for (int32 i = 0; i < LocalVariables.Num() && !bLocalVarsDiffer; i++){const FBPVariableDescription& ThisVar = LocalVariables[i];const FBPVariableDescription& OtherVar = OtherFunction->LocalVariables[i];// Can't do a raw compare, for local variable defaults we need to compare the structif (ThisVar.VarName != OtherVar.VarName|| ThisVar.VarType != OtherVar.VarType|| ThisVar.FriendlyName != OtherVar.FriendlyName|| !ThisVar.Category.EqualTo(OtherVar.Category)|| ThisVar.PropertyFlags != OtherVar.PropertyFlags|| ThisVar.RepNotifyFunc != OtherVar.RepNotifyFunc|| ThisVar.ReplicationCondition != OtherVar.ReplicationCondition){bLocalVarsDiffer = true;}}if (bLocalVarsDiffer){FDiffSingleResult Diff;Diff.Diff = EDiffType::NODE_PROPERTY;Diff.Node1 = this;Diff.Node2 = OtherNode;Diff.DisplayString = LOCTEXT("DIF_FunctionLocalVariables", "Function local variables have changed in structure");Diff.DisplayColor = FLinearColor(0.25f, 0.71f, 0.85f);Results.Add(Diff);}else{TSharedPtr<FStructOnScope> MyLocals = GetFunctionVariableCache();TSharedPtr<FStructOnScope> OtherLocals = OtherFunction->GetFunctionVariableCache();if (MyLocals.IsValid() && MyLocals->IsValid() && OtherLocals.IsValid() && OtherLocals->IsValid()){// Check for local var diffsFDiffSingleResult Diff;Diff.Diff = EDiffType::NODE_PROPERTY;Diff.Node1 = this;Diff.Node2 = OtherNode;Diff.ToolTip = LOCTEXT("DIF_FunctionLocalVariableDefaults", "Function local variable default values have changed");Diff.DisplayColor = FLinearColor(0.25f, 0.71f, 0.85f);DiffProperties(const_cast<UStruct*>(MyLocals->GetStruct()), const_cast<UStruct*>(OtherLocals->GetStruct()), MyLocals->GetStructMemory(), OtherLocals->GetStructMemory(), Results, Diff);}}}
}bool UK2Node_FunctionEntry::IsCompatibleWithGraph(const UEdGraph* InGraph) const
{if (CanCreateUnderSpecifiedSchema(InGraph->GetSchema())){if (InGraph->GetSchema()->GetGraphType(InGraph) == GT_Function){TArray<UK2Node_FunctionEntry*> Nodes;InGraph->GetNodesOfClass<UK2Node_FunctionEntry>(Nodes);return Nodes.Num() == 0;}}return false;
}void UK2Node_FunctionEntry::PostPasteNode()
{Super::PostPasteNode();// If a function entry is being pasted, it should be editable in it's new graphbIsEditable = true;// ensure there are UserDefinedPins for all pins except the 'then' pinfor (int32 PinIdx = 1; PinIdx < Pins.Num(); ++PinIdx){UEdGraphPin* Pin = Pins[PinIdx];if (Pin && !UserDefinedPinExists(Pin->GetFName())){UserDefinedPins.Add(MakeShared<FUserPinInfo>(*Pin));}}ReconstructNode();
}int32 UK2Node_FunctionEntry::GetFunctionFlags() const
{int32 ReturnFlags = 0;if (UFunction* const Function = FunctionReference.ResolveMember<UFunction>(GetBlueprintClassFromNode())){ReturnFlags = Function->FunctionFlags;}return ReturnFlags | ExtraFlags;
}void UK2Node_FunctionEntry::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{Super::ExpandNode(CompilerContext, SourceGraph);const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();UEdGraphPin* OldStartExecPin = nullptr;if(Pins[0]->LinkedTo.Num()){OldStartExecPin = Pins[0]->LinkedTo[0];}UEdGraphPin* LastActiveOutputPin = Pins[0];// Only look for FunctionEntry nodes who were duplicated and have a source objectif ( UK2Node_FunctionEntry* OriginalNode = Cast<UK2Node_FunctionEntry>(CompilerContext.MessageLog.FindSourceObject(this)) ){check(OriginalNode->GetOuter());// Find the associated UFunctionUFunction* Function = FindUField<UFunction>(CompilerContext.Blueprint->SkeletonGeneratedClass, *OriginalNode->GetOuter()->GetName());// When regenerating on load, we may need to import text on certain properties to force load the assetsTSharedPtr<FStructOnScope> LocalVarData;if (Function && CompilerContext.Blueprint->bIsRegeneratingOnLoad){if (Function->GetStructureSize() > 0 || !ensure(Function->PropertyLink == nullptr)){LocalVarData = MakeShareable(new FStructOnScope(Function));}}for (TFieldIterator<FProperty> It(Function); It; ++It){if (const FProperty* Property = *It){const FStructProperty* PotentialUDSProperty = CastField<const FStructProperty>(Property);for (const FBPVariableDescription& LocalVar : LocalVariables){if (LocalVar.VarName == Property->GetFName() && !LocalVar.DefaultValue.IsEmpty()){// Add a variable set node for the local variable and hook it up immediately following the entry node or the last added local variableUK2Node_VariableSet* VariableSetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableSet>(this, SourceGraph);VariableSetNode->SetFromProperty(Property, false, Property->GetOwnerClass());Schema->ConfigureVarNode(VariableSetNode, LocalVar.VarName, Function, CompilerContext.Blueprint);VariableSetNode->AllocateDefaultPins();if(UEdGraphPin* SetPin = VariableSetNode->FindPin(Property->GetFName())){if(LocalVar.VarType.IsArray()){TSharedPtr<FStructOnScope> StructData = MakeShareable(new FStructOnScope(Function));FBlueprintEditorUtils::PropertyValueFromString(Property, LocalVar.DefaultValue, StructData->GetStructMemory());// Create a Make Array node to setup the array's defaultsUK2Node_MakeArray* MakeArray = CompilerContext.SpawnIntermediateNode<UK2Node_MakeArray>(this, SourceGraph);MakeArray->AllocateDefaultPins();MakeArray->GetOutputPin()->MakeLinkTo(SetPin);MakeArray->PostReconstructNode();const FArrayProperty* ArrayProperty = CastField<FArrayProperty>(Property);check(ArrayProperty);FScriptArrayHelper_InContainer ArrayHelper(ArrayProperty, StructData->GetStructMemory());FScriptArrayHelper_InContainer DefaultArrayHelper(ArrayProperty, StructData->GetStructMemory());// Go through each element in the array to set the default valuefor( int32 ArrayIndex = 0 ; ArrayIndex < ArrayHelper.Num() ; ArrayIndex++ ){uint8* PropData = ArrayHelper.GetRawPtr(ArrayIndex);// Retrieve the element's default valueFString DefaultValue;FBlueprintEditorUtils::PropertyValueToString(ArrayProperty->Inner, PropData, DefaultValue);if(ArrayIndex > 0){MakeArray->AddInputPin();}// Add one to the index for the pin to set the default on to skip the output pinSchema->TrySetDefaultValue(*MakeArray->Pins[ArrayIndex + 1], DefaultValue);}}else if(LocalVar.VarType.IsSet() || LocalVar.VarType.IsMap()){UK2Node_MakeVariable* MakeVariableNode = CompilerContext.SpawnIntermediateNode<UK2Node_MakeVariable>(this, SourceGraph);MakeVariableNode->SetupVariable(LocalVar, SetPin, CompilerContext, Function, Property);}else{if (CompilerContext.Blueprint->bIsRegeneratingOnLoad){// When regenerating on load, we want to force load assets referenced by local variables.// This functionality is already handled when generating Terms in the Kismet Compiler for Arrays and Structs, so we do not have to worry about them.if (LocalVar.VarType.PinCategory == UEdGraphSchema_K2::PC_Object || LocalVar.VarType.PinCategory == UEdGraphSchema_K2::PC_Class || LocalVar.VarType.PinCategory == UEdGraphSchema_K2::PC_Interface){FBlueprintEditorUtils::PropertyValueFromString(Property, LocalVar.DefaultValue, LocalVarData->GetStructMemory());}}// Set the default valueSchema->TrySetDefaultValue(*SetPin, LocalVar.DefaultValue);}}LastActiveOutputPin->BreakAllPinLinks();LastActiveOutputPin->MakeLinkTo(VariableSetNode->Pins[0]);LastActiveOutputPin = VariableSetNode->Pins[1];}}}}// Finally, hook up the last node to the old node the function entry node was connected toif(OldStartExecPin){LastActiveOutputPin->MakeLinkTo(OldStartExecPin);}}
}void UK2Node_FunctionEntry::PostReconstructNode()
{Super::PostReconstructNode();
}void UK2Node_FunctionEntry::FixupPinStringDataReferences(FArchive* SavingArchive)
{Super::FixupPinStringDataReferences(SavingArchive);if (SavingArchive){UpdateUserDefinedPinDefaultValues();}
}bool UK2Node_FunctionEntry::ModifyUserDefinedPinDefaultValue(TSharedPtr<FUserPinInfo> PinInfo, const FString& NewDefaultValue)
{if (Super::ModifyUserDefinedPinDefaultValue(PinInfo, NewDefaultValue)){const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();K2Schema->HandleParameterDefaultValueChanged(this);RefreshFunctionVariableCache();return true;}return false;
}bool UK2Node_FunctionEntry::ShouldUseConstRefParams() const
{// Interface functions with no outputs will be implemented as events. As with native interface functions with no outputs, the entry// node is expected to use 'const Type&' for input parameters that are passed by reference. See UEditablePinBase::PostLoad() for details.if (const UEdGraph* OwningGraph = GetGraph()){const UBlueprint* OwningBlueprint = FBlueprintEditorUtils::FindBlueprintForGraph(OwningGraph);if (OwningBlueprint && OwningBlueprint->BlueprintType == BPTYPE_Interface){// Find paired result node and check for outputs.for (UEdGraphNode* Node : OwningGraph->Nodes){if (UK2Node_FunctionResult* ResultNode = Cast<UK2Node_FunctionResult>(Node)){// This might be called from the super's Serialize() method for older assets, so make sure the result node's pins have been loaded.if (ResultNode->HasAnyFlags(RF_NeedLoad)){GetLinker()->Preload(ResultNode);}return ResultNode->UserDefinedPins.Num() == 0;}}// No result node, so there are no outputs.return true;}}return false;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/695176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git合并固定分支的某一部分至当前分支

在 Git 中&#xff0c;通常使用 git merge 命令来将一个分支的更改合并到另一个分支。如果你只想合并某个分支的一部分代码&#xff0c;可以使用以下两种方法&#xff1a; 1.批量文件合并 1.1.创建并切换到一个新的临时分支 首先&#xff0c;从要合并的源分支&#xff08;即要…

C++面向对象程序设计-北京大学-郭炜【课程笔记(四)】

C面向对象程序设计-北京大学-郭炜【课程笔记&#xff08;四&#xff09;】 1、this指针1.1、this指针的作用1.2、this指针和静态成员函数 2、静态成员变量和静态成员函数2.1、基本概念2.2、基本概念总结2.3、如何访问静态成员2.4、静态成员变量的使用场景&#xff08;重要&…

浏览器---浏览器/http相关面试题

1.localStorage和sessionStorage 共同点&#xff1a;二者都是以key-value的键值对方式存储在浏览器端&#xff0c;大小大概在5M。 区别&#xff1a; &#xff08;1&#xff09;数据有效期不同&#xff1a;sessionStorage仅在当前浏览器窗口关闭之前有效&#xff1b;localStorag…

Eigen:Vector3d 变量初始化遇到的问题

Eigen:Vector3d 变量初始化遇到的问题 2024.2.22 日 &#xff0c;在使用 Eigen:Vector3d 这个类型的 变量&#xff0c;在类中进行初始化时 遇到了如下问题&#xff1a; 首先在类的声明内部&#xff0c;是不能声明完&#xff0c;再给变量赋值的&#xff0c;不管是 Eigen:Vector…

【 Flutter】安装、运行坑记录

运行demo报错 Exception in thread “main” java.net.ConnectException: Connection timed out: connect原因&#xff1a;网络问题&#xff0c;gradle包未能下载 解决方案&#xff1a;配置android studio代理&#xff0c;重新打开项目&#xff0c;as会自动下载缺失依赖

(done) 如何判断一个矩阵是否可逆?

参考视频&#xff1a;https://www.bilibili.com/video/BV15H4y1y737/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 这个视频里还暗含了一些引理 1.若 AX XB 且 X 和 A,B 同阶可逆&#xff0c;那么 A 和 B 相似。原因&#xff1…

安卓开发:挑战每天发布一个封装类02--Wav录音封装类AudioChannel 1.0

简介 库名称&#xff1a;AudioChannel 版本:1.0 由于项目需求录音并base64编码存到服务器中&#xff0c;就顺手改装了一个别人的封装类 原封装类地址:Android AudioRecord音频录制wav文件输出 - 简书 (jianshu.com) 描述&#xff1a;此封装类基于AudioRecord实现wav的音频…

WEB相关工具(wget、curl、ab)

目录 一、wget 1、wget基本语法 2、wget帮助的更多选项 二、curl 1、curl基本语法 2、curl命令下载 3、curl命令基本用法 3.1 curl伪装 3.2 提取状态码 3.3 提取本地IP地址 3.4 提取远端服务器IP地址 3.5 提取本地端口 3.6 提取远端服务器端口 三、压力测试工具…

Unity xLua开发环境搭建与基础进阶

Unity是一款非常流行的游戏开发引擎&#xff0c;而xLua是一个为Unity开发者提供的Lua框架&#xff0c;可以让开发者使用Lua语言来进行游戏开发。在本文中&#xff0c;我们将介绍如何搭建Unity xLua开发环境&#xff0c;并进行基础进阶的学习。 环境搭建 首先&#xff0c;我们需…

高维数据的中介效应【中介分析】《R包:HIMA》

允许基于高级中介筛选和惩罚回归技术来估计和测试高维中介效应 Hima包浏览 高维中介示意图 图1. 在暴露和结果之间有高维中介的情况 本包的作用 在确定独立筛选和极小极大凹惩罚技术的基础上&#xff0c;采用联合显著性检验方法对调解效果进行检验。使用蒙特卡罗模拟研究来展…

Python爬虫实战入门:爬取360模拟翻译(仅实验)

文章目录 需求所需第三方库requests 实战教程打开网站抓包添加请求头等信息发送请求&#xff0c;解析数据修改翻译内容以及实现中英互译 完整代码 需求 目标网站&#xff1a;https://fanyi.so.com/# 要求&#xff1a;爬取360翻译数据包&#xff0c;实现翻译功能 所需第三方库 …

2024什么样的大路灯比较好?5大爆款落地灯推荐必看!

大路灯作为一个可以照明&#xff0c;让室内环境光线更加舒适的电器&#xff0c;能够减少用眼时不良光线带来的疲劳感&#xff0c;营造接近自然光的舒适光&#xff0c;受到很多家长的关注&#xff01; 但现在市面有很多不良商家推出的大路灯虚标参数&#xff0c;实际护眼性能很低…

线性代数:向量空间

目录 向量空间 Ax 0 的解空间S Ax b 的全体解向量所构成集合不是向量空间 基、维数、子空间 自然基与坐标 例1 例2 向量空间 Ax 0 的解空间S Ax b 的全体解向量所构成集合不是向量空间 基、维数、子空间 自然基与坐标 例1 例2

vue中使用AraleQRCode生成二维码

vue中使用AraleQRCode生成二维码 问题背景 本文介绍vue中生成二维码的一种方案&#xff0c;使用AraleQRCode来实现。 问题分析 &#xff08;1&#xff09;安装对应的依赖包 npm i arale-qrcode --save &#xff08;2&#xff09;完整代码如下: <template><!-…

解决docker中运行的jar包连不上前端程序

目录 检查端口映射 查看容器的 IP 地址 检查容器网络设置 防火墙和网络策略 前端程序配置 跨域资源共享 (CORS) 日志查看 连接问题通常涉及到网络配置和端口映射。确保你在 Docker 中运行的 JAR 包可以被前端程序访问&#xff0c;可以采取以下步骤来解决问题&#xff1a…

ATCoder Beginnner Contest 341 A~G

A.Print 341&#xff08;模拟&#xff09; 题意&#xff1a; 给定一个正整数 N N N&#xff0c;输出由 N N N个0和 ( N 1 ) (N1) (N1)个1交替组成的字符串。 分析&#xff1a; 按题意模拟即可 代码&#xff1a; #include<bits/stdc.h>using namespace std;int mai…

猫咪不喝水是什么原因?这些方法远离缺水小猫

有经验的铲屎官都知道&#xff0c;家里的猫似乎不太喜欢喝水。只看到一只或两只猫不喝水&#xff0c;那可能是例外情况。但绝大部分的猫都不咋爱喝水&#xff0c;这是为什么呢&#xff1f; 一、猫咪不喝水是什么原因&#xff1f; 如果你已经尝试了各种方法来让猫咪多喝水&…

合并Windows电脑的不同分区(不同的盘)的方法

本文介绍在Windows操作系统的电脑中&#xff0c;将磁盘上的不同分区&#xff08;例如E盘与F盘&#xff09;加以合并的方法。 最近&#xff0c;想着将新电脑的2个分区加以合并&#xff1b;如下图所示&#xff0c;希望将E盘与F盘合并为一个分区。本文就介绍一下实现这一需求的具体…

微服务篇之监控

一、为什么要监控 1.问题定位 假设客户端查询一些东西的时候&#xff0c;需要经过网关&#xff0c;然后服务A调用服务H&#xff0c;服务H调用K&#xff0c;服务K调用MySQL&#xff0c;当查询不出来的时候&#xff0c;我们不能快速定位到底是哪个服务的问题&#xff0c;这就需要…

【前端】夯实基础 css/html/js 50个练手项目(持续更新)

文章目录 前言Day 1 expanding-cardsDay 2 progress-steps 前言 发现一个没有用前端框架的练手项目&#xff0c;很适合我这种纯后端开发夯实基础&#xff0c;内含50个mini project&#xff0c;学习一下&#xff0c;做做笔记。 项目地址&#xff1a;https://github.com/bradtr…