UE Get节点和源码

文章目录

    • 概要
    • UE Get节点有哪些常见的应用场景
    • 相关源码

概要

UE Get节点在Unreal Engine的蓝图系统中用于获取变量的值。这个节点通常用于从变量中读取数据,以便在游戏的逻辑流程中使用。

要使用Get节点,你首先需要有一个已经定义的变量。然后,在蓝图编辑器中,你可以通过右键点击空白处,选择“添加节点” -> “变量” -> “Get”来创建一个Get节点。在弹出的窗口中,你可以选择需要获取的变量。一旦创建了Get节点,你可以将其拖拽到蓝图的适当位置,并连接它到需要使用该变量值的其他节点。
在这里插入图片描述

需要注意的是,Get节点只是获取变量的值,而不会修改它。如果你想修改变量的值,你应该使用Set节点。

Get节点的输出可以用于驱动蓝图中的其他逻辑或操作。例如,你可以使用Get节点获取一个游戏对象的位置,然后根据这个位置来执行某些动作或决策。

总的来说,UE Get节点是Unreal Engine蓝图系统中用于读取变量值的重要工具,它使得开发者能够灵活地获取和使用游戏中的数据。

UE Get节点有哪些常见的应用场景

UE Get节点在Unreal Engine的蓝图系统中主要用于获取变量的值,这些变量可以是游戏对象的状态、属性、配置参数等。由于Get节点能够动态地获取变量的值,因此它在多种场景中都有广泛的应用。以下是一些UE Get节点常见的应用场景:

动态调整游戏对象的行为:通过Get节点获取游戏对象的某些属性(如位置、速度、旋转等),然后根据这些属性的值动态调整游戏对象的行为。例如,根据玩家的位置调整敌人的攻击策略,或者根据物体的速度调整其移动方式。
实现条件判断和分支逻辑:结合Branch节点或其他控制流节点,使用Get节点获取变量的值来进行条件判断。根据判断结果,执行不同的逻辑分支。这在构建复杂的游戏逻辑和交互中非常常见。
同步多个游戏对象的状态:在某些情况下,你可能需要确保多个游戏对象保持同步的状态。通过Get节点获取一个游戏对象的状态,并使用Set节点将其应用到其他游戏对象上,可以实现状态的同步和一致性。
响应用户输入和事件:在事件驱动的游戏逻辑中,Get节点可以用于获取用户输入或事件触发的变量值。例如,当用户按下某个按钮时,通过Get节点获取按钮状态的值,并据此执行相应的操作或响应。
配置管理和动态加载:在游戏开发过程中,可能需要根据不同的配置或参数来调整游戏的行为。通过Get节点获取配置文件或参数表中的变量值,可以实现游戏行为的动态加载和调整。
需要注意的是,虽然Get节点在多种场景中都有应用,但在使用时也需要注意数据的时效性和准确性。确保你获取的变量值是最新且正确的,以避免逻辑错误或不一致的行为。

总的来说,UE Get节点是Unreal Engine蓝图系统中非常重要的一个节点类型,它使得开发者能够灵活地获取游戏中的数据,并根据这些数据实现各种复杂的逻辑和交互。

相关源码

源码文件:
K2Node_VariableGet.h
K2Node_VariableGet.cpp
相关类:
FKCHandler_VariableGet
K2Node_VariableGetImpl

#include "K2Node_VariableGet.h"
#include "UObject/UObjectHash.h"
#include "UObject/PropertyPortFlags.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Framework/Commands/UIAction.h"
#include "ToolMenus.h"
#include "EdGraph/EdGraph.h"
#include "EdGraphSchema_K2.h"
#include "K2Node_CallFunction.h"
#include "K2Node_IfThenElse.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "KismetCompilerMisc.h"
#include "KismetCompiler.h"
#include "ScopedTransaction.h"//
// FKCHandler_VariableGet#define LOCTEXT_NAMESPACE "K2Node"class FKCHandler_VariableGet : public FNodeHandlingFunctor
{
public:FKCHandler_VariableGet(FKismetCompilerContext& InCompilerContext): FNodeHandlingFunctor(InCompilerContext){}virtual void RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) override{// This net is a variable readResolveAndRegisterScopedTerm(Context, Net, Context.VariableReferences);}virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override{UK2Node_Variable* VarNode = Cast<UK2Node_Variable>(Node);if (VarNode){VarNode->CheckForErrors(CompilerContext.GetSchema(), Context.MessageLog);// Report an error that the local variable could not be foundif(VarNode->VariableReference.IsLocalScope() && VarNode->GetPropertyForVariable() == NULL){FFormatNamedArguments Args;Args.Add(TEXT("VariableName"), FText::FromName(VarNode->VariableReference.GetMemberName()));if(VarNode->VariableReference.GetMemberScopeName() != Context.Function->GetName()){Args.Add(TEXT("ScopeName"), FText::FromString(VarNode->VariableReference.GetMemberScopeName()));CompilerContext.MessageLog.Warning(*FText::Format(LOCTEXT("LocalVariableNotFoundInScope_Error", "Unable to find local variable with name '{VariableName}' for @@, scope expected: @@, scope found: {ScopeName}"), Args).ToString(), Node, Node->GetGraph());}else{CompilerContext.MessageLog.Warning(*FText::Format(LOCTEXT("LocalVariableNotFound_Error", "Unable to find local variable with name '{VariableName}' for @@"), Args).ToString(), Node);}}}FNodeHandlingFunctor::RegisterNets(Context, Node);}
};namespace K2Node_VariableGetImpl
{/*** Shared utility method for retrieving a UK2Node_VariableGet's bare tooltip.* * @param  VarName	The name of the variable that the node represents.* @return A formatted text string, describing what the VariableGet node does.*/static FText GetBaseTooltip(FName VarName);
}static FText K2Node_VariableGetImpl::GetBaseTooltip(FName VarName)
{FFormatNamedArguments Args;Args.Add(TEXT("VarName"), FText::FromName(VarName));return FText::Format(LOCTEXT("GetVariableTooltip", "Read the value of variable {VarName}"), Args);}UK2Node_VariableGet::UK2Node_VariableGet(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer), bIsPureGet(true)
{
}void UK2Node_VariableGet::CreateNonPurePins(TArray<UEdGraphPin*>* InOldPinsPtr)
{const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());check(K2Schema != nullptr);if (!K2Schema->DoesGraphSupportImpureFunctions(GetGraph())){bIsPureGet = true;}if (!bIsPureGet){FEdGraphPinType PinType;FProperty* VariableProperty = GetPropertyForVariable();// We need the pin's type, to both see if it's an array and if it is of the correct types to remain an impure nodeif (VariableProperty){K2Schema->ConvertPropertyToPinType(GetPropertyForVariable(), PinType);}// If there is no property and we are given some old pins to look at, find the old value pin and use the type there// This allows nodes to be pasted into other BPs without access to the propertyelse if (InOldPinsPtr){// find old variable pin and use the type.const FName PinName = GetVarName();for (const UEdGraphPin* Pin : *InOldPinsPtr){if (Pin && PinName == Pin->PinName){PinType = Pin->PinType;break;}}}if (IsValidTypeForNonPure(PinType)){// Input - Execution PinCreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);// Output - Execution PinsUEdGraphPin* ValidPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);ValidPin->PinFriendlyName = LOCTEXT("Valid", "Is Valid");UEdGraphPin* InvalidPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Else);InvalidPin->PinFriendlyName = LOCTEXT("Invalid", "Is Not Valid");}else{bIsPureGet = true;}}
}void UK2Node_VariableGet::AllocateDefaultPins()
{if(GetVarName() != NAME_None){CreateNonPurePins(nullptr);if(CreatePinForVariable(EGPD_Output)){CreatePinForSelf();}}Super::AllocateDefaultPins();
}void UK2Node_VariableGet::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins)
{if(GetVarName() != NAME_None){CreateNonPurePins(&OldPins);if(!CreatePinForVariable(EGPD_Output)){if(!RecreatePinForVariable(EGPD_Output, OldPins)){return;}}CreatePinForSelf();RestoreSplitPins(OldPins);}
}FText UK2Node_VariableGet::GetPropertyTooltip(FProperty const* VariableProperty)
{FName VarName = NAME_None;if (VariableProperty != nullptr){VarName = VariableProperty->GetFName();UClass* SourceClass = VariableProperty->GetOwnerClass();// discover if the variable property is a non blueprint user variablebool const bIsNativeVariable = (SourceClass != nullptr) && (SourceClass->ClassGeneratedBy == nullptr);FText SubTooltip;if (bIsNativeVariable){FText const PropertyTooltip = VariableProperty->GetToolTipText();if (!PropertyTooltip.IsEmpty()){// See if the native property has a tooltipSubTooltip = PropertyTooltip;FString TooltipName = FString::Printf(TEXT("%s.%s"), *VarName.ToString(), *FBlueprintMetadata::MD_Tooltip.ToString());FText::FindText(*VariableProperty->GetFullGroupName(true), *TooltipName, SubTooltip);}}else if (SourceClass){if (UBlueprint* VarBlueprint = Cast<UBlueprint>(SourceClass->ClassGeneratedBy)){FString UserTooltipData;if (FBlueprintEditorUtils::GetBlueprintVariableMetaData(VarBlueprint, VarName, VariableProperty->GetOwnerStruct(), FBlueprintMetadata::MD_Tooltip, UserTooltipData)){SubTooltip = FText::FromString(UserTooltipData);}}}if (!SubTooltip.IsEmpty()){FFormatNamedArguments Args;Args.Add(TEXT("VarName"), FText::FromName(VarName));Args.Add(TEXT("PropertyTooltip"), SubTooltip);return FText::Format(LOCTEXT("GetVariableProperty_Tooltip", "Read the value of variable {VarName}\n{PropertyTooltip}"), Args);}}return K2Node_VariableGetImpl::GetBaseTooltip(VarName);
}FText UK2Node_VariableGet::GetBlueprintVarTooltip(FBPVariableDescription const& VarDesc)
{int32 const MetaIndex = VarDesc.FindMetaDataEntryIndexForKey(FBlueprintMetadata::MD_Tooltip);bool const bHasTooltipData = (MetaIndex != INDEX_NONE);if (bHasTooltipData){FString UserTooltipData = VarDesc.GetMetaData(FBlueprintMetadata::MD_Tooltip);FFormatNamedArguments Args;Args.Add(TEXT("VarName"), FText::FromName(VarDesc.VarName));Args.Add(TEXT("UserTooltip"), FText::FromString(UserTooltipData));return FText::Format(LOCTEXT("GetBlueprintVariable_Tooltip", "Read the value of variable {VarName}\n{UserTooltip}"), Args);}return K2Node_VariableGetImpl::GetBaseTooltip(VarDesc.VarName);
}FText UK2Node_VariableGet::GetTooltipText() const
{if (CachedTooltip.IsOutOfDate(this)){if (FProperty* Property = GetPropertyForVariable()){CachedTooltip.SetCachedText(GetPropertyTooltip(Property), this);}else if (FBPVariableDescription const* VarDesc = GetBlueprintVarDescription()){CachedTooltip.SetCachedText(GetBlueprintVarTooltip(*VarDesc), this);}else{CachedTooltip.SetCachedText(K2Node_VariableGetImpl::GetBaseTooltip(GetVarName()), this);}}return CachedTooltip;
}FText UK2Node_VariableGet::GetNodeTitle(ENodeTitleType::Type TitleType) const
{// If there is only one variable being read, the title can be made the variable nameFName OutputPinName;int32 NumOutputsFound = 0;for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex){UEdGraphPin* Pin = Pins[PinIndex];// The following code is to attempt to log info related to UE-19729if (TitleType == ENodeTitleType::ListView){if (UEdGraph* Graph = Cast<UEdGraph>(GetOuter())){FString VariableName = GetVarNameString();FString BlueprintPath = FBlueprintEditorUtils::FindBlueprintForGraph(Graph)->GetPathName();FString SetupStyle = bIsPureGet? TEXT("pure") : TEXT("validated");FString VariableResolves = (VariableReference.ResolveMember<FProperty>(GetBlueprintClassFromNode()) != nullptr)? TEXT("resolves") : TEXT("does not resolve");checkf(Pin, TEXT("Get node for variable '%s' in Blueprint '%s' which is setup as %s and has %d pins. Variable %s"), *VariableName, *BlueprintPath, *SetupStyle, Pins.Num(), *VariableResolves);}}if (Pin->Direction == EGPD_Output){++NumOutputsFound;OutputPinName = Pin->PinName;}}if (NumOutputsFound != 1){return LOCTEXT("Get", "Get");}else if (CachedNodeTitle.IsOutOfDate(this)){FFormatNamedArguments Args;Args.Add(TEXT("PinName"), FText::FromName(OutputPinName));// FText::Format() is slow, so we cache this to save on performanceCachedNodeTitle.SetCachedText(FText::Format(LOCTEXT("GetPinName", "Get {PinName}"), Args), this);}return CachedNodeTitle;
}FNodeHandlingFunctor* UK2Node_VariableGet::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
{return new FKCHandler_VariableGet(CompilerContext);
}bool UK2Node_VariableGet::IsValidTypeForNonPure(const FEdGraphPinType& InPinType)
{return !InPinType.IsContainer() && (InPinType.PinCategory == UEdGraphSchema_K2::PC_Object || InPinType.PinCategory == UEdGraphSchema_K2::PC_Class || InPinType.PinCategory == UEdGraphSchema_K2::PC_SoftObject || InPinType.PinCategory == UEdGraphSchema_K2::PC_SoftClass);
}void UK2Node_VariableGet::GetNodeContextMenuActions(UToolMenu* Menu, UGraphNodeContextMenuContext* Context) const
{Super::GetNodeContextMenuActions(Menu, Context);const UEdGraphPin* ValuePin = GetValuePin();if (ValuePin && IsValidTypeForNonPure(ValuePin->PinType)){{FText MenuEntryTitle;FText MenuEntryTooltip;bool bCanTogglePurity = true;auto CanExecutePurityToggle = [](bool const bInCanTogglePurity)->bool{return bInCanTogglePurity;};if (bIsPureGet){MenuEntryTitle   = LOCTEXT("ConvertToImpureGetTitle",   "Convert to Validated Get");MenuEntryTooltip = LOCTEXT("ConvertToImpureGetTooltip", "Adds in branching execution pins so that you can separately handle when the returned value is valid/invalid.");const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());check(K2Schema != nullptr);bCanTogglePurity = K2Schema->DoesGraphSupportImpureFunctions(GetGraph());if (!bCanTogglePurity){MenuEntryTooltip = LOCTEXT("CannotMakeImpureGetTooltip", "This graph does not support impure calls!");}}else{MenuEntryTitle   = LOCTEXT("ConvertToPureGetTitle",   "Convert to pure Get");MenuEntryTooltip = LOCTEXT("ConvertToPureGetTooltip", "Removes the execution pins to make the node more versatile.");}FToolMenuSection& Section = Menu->AddSection("K2NodeVariableGet", LOCTEXT("VariableGetHeader", "Variable Get"));Section.AddMenuEntry("TogglePurity",MenuEntryTitle,MenuEntryTooltip,FSlateIcon(),FUIAction(FExecuteAction::CreateUObject(const_cast<UK2Node_VariableGet*>(this), &UK2Node_VariableGet::TogglePurity),FCanExecuteAction::CreateStatic(CanExecutePurityToggle, bCanTogglePurity && !Context->bIsDebugging),FIsActionChecked()));}}
}void UK2Node_VariableGet::TogglePurity()
{FText TransactionTitle;if(!bIsPureGet){TransactionTitle = LOCTEXT("TogglePureGet", "Convert to Pure Get");}else{TransactionTitle = LOCTEXT("ToggleImpureGet", "Convert to Impure Get");}const FScopedTransaction Transaction( TransactionTitle );Modify();SetPurity(!bIsPureGet);
}void UK2Node_VariableGet::SetPurity(bool bNewPurity)
{if (bNewPurity != bIsPureGet){bIsPureGet = bNewPurity;bool const bHasBeenConstructed = (Pins.Num() > 0);if (bHasBeenConstructed){ReconstructNode();}}
}void UK2Node_VariableGet::ValidateNodeDuringCompilation(FCompilerResultsLog& MessageLog) const
{Super::ValidateNodeDuringCompilation(MessageLog);// Some expansions, such as timelines, will create gets for non-blueprint visible properties, and we don't want to validate against thatif (!IsIntermediateNode()){if (FProperty* Property = GetPropertyForVariable()){const FBlueprintEditorUtils::EPropertyReadableState PropertyReadableState = FBlueprintEditorUtils::IsPropertyReadableInBlueprint(GetBlueprint(), Property);if (PropertyReadableState != FBlueprintEditorUtils::EPropertyReadableState::Readable){FFormatNamedArguments Args;if (UObject* Class = Property->GetOwner<UObject>()){Args.Add(TEXT("VariableName"), FText::AsCultureInvariant(FString::Printf(TEXT("%s.%s"), *Class->GetName(), *Property->GetName())));}else{Args.Add(TEXT("VariableName"), FText::AsCultureInvariant(Property->GetName()));}if (PropertyReadableState == FBlueprintEditorUtils::EPropertyReadableState::NotBlueprintVisible){// UE_DEPRECATED(4.17) ... make this an errorMessageLog.Warning(*FText::Format(LOCTEXT("UnableToGet_NotVisible", "{VariableName} is not blueprint visible (BlueprintReadOnly or BlueprintReadWrite). Please fix mark up or cease accessing as this will be made an error in a future release. @@"), Args).ToString(), this);}else if (PropertyReadableState == FBlueprintEditorUtils::EPropertyReadableState::Private){// UE_DEPRECATED(4.17) ... make this an errorMessageLog.Warning(*FText::Format(LOCTEXT("UnableToGet_ReadOnly", "{VariableName} is private and not accessible in this context. Please fix mark up or cease accessing as this will be an error in a future release. @@"), Args).ToString(), this);}else{check(false);}}}}
}void UK2Node_VariableGet::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{Super::ExpandNode(CompilerContext, SourceGraph);FProperty* VariableProperty = GetPropertyForVariable();UK2Node_VariableGet* VariableGetNode = this;// Do not attempt to expand the node when not a pure get nor when there is no property. Normal compilation error detection will detect the missing property.if (!bIsPureGet && VariableProperty){UEdGraphPin* ValuePin = GetValuePin();// Impure Get nodes convert into three nodes:// 1. A pure Get node// 2. An IsValid node// 3. A Branch node (only impure part)// Create the pure Get nodeVariableGetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableGet>(this, SourceGraph);VariableGetNode->VariableReference = VariableReference;VariableGetNode->AllocateDefaultPins();CompilerContext.MessageLog.NotifyIntermediateObjectCreation(VariableGetNode, this);// Move pin links from Get node we are expanding, to the new pure one we've createdCompilerContext.MovePinLinksToIntermediate(*ValuePin, *VariableGetNode->GetValuePin());if (!VariableReference.IsLocalScope()){CompilerContext.MovePinLinksToIntermediate(*FindPin(UEdGraphSchema_K2::PN_Self), *VariableGetNode->FindPin(UEdGraphSchema_K2::PN_Self));}// Create the IsValid nodeUK2Node_CallFunction* IsValidFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);// Based on if the type is an "Object" or a "Class" changes which function to useif (ValuePin->PinType.PinCategory == UEdGraphSchema_K2::PC_Object){IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValid)));}else if (ValuePin->PinType.PinCategory == UEdGraphSchema_K2::PC_Class){IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValidClass)));}else if (ValuePin->PinType.PinCategory == UEdGraphSchema_K2::PC_SoftObject){IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValidSoftObjectReference)));}else if (ValuePin->PinType.PinCategory == UEdGraphSchema_K2::PC_SoftClass){IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValidSoftClassReference)));}IsValidFunction->AllocateDefaultPins();CompilerContext.MessageLog.NotifyIntermediateObjectCreation(IsValidFunction, this);// Connect the value pin from the new Get node to the IsValidUEdGraphPin* ObjectPin = IsValidFunction->Pins[1];check(ObjectPin->Direction == EGPD_Input);ObjectPin->MakeLinkTo(VariableGetNode->GetValuePin());// Create the Branch nodeUK2Node_IfThenElse* BranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph);BranchNode->AllocateDefaultPins();CompilerContext.MessageLog.NotifyIntermediateObjectCreation(BranchNode, this);// Connect the bool output pin from IsValid node to the Branch nodeUEdGraphPin* BoolPin = IsValidFunction->Pins[2];check(BoolPin->Direction == EGPD_Output);BoolPin->MakeLinkTo(BranchNode->GetConditionPin());// Connect the Branch node to the input of the impure Get nodeCompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BranchNode->GetExecPin());// Move the two Branch pins to the Branch nodeCompilerContext.MovePinLinksToIntermediate(*FindPin(UEdGraphSchema_K2::PN_Then), *BranchNode->FindPin(UEdGraphSchema_K2::PN_Then));CompilerContext.MovePinLinksToIntermediate(*FindPin(UEdGraphSchema_K2::PN_Else), *BranchNode->FindPin(UEdGraphSchema_K2::PN_Else));BreakAllNodeLinks();}// If property has a BlueprintGetter accessor, then replace the variable get node with a call functionif (VariableProperty){const FString& GetFunctionName = VariableProperty->GetMetaData(FBlueprintMetadata::MD_PropertyGetFunction);if (!GetFunctionName.IsEmpty()){UClass* OwnerClass = VariableProperty->GetOwnerClass();UFunction* GetFunction = OwnerClass->FindFunctionByName(*GetFunctionName);check(GetFunction);UK2Node_CallFunction* CallFuncNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);CallFuncNode->SetFromFunction(GetFunction);CallFuncNode->AllocateDefaultPins();const UEdGraphSchema_K2* K2Schema = CompilerContext.GetSchema();// Move Self pin connectionsCompilerContext.MovePinLinksToIntermediate(*K2Schema->FindSelfPin(*this, EGPD_Input), *K2Schema->FindSelfPin(*CallFuncNode, EGPD_Input));// Move Value pin connectionsCompilerContext.MovePinLinksToIntermediate(*GetValuePin(), *CallFuncNode->GetReturnValuePin());}}
}void UK2Node_VariableGet::Serialize(FArchive& Ar)
{// The following code is to attempt to log info related to UE-19729if (Ar.IsSaving() && Ar.IsPersistent()){uint32 PortFlagsToSkip = PPF_Duplicate | PPF_DuplicateForPIE;if (!(Ar.GetPortFlags() & PortFlagsToSkip)){if (UEdGraph* Graph = Cast<UEdGraph>(GetOuter())){if (UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(Graph)){if (!Blueprint->bBeingCompiled){// The following line may spur the crash noted in UE-19729 and will confirm that the crash happens before the FiB gather.GetNodeTitle(ENodeTitleType::ListView);}}}}}Super::Serialize(Ar);
}#undef LOCTEXT_NAMESPACE

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

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

相关文章

文件上传漏洞--Upload-labs--Pass01--前端绕过

一、前端绕过原理 通俗解释&#xff0c;我们将写有恶意代码的php后缀文件上传到网页&#xff0c;网页中的javascript代码会先对文件的后缀名进行检测&#xff0c;若检测到上传文件的后缀名为非法&#xff0c;则会进行alert警告。若想上传php后缀的文件&#xff0c;就要想办法对…

可视化和跟踪机器学习实验的工具——Wandb

简介&#xff1a;用于可视化和跟踪机器学习实验的工具。Weights & Biases 是一个机器学习平台&#xff0c;供开发人员更快地构建更好的模型。使用 W&B 的轻量级、可互操作的工具快速跟踪实验、对数据集进行版本和迭代、评估模型性能、重现模型、可视化结果和发现回归&a…

微服务学习Day4

文章目录 初始MQ同步通讯和异步通讯MQ常见技术介绍 RabbitMQ快速入门入门案例 SpringAMQP介绍例子WorkQueue模型exchange交换机消息转换器 初始MQ 同步通讯和异步通讯 MQ常见技术介绍 RabbitMQ快速入门 入门案例 SpringAMQP 介绍 例子 WorkQueue模型 exchange交换机 消息转换…

【力扣hot100】刷题笔记Day5

前言 回学校了&#xff0c;荒废了半天之后打算奋发图强猛猛刷题&#xff0c;找实习&#xff01;赚钱&#xff01;&#xff01; 560. 和为 K 的子数组 - 力扣&#xff08;LeetCode&#xff09; 前缀法 哈希表 这个题解解释比官方清晰&#xff0c;截个图方便看&#xff0c;另一…

算法刷题:将 x 减到 0 的最小操作数

将 x 减到 0 的最小操作数 .题目链接题目详情题目解析滑动窗口定义指针及其他变量进窗口判断出窗口更新结果 我的答案 . 题目链接 将 x 减到 0 的最小操作数 题目详情 题目解析 正面做这道题比较难,我们可以进行逆向思维 将这道题理解为: 求数组中,最长的子数组,且子数组中的…

【STM32 CubeMX】SPI_Flash_W25Q64的操作方法

文章目录 前言一、W25Q64操作方法基本概念1.1 读数据1.2 写使能1.3 读状态1.4 擦除扇区1.5 烧写页 总结 前言 在嵌入式系统开发中&#xff0c;使用外部 SPI Flash 存储器可以为 STM32 微控制器提供额外的存储空间&#xff0c;以存储程序代码、配置数据等。W25Q64 是一款常见的…

深入剖析跨域请求发送两次的原因及解决方案(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

linux kernel 内存踩踏之KASAN_SW_TAGS(二)

一、背景 linux kernel 内存踩踏之KASAN&#xff08;一&#xff09;_kasan版本跟hasan版本区别-CSDN博客 上一篇简单介绍了标准版本的KASAN使用方法和实现&#xff0c;这里将介绍KASAN_SW_TAGS和KASAN_HW_TAGS 的使用和背后基本原理&#xff0c;下图是三种方式的对比&#x…

计算机设计大赛 深度学习中文汉字识别

文章目录 0 前言1 数据集合2 网络构建3 模型训练4 模型性能评估5 文字预测6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习中文汉字识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xf…

RegExp正则表达式左限定右限定左右限定,预查询,预查寻,断言 : (?<= , (?= , (?<! , (?!

RegExp正则表达式左限定右限定左右限定,预查询,预查寻,断言 : (?< , (? , (?<! , (?! 有好多种称呼 (?< , (? , (?<! , (?! 有好多种称呼 , 我称为: 左限定, 右限定, 左否定, 右否定 (?<左限定)    (?右限定)(?<!左否定)    (?!右限定) 再…

人力资源智能化管理项目(day10:首页开发以及上线部署)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/humanResourceIntelligentManagementProject 首页-基本结构和数字滚动 安装插件 npm i vue-count-to <template><div class"dashboard"><div class"container"><!-- 左侧内…

【JavaScript】面试手写题精讲之数组(下)

引入 这章主要讲的是数组的排序篇&#xff0c;我们知道面试的时候&#xff0c;数组的排序是经常出现的题目。所以这块还是有必要进行一下讲解的。笔者观察了下前端这块的常用算法排序题&#xff0c;大概可以分为如下 冒泡排–> 稳定排序插入排序–> 稳定排序选择排序–…