You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Overview: - An "override flag" is an inline toggle-style Boolean edit condition. These are implicitly set to true at runtime within the output struct value if any member that's bound to it is exposed as a visible input pin on a MakeStruct node. - For context, the Property Editor implicitly sets an override flag to true at edit time when a member that's bound to it is enabled for editing. These members are not otherwise labeled/exposed for direct editing. - An override flag is meant to signal to a system that the user wishes to use the bound member's value in place of the current value (whatever that may be) when the full struct value is applied. Examples: FPostProcessSettings, FMovieSceneSequencePlaybackSettings, etc. Previous UX: - All boolean edit conditions were being treated as override flags on a MakeStruct node. - Any inline toggle edit condition that did not begin with "bOverride_" or whose suffix otherwise did not match another value member could be exposed as an input on a MakeStruct node. - Override flags exposed as inputs would always be set to TRUE at runtime regardless of input if it was declared at the top of the struct and if a member value bound to it was also exposed as an input pin. After this change: - Only inline toggle edit conditions and legacy struct members that follow the "bOverride_" naming convention will be treated as an override flag on a MakeStruct node. - Inline toggle edit conditions can no longer be exposed directly as an input on a MakeStruct node. The intent was to bring the MakeStruct node UX closer to parity with the Property Editor UX. Additional notes: - Members that follow the legacy "bOverride_" naming convention were already being excluded from the optional input pin set on MakeStruct nodes if another member property name also matched its suffix. These have historically been excluded from ALL optional pin sets that utilize any FOptionalPinManager subtype (regardless of node type), so there was no change here. - Existing MakeStruct nodes that may have already exposed inline toggle edit condition members as input pins will now orphan those pins on load if connected or if set to a non-default value (true). The "correct" way to set an override flag is by choosing to expose a member that's bound to the override condition as an input. - Existing BreakStruct nodes are unchanged currently. Meaning, inline edit conditions that don't follow the legacy "bOverride_" convention can still be optionally exposed as an output pin. This UX was preserved as existing Blueprint logic could conceivably rely on the value of an override flag. - Only one implicit assignment is now emitted for each override flag binding. Previously, we were emitting one assignment statement per bound property, so it could result in redundant assignments to the same flag if more than one property was bound to it. #jira UE-147873 #rb Ben.Zeigler, Sebastian.Nordgren #preflight 632c7353c7791417aa87f3bf [CL 22164359 by phillip kavan in ue5-main branch]
477 lines
16 KiB
C++
477 lines
16 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "K2Node_MakeStruct.h"
|
|
|
|
#include "Containers/Array.h"
|
|
#include "Containers/EnumAsByte.h"
|
|
#include "Containers/Map.h"
|
|
#include "Containers/UnrealString.h"
|
|
#include "Delegates/Delegate.h"
|
|
#include "EdGraph/EdGraphPin.h"
|
|
#include "EdGraphSchema_K2.h"
|
|
#include "EditorCategoryUtils.h"
|
|
#include "Engine/Blueprint.h"
|
|
#include "Internationalization/Internationalization.h"
|
|
#include "Kismet/KismetMathLibrary.h"
|
|
#include "Kismet2/BlueprintEditorUtils.h"
|
|
#include "Kismet2/CompilerResultsLog.h"
|
|
#include "KismetCompilerMisc.h"
|
|
#include "MakeStructHandler.h"
|
|
#include "Math/Rotator.h"
|
|
#include "Math/UnrealMathSSE.h"
|
|
#include "Math/Vector2D.h"
|
|
#include "Misc/AssertionMacros.h"
|
|
#include "PropertyCustomizationHelpers.h"
|
|
#include "Serialization/Archive.h"
|
|
#include "Styling/AppStyle.h"
|
|
#include "UObject/Class.h"
|
|
#include "UObject/ObjectPtr.h"
|
|
#include "UObject/ObjectSaveContext.h"
|
|
#include "UObject/StructOnScope.h"
|
|
#include "UObject/TextProperty.h"
|
|
#include "UObject/UnrealType.h"
|
|
#include "UObject/WeakObjectPtrTemplates.h"
|
|
|
|
class FKismetCompilerContext;
|
|
|
|
#define LOCTEXT_NAMESPACE "K2Node_MakeStruct"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// UK2Node_MakeStruct
|
|
|
|
|
|
UK2Node_MakeStruct::FMakeStructPinManager::FMakeStructPinManager(const uint8* InSampleStructMemory, UBlueprint* InOwningBP)
|
|
: FStructOperationOptionalPinManager()
|
|
, SampleStructMemory(InSampleStructMemory)
|
|
, OwningBP(InOwningBP)
|
|
, bHasAdvancedPins(false)
|
|
{
|
|
}
|
|
|
|
void UK2Node_MakeStruct::FMakeStructPinManager::GetRecordDefaults(FProperty* TestProperty, FOptionalPinFromProperty& Record) const
|
|
{
|
|
UK2Node_StructOperation::FStructOperationOptionalPinManager::GetRecordDefaults(TestProperty, Record);
|
|
Record.bIsMarkedForAdvancedDisplay = TestProperty ? TestProperty->HasAnyPropertyFlags(CPF_AdvancedDisplay) : false;
|
|
bHasAdvancedPins |= Record.bIsMarkedForAdvancedDisplay;
|
|
}
|
|
|
|
void UK2Node_MakeStruct::FMakeStructPinManager::CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex, FProperty* Property) const
|
|
{
|
|
UK2Node_StructOperation::FStructOperationOptionalPinManager::CustomizePinData(Pin, SourcePropertyName, ArrayIndex, Property);
|
|
if (Pin && Property)
|
|
{
|
|
const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
|
|
check(Schema);
|
|
|
|
// Should pin default value be filled as FText?
|
|
const bool bIsText = Property->IsA<FTextProperty>();
|
|
checkSlow(bIsText == ((UEdGraphSchema_K2::PC_Text == Pin->PinType.PinCategory) && !Pin->PinType.IsContainer()));
|
|
|
|
const bool bIsObject = Property->IsA<FObjectPropertyBase>();
|
|
checkSlow(bIsObject == ((UEdGraphSchema_K2::PC_Object == Pin->PinType.PinCategory || UEdGraphSchema_K2::PC_Class == Pin->PinType.PinCategory ||
|
|
UEdGraphSchema_K2::PC_SoftObject == Pin->PinType.PinCategory || UEdGraphSchema_K2::PC_SoftClass == Pin->PinType.PinCategory) && !Pin->PinType.IsContainer()));
|
|
|
|
if (Property->HasAnyPropertyFlags(CPF_AdvancedDisplay))
|
|
{
|
|
Pin->bAdvancedView = true;
|
|
bHasAdvancedPins = true;
|
|
}
|
|
|
|
const FString& MetadataDefaultValue = Property->GetMetaData(TEXT("MakeStructureDefaultValue"));
|
|
if (!MetadataDefaultValue.IsEmpty())
|
|
{
|
|
Schema->SetPinAutogeneratedDefaultValue(Pin, MetadataDefaultValue);
|
|
return;
|
|
}
|
|
|
|
if (nullptr != SampleStructMemory)
|
|
{
|
|
FString NewDefaultValue;
|
|
if (FBlueprintEditorUtils::PropertyValueToString(Property, SampleStructMemory, NewDefaultValue))
|
|
{
|
|
if (Schema->IsPinDefaultValid(Pin, NewDefaultValue, nullptr, FText::GetEmpty()).IsEmpty())
|
|
{
|
|
Schema->SetPinAutogeneratedDefaultValue(Pin, NewDefaultValue);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
Schema->SetPinAutogeneratedDefaultValueBasedOnType(Pin);
|
|
}
|
|
}
|
|
|
|
static bool CanBeExposed(const FProperty* Property, UBlueprint* BP)
|
|
{
|
|
if (Property)
|
|
{
|
|
const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
|
|
check(Schema);
|
|
|
|
// Treat all inline edit condition properties as override flags; that is, don't allow
|
|
// these to be exposed as part of the optional input pin set. Their value will be set
|
|
// implicitly at runtime based on whether or not any bound members are exposed, rather
|
|
// than explicitly via an exposed input pin. This emulates how the Property Editor
|
|
// handles setting these values at edit time (they appear as an inline checkbox that
|
|
// the user ticks on to set the flag and enable/override a bound property's value).
|
|
static const FName MD_InlineEditConditionToggle(TEXT("InlineEditConditionToggle"));
|
|
if (Property->HasMetaData(MD_InlineEditConditionToggle))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const bool bIsEditorBP = IsEditorOnlyObject(BP);
|
|
const bool bIsEditAnywhereProperty = Property->HasAllPropertyFlags(CPF_Edit) &&
|
|
!Property->HasAnyPropertyFlags(CPF_EditConst);
|
|
|
|
if (!Property->HasAllPropertyFlags(CPF_BlueprintReadOnly) ||
|
|
(bIsEditorBP && bIsEditAnywhereProperty) )
|
|
{
|
|
if (Property->HasAllPropertyFlags(CPF_BlueprintVisible) && !(Property->ArrayDim > 1))
|
|
{
|
|
FEdGraphPinType DumbGraphPinType;
|
|
if (Schema->ConvertPropertyToPinType(Property, /*out*/ DumbGraphPinType))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool UK2Node_MakeStruct::FMakeStructPinManager::CanTreatPropertyAsOptional(FProperty* TestProperty) const
|
|
{
|
|
return CanBeExposed(TestProperty, OwningBP);
|
|
}
|
|
|
|
UK2Node_MakeStruct::UK2Node_MakeStruct(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
, bMadeAfterOverridePinRemoval(false)
|
|
{
|
|
}
|
|
|
|
void UK2Node_MakeStruct::AllocateDefaultPins()
|
|
{
|
|
if (StructType)
|
|
{
|
|
PreloadObject(StructType);
|
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Struct, StructType, StructType->GetFName());
|
|
|
|
bool bHasAdvancedPins = false;
|
|
{
|
|
FStructOnScope StructOnScope(StructType);
|
|
FMakeStructPinManager OptionalPinManager(StructOnScope.GetStructMemory(), GetBlueprint());
|
|
OptionalPinManager.RebuildPropertyList(ShowPinForProperties, StructType);
|
|
OptionalPinManager.CreateVisiblePins(ShowPinForProperties, StructType, EGPD_Input, this);
|
|
|
|
bHasAdvancedPins = OptionalPinManager.HasAdvancedPins();
|
|
}
|
|
|
|
// Set container pin types to have their default values ignored, which will in turn
|
|
// enable auto generation for any that are not set by the user.
|
|
for(UEdGraphPin* Pin : Pins)
|
|
{
|
|
Pin->bDefaultValueIsIgnored = Pin->bDefaultValueIsIgnored || Pin->PinType.IsContainer();
|
|
}
|
|
|
|
// When struct has a lot of fields, mark their pins as advanced
|
|
if(!bHasAdvancedPins && Pins.Num() > 5)
|
|
{
|
|
for(int32 PinIndex = 3; PinIndex < Pins.Num(); ++PinIndex)
|
|
{
|
|
if(UEdGraphPin * EdGraphPin = Pins[PinIndex])
|
|
{
|
|
EdGraphPin->bAdvancedView = true;
|
|
bHasAdvancedPins = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bHasAdvancedPins && (ENodeAdvancedPins::NoPins == AdvancedPinDisplay))
|
|
{
|
|
AdvancedPinDisplay = ENodeAdvancedPins::Hidden;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UK2Node_MakeStruct::PreloadRequiredAssets()
|
|
{
|
|
PreloadObject(StructType);
|
|
Super::PreloadRequiredAssets();
|
|
}
|
|
|
|
void UK2Node_MakeStruct::ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const
|
|
{
|
|
Super::ValidateNodeDuringCompilation(MessageLog);
|
|
|
|
if(!StructType)
|
|
{
|
|
MessageLog.Error(*LOCTEXT("NoStruct_Error", "No Struct in @@").ToString(), this);
|
|
}
|
|
else
|
|
{
|
|
UBlueprint* BP = GetBlueprint();
|
|
for (TFieldIterator<FProperty> It(StructType); It; ++It)
|
|
{
|
|
const FProperty* Property = *It;
|
|
if (CanBeExposed(Property, BP))
|
|
{
|
|
if (Property->ArrayDim > 1)
|
|
{
|
|
const UEdGraphPin* Pin = FindPin(Property->GetFName());
|
|
MessageLog.Warning(*LOCTEXT("StaticArray_Warning", "@@ - the native property is a static array, which is not supported by blueprints").ToString(), Pin);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bMadeAfterOverridePinRemoval)
|
|
{
|
|
MessageLog.Note(*NSLOCTEXT("K2Node", "OverridePinRemoval_SetFieldsInStruct", "Override pins have been removed from @@ in @@, it functions the same as it did but some functionality may be deprecated! This note will go away after you resave the asset!").ToString(), this, GetBlueprint());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
FText UK2Node_MakeStruct::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
|
{
|
|
if (StructType == nullptr)
|
|
{
|
|
return LOCTEXT("MakeNullStructTitle", "Make <unknown struct>");
|
|
}
|
|
else if (CachedNodeTitle.IsOutOfDate(this))
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("StructName"), FText::FromName(StructType->GetFName()));
|
|
// FText::Format() is slow, so we cache this to save on performance
|
|
CachedNodeTitle.SetCachedText(FText::Format(LOCTEXT("MakeNodeTitle", "Make {StructName}"), Args), this);
|
|
}
|
|
return CachedNodeTitle;
|
|
}
|
|
|
|
FText UK2Node_MakeStruct::GetTooltipText() const
|
|
{
|
|
if (StructType == nullptr)
|
|
{
|
|
return LOCTEXT("MakeNullStruct_Tooltip", "Adds a node that create an '<unknown struct>' from its members");
|
|
}
|
|
else if (CachedTooltip.IsOutOfDate(this))
|
|
{
|
|
// FText::Format() is slow, so we cache this to save on performance
|
|
CachedTooltip.SetCachedText(FText::Format(
|
|
LOCTEXT("MakeStruct_Tooltip", "Adds a node that create a '{0}' from its members"),
|
|
FText::FromName(StructType->GetFName())
|
|
), this);
|
|
}
|
|
return CachedTooltip;
|
|
}
|
|
|
|
FSlateIcon UK2Node_MakeStruct::GetIconAndTint(FLinearColor& OutColor) const
|
|
{
|
|
static FSlateIcon Icon(FAppStyle::GetAppStyleSetName(), "GraphEditor.MakeStruct_16x");
|
|
return Icon;
|
|
}
|
|
|
|
FLinearColor UK2Node_MakeStruct::GetNodeTitleColor() const
|
|
{
|
|
if(const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>())
|
|
{
|
|
FEdGraphPinType PinType;
|
|
PinType.PinCategory = UEdGraphSchema_K2::PC_Struct;
|
|
PinType.PinSubCategoryObject = StructType;
|
|
return K2Schema->GetPinTypeColor(PinType);
|
|
}
|
|
return UK2Node::GetNodeTitleColor();
|
|
}
|
|
|
|
bool UK2Node_MakeStruct::CanBeMade(const UScriptStruct* Struct, const bool bForInternalUse)
|
|
{
|
|
return (Struct && !Struct->HasMetaData(FBlueprintMetadata::MD_NativeMakeFunction) && UEdGraphSchema_K2::IsAllowableBlueprintVariableType(Struct, bForInternalUse));
|
|
}
|
|
|
|
bool UK2Node_MakeStruct::CanBeSplit(const UScriptStruct* Struct, UBlueprint* InBP)
|
|
{
|
|
if (CanBeMade(Struct))
|
|
{
|
|
for (TFieldIterator<FProperty> It(Struct); It; ++It)
|
|
{
|
|
if (CanBeExposed(*It, InBP))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
FNodeHandlingFunctor* UK2Node_MakeStruct::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
|
|
{
|
|
return new FKCHandler_MakeStruct(CompilerContext);
|
|
}
|
|
|
|
UK2Node::ERedirectType UK2Node_MakeStruct::DoPinsMatchForReconstruction(const UEdGraphPin* NewPin, int32 NewPinIndex, const UEdGraphPin* OldPin, int32 OldPinIndex) const
|
|
{
|
|
ERedirectType Result = UK2Node::DoPinsMatchForReconstruction(NewPin, NewPinIndex, OldPin, OldPinIndex);
|
|
if ((ERedirectType_None == Result) && DoRenamedPinsMatch(NewPin, OldPin, false))
|
|
{
|
|
Result = ERedirectType_Name;
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
void UK2Node_MakeStruct::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
|
|
{
|
|
Super::SetupMenuActions(ActionRegistrar, FMakeStructSpawnerAllowedDelegate::CreateStatic(&UK2Node_MakeStruct::CanBeMade), EGPD_Input);
|
|
}
|
|
|
|
FText UK2Node_MakeStruct::GetMenuCategory() const
|
|
{
|
|
return FEditorCategoryUtils::GetCommonCategory(FCommonEditorCategory::Struct);
|
|
}
|
|
|
|
void UK2Node_MakeStruct::PreSave(FObjectPreSaveContext SaveContext)
|
|
{
|
|
Super::PreSave(SaveContext);
|
|
UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForNode(this);
|
|
if (Blueprint && !Blueprint->bBeingCompiled)
|
|
{
|
|
bMadeAfterOverridePinRemoval = true;
|
|
}
|
|
}
|
|
|
|
void UK2Node_MakeStruct::PostPlacedNewNode()
|
|
{
|
|
Super::PostPlacedNewNode();
|
|
|
|
// New nodes automatically have this set.
|
|
bMadeAfterOverridePinRemoval = true;
|
|
}
|
|
|
|
void UK2Node_MakeStruct::Serialize(FArchive& Ar)
|
|
{
|
|
Super::Serialize(Ar);
|
|
|
|
if (Ar.IsLoading() && !Ar.IsTransacting() && !HasAllFlags(RF_Transient))
|
|
{
|
|
UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForNode(this);
|
|
if (Blueprint && !bMadeAfterOverridePinRemoval)
|
|
{
|
|
// Check if this node actually requires warning the user that functionality has changed.
|
|
bMadeAfterOverridePinRemoval = true;
|
|
if (StructType != nullptr)
|
|
{
|
|
FOptionalPinManager PinManager;
|
|
|
|
// Have to check if this node is even in danger.
|
|
for (FOptionalPinFromProperty& PropertyEntry : ShowPinForProperties)
|
|
{
|
|
FProperty* Property = StructType->FindPropertyByName(PropertyEntry.PropertyName);
|
|
bool bNegate = false;
|
|
if (FProperty* OverrideProperty = PropertyCustomizationHelpers::GetEditConditionProperty(Property, bNegate))
|
|
{
|
|
bool bHadOverridePropertySeparation = false;
|
|
for (FOptionalPinFromProperty& OverridePropertyEntry : ShowPinForProperties)
|
|
{
|
|
if (OverridePropertyEntry.PropertyName == OverrideProperty->GetFName())
|
|
{
|
|
bHadOverridePropertySeparation = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bMadeAfterOverridePinRemoval = false;
|
|
UEdGraphPin* Pin = FindPin(Property->GetFName());
|
|
|
|
if (bHadOverridePropertySeparation)
|
|
{
|
|
UEdGraphPin* OverridePin = FindPin(OverrideProperty->GetFName());
|
|
if (OverridePin)
|
|
{
|
|
// Override pins are always booleans
|
|
check(OverridePin->PinType.PinCategory == UEdGraphSchema_K2::PC_Boolean);
|
|
// If the old override pin's default value was true, then the override should be marked as enabled
|
|
PropertyEntry.bIsOverrideEnabled = OverridePin->DefaultValue.ToBool();
|
|
// It had an override pin, so conceptually the override pin is visible
|
|
PropertyEntry.bIsOverridePinVisible = true;
|
|
// Because there was an override pin visible for this property, this property will be forced to have a pin
|
|
PropertyEntry.bShowPin = true;
|
|
}
|
|
else
|
|
{
|
|
// No override pin, ensure all override bools are false
|
|
PropertyEntry.bIsOverrideEnabled = false;
|
|
PropertyEntry.bIsOverridePinVisible = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Pin)
|
|
{
|
|
PropertyEntry.bIsOverrideEnabled = true;
|
|
PropertyEntry.bIsOverridePinVisible = true;
|
|
}
|
|
}
|
|
|
|
// If the pin for this property, which sets the property's value, does not exist then the user was not trying to set the value
|
|
PropertyEntry.bIsSetValuePinVisible = Pin != nullptr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UK2Node_MakeStruct::ConvertDeprecatedNode(UEdGraph* Graph, bool bOnlySafeChanges)
|
|
{
|
|
const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
|
|
|
|
// User may have since deleted the struct type
|
|
if (StructType == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Check to see if the struct has a native make/break that we should try to convert to.
|
|
if (StructType->HasMetaData(FBlueprintMetadata::MD_NativeMakeFunction))
|
|
{
|
|
UFunction* MakeNodeFunction = nullptr;
|
|
|
|
// If any pins need to change their names during the conversion, add them to the map.
|
|
TMap<FName, FName> OldPinToNewPinMap;
|
|
|
|
if (StructType == TBaseStructure<FRotator>::Get())
|
|
{
|
|
MakeNodeFunction = UKismetMathLibrary::StaticClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED(UKismetMathLibrary, MakeRotator));
|
|
OldPinToNewPinMap.Add(TEXT("Rotator"), UEdGraphSchema_K2::PN_ReturnValue);
|
|
}
|
|
else if (StructType == TBaseStructure<FVector>::Get())
|
|
{
|
|
MakeNodeFunction = UKismetMathLibrary::StaticClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED_ThreeParams(UKismetMathLibrary, MakeVector, double, double, double));
|
|
OldPinToNewPinMap.Add(TEXT("Vector"), UEdGraphSchema_K2::PN_ReturnValue);
|
|
}
|
|
else if (StructType == TBaseStructure<FVector2D>::Get())
|
|
{
|
|
MakeNodeFunction = UKismetMathLibrary::StaticClass()->FindFunctionByName(GET_FUNCTION_NAME_CHECKED_TwoParams(UKismetMathLibrary, MakeVector2D, double, double));
|
|
OldPinToNewPinMap.Add(TEXT("Vector2D"), UEdGraphSchema_K2::PN_ReturnValue);
|
|
}
|
|
else
|
|
{
|
|
const FString& MetaData = StructType->GetMetaData(FBlueprintMetadata::MD_NativeMakeFunction);
|
|
MakeNodeFunction = FindObject<UFunction>(nullptr, *MetaData, true);
|
|
|
|
if (MakeNodeFunction)
|
|
{
|
|
OldPinToNewPinMap.Add(*StructType->GetName(), UEdGraphSchema_K2::PN_ReturnValue);
|
|
}
|
|
}
|
|
|
|
if (MakeNodeFunction)
|
|
{
|
|
Schema->ConvertDeprecatedNodeToFunctionCall(this, MakeNodeFunction, OldPinToNewPinMap, Graph);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|