You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Promote Resolve Soft Reference to the default category and change title to Make when going the opposite direction Move the UDN documentation node out of the top level category because end users never want it #rb ben.hoffman [CL 16270114 by ben zeigler in ue5-main branch]
353 lines
13 KiB
C++
353 lines
13 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "K2Node_ConvertAsset.h"
|
|
#include "EdGraph/EdGraphPin.h"
|
|
#include "Engine/Blueprint.h"
|
|
#include "Kismet/KismetSystemLibrary.h"
|
|
#include "Kismet2/BlueprintEditorUtils.h"
|
|
#include "EdGraphSchema_K2.h"
|
|
#include "K2Node_CallFunction.h"
|
|
#include "K2Node_DynamicCast.h"
|
|
#include "K2Node_ClassDynamicCast.h"
|
|
#include "KismetCompiler.h"
|
|
#include "BlueprintNodeSpawner.h"
|
|
#include "BlueprintFieldNodeSpawner.h"
|
|
#include "BlueprintActionDatabaseRegistrar.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "K2Node_ConvertAsset"
|
|
|
|
namespace UK2Node_ConvertAssetImpl
|
|
{
|
|
static const FName InputPinName("Input");
|
|
static const FName OutputPinName("Output");
|
|
}
|
|
|
|
UClass* UK2Node_ConvertAsset::GetTargetClass() const
|
|
{
|
|
UEdGraphPin* InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
|
|
bool bIsConnected = InputPin && InputPin->LinkedTo.Num() && InputPin->LinkedTo[0];
|
|
UEdGraphPin* SourcePin = bIsConnected ? InputPin->LinkedTo[0] : nullptr;
|
|
return SourcePin ? FBlueprintEditorUtils::GetTypeForPin(*SourcePin) : nullptr;
|
|
}
|
|
|
|
bool UK2Node_ConvertAsset::IsClassType() const
|
|
{
|
|
UEdGraphPin* InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
|
|
bool bIsConnected = InputPin && InputPin->LinkedTo.Num() && InputPin->LinkedTo[0];
|
|
UEdGraphPin* SourcePin = bIsConnected ? InputPin->LinkedTo[0] : nullptr;
|
|
return SourcePin ? (SourcePin->PinType.PinCategory == UEdGraphSchema_K2::PC_SoftClass || SourcePin->PinType.PinCategory == UEdGraphSchema_K2::PC_Class) : false;
|
|
}
|
|
|
|
bool UK2Node_ConvertAsset::IsConvertToSoft() const
|
|
{
|
|
UEdGraphPin* InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
|
|
bool bIsConnected = InputPin && InputPin->LinkedTo.Num() && InputPin->LinkedTo[0];
|
|
UEdGraphPin* SourcePin = bIsConnected ? InputPin->LinkedTo[0] : nullptr;
|
|
return SourcePin ? (SourcePin->PinType.PinCategory == UEdGraphSchema_K2::PC_Class || SourcePin->PinType.PinCategory == UEdGraphSchema_K2::PC_Object) : false;
|
|
}
|
|
|
|
bool UK2Node_ConvertAsset::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason) const
|
|
{
|
|
UEdGraphPin* InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
|
|
if (InputPin && OtherPin && (InputPin == MyPin) && (MyPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard))
|
|
{
|
|
if ((OtherPin->PinType.PinCategory != UEdGraphSchema_K2::PC_SoftObject) &&
|
|
(OtherPin->PinType.PinCategory != UEdGraphSchema_K2::PC_SoftClass) &&
|
|
(OtherPin->PinType.PinCategory != UEdGraphSchema_K2::PC_Object) &&
|
|
(OtherPin->PinType.PinCategory != UEdGraphSchema_K2::PC_Class))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void UK2Node_ConvertAsset::RefreshPinTypes()
|
|
{
|
|
const UEdGraphSchema_K2* K2Schema = CastChecked<UEdGraphSchema_K2>(GetSchema());
|
|
UEdGraphPin* InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
|
|
UEdGraphPin* OutputPin = FindPin(UK2Node_ConvertAssetImpl::OutputPinName);
|
|
ensure(InputPin && OutputPin);
|
|
if (InputPin && OutputPin)
|
|
{
|
|
const bool bIsConnected = InputPin->LinkedTo.Num() > 0;
|
|
UClass* TargetType = bIsConnected ? GetTargetClass() : nullptr;
|
|
const bool bIsClassType = bIsConnected ? IsClassType() : false;
|
|
const bool bIsConvertToSoft = bIsConnected ? IsConvertToSoft() : false;
|
|
|
|
FName InputCategory = UEdGraphSchema_K2::PC_Wildcard;
|
|
FName OutputCategory = UEdGraphSchema_K2::PC_Wildcard;
|
|
if (bIsConnected)
|
|
{
|
|
if (bIsConvertToSoft)
|
|
{
|
|
InputCategory = (bIsClassType ? UEdGraphSchema_K2::PC_Class : UEdGraphSchema_K2::PC_Object);
|
|
OutputCategory = (bIsClassType ? UEdGraphSchema_K2::PC_SoftClass : UEdGraphSchema_K2::PC_SoftObject);
|
|
}
|
|
else
|
|
{
|
|
InputCategory = (bIsClassType ? UEdGraphSchema_K2::PC_SoftClass : UEdGraphSchema_K2::PC_SoftObject);
|
|
OutputCategory = (bIsClassType ? UEdGraphSchema_K2::PC_Class : UEdGraphSchema_K2::PC_Object);
|
|
}
|
|
}
|
|
|
|
InputPin->PinType = FEdGraphPinType(InputCategory, NAME_None, TargetType, EPinContainerType::None, false, FEdGraphTerminalType() );
|
|
OutputPin->PinType = FEdGraphPinType(OutputCategory, NAME_None, TargetType, EPinContainerType::None, false, FEdGraphTerminalType() );
|
|
|
|
PinTypeChanged(InputPin);
|
|
PinTypeChanged(OutputPin);
|
|
|
|
if (OutputPin->LinkedTo.Num())
|
|
{
|
|
TArray<UEdGraphPin*> PinsToUnlink = OutputPin->LinkedTo;
|
|
|
|
UClass const* CallingContext = nullptr;
|
|
if (UBlueprint const* Blueprint = GetBlueprint())
|
|
{
|
|
CallingContext = Blueprint->GeneratedClass;
|
|
if (CallingContext == NULL)
|
|
{
|
|
CallingContext = Blueprint->ParentClass;
|
|
}
|
|
}
|
|
|
|
for (UEdGraphPin* TargetPin : PinsToUnlink)
|
|
{
|
|
if (TargetPin && !K2Schema->ArePinsCompatible(OutputPin, TargetPin, CallingContext))
|
|
{
|
|
OutputPin->BreakLinkTo(TargetPin);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UK2Node_ConvertAsset::PostReconstructNode()
|
|
{
|
|
RefreshPinTypes();
|
|
|
|
Super::PostReconstructNode();
|
|
}
|
|
|
|
void UK2Node_ConvertAsset::NotifyPinConnectionListChanged(UEdGraphPin* Pin)
|
|
{
|
|
Super::NotifyPinConnectionListChanged(Pin);
|
|
if (Pin && (UK2Node_ConvertAssetImpl::InputPinName == Pin->PinName))
|
|
{
|
|
RefreshPinTypes();
|
|
|
|
GetGraph()->NotifyGraphChanged();
|
|
}
|
|
}
|
|
|
|
void UK2Node_ConvertAsset::AllocateDefaultPins()
|
|
{
|
|
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, UK2Node_ConvertAssetImpl::InputPinName);
|
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Wildcard, UK2Node_ConvertAssetImpl::OutputPinName);
|
|
}
|
|
|
|
UK2Node::ERedirectType UK2Node_ConvertAsset::DoPinsMatchForReconstruction(const UEdGraphPin* NewPin, int32 NewPinIndex, const UEdGraphPin* OldPin, int32 OldPinIndex) const
|
|
{
|
|
// Names changed, only thing that matters is the direction
|
|
if (NewPin->Direction == OldPin->Direction)
|
|
{
|
|
return UK2Node::ERedirectType_Name;
|
|
}
|
|
return UK2Node::ERedirectType_None;
|
|
}
|
|
|
|
void UK2Node_ConvertAsset::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
|
|
{
|
|
struct GetMenuActions_Utils
|
|
{
|
|
static void OverrideUI(FBlueprintActionContext const& Context, IBlueprintNodeBinder::FBindingSet const& /*Bindings*/, FBlueprintActionUiSpec* UiSpecOut)
|
|
{
|
|
bool bShouldPromote = false;
|
|
bool bIsMakeSoft = false;
|
|
for (UEdGraphPin* Pin : Context.Pins)
|
|
{
|
|
// Auto promote for soft refs
|
|
if (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_SoftClass || Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_SoftObject)
|
|
{
|
|
if (Pin->Direction == EGPD_Output)
|
|
{
|
|
// The wildcards don't get set when connecting right side, so don't promote
|
|
bShouldPromote = true;
|
|
}
|
|
}
|
|
|
|
// Change title for hard refs
|
|
if (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Class || Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Object)
|
|
{
|
|
if (Pin->Direction == EGPD_Output)
|
|
{
|
|
bIsMakeSoft = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bShouldPromote)
|
|
{
|
|
UiSpecOut->Category = NSLOCTEXT("BlueprintFunctionNodeSpawner", "EmptyFunctionCategory", "|");
|
|
}
|
|
if (bIsMakeSoft)
|
|
{
|
|
UiSpecOut->MenuName = LOCTEXT("MakeSoftTitle", "Make Soft Reference");
|
|
}
|
|
}
|
|
};
|
|
|
|
UClass* ActionKey = GetClass();
|
|
if (ActionRegistrar.IsOpenForRegistration(ActionKey))
|
|
{
|
|
UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
|
|
check(NodeSpawner != nullptr);
|
|
NodeSpawner->DynamicUiSignatureGetter = UBlueprintFieldNodeSpawner::FUiSpecOverrideDelegate::CreateStatic(GetMenuActions_Utils::OverrideUI);
|
|
|
|
ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
|
|
}
|
|
}
|
|
|
|
void UK2Node_ConvertAsset::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
|
|
{
|
|
Super::ExpandNode(CompilerContext, SourceGraph);
|
|
const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
|
|
|
|
UClass* TargetType = GetTargetClass();
|
|
if (TargetType && Schema && (2 == Pins.Num()))
|
|
{
|
|
const bool bIsClassType = IsClassType();
|
|
UClass *TargetClass = GetTargetClass();
|
|
bool bIsErrorFree = true;
|
|
|
|
if (IsConvertToSoft())
|
|
{
|
|
//Create Convert Function
|
|
UK2Node_CallFunction* ConvertToObjectFunc = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
|
|
FName ConvertFunctionName = bIsClassType
|
|
? GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, Conv_ClassToSoftClassReference)
|
|
: GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, Conv_ObjectToSoftObjectReference);
|
|
|
|
ConvertToObjectFunc->FunctionReference.SetExternalMember(ConvertFunctionName, UKismetSystemLibrary::StaticClass());
|
|
ConvertToObjectFunc->AllocateDefaultPins();
|
|
|
|
//Connect input to convert
|
|
UEdGraphPin* InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
|
|
const FName ConvertInputName = bIsClassType ? FName(TEXT("Class")) : FName(TEXT("Object"));
|
|
UEdGraphPin* ConvertInput = ConvertToObjectFunc->FindPin(ConvertInputName);
|
|
bIsErrorFree = InputPin && ConvertInput && CompilerContext.MovePinLinksToIntermediate(*InputPin, *ConvertInput).CanSafeConnect();
|
|
|
|
if (UEdGraphPin* ConvertOutput = ConvertToObjectFunc->GetReturnValuePin())
|
|
{
|
|
// Force the convert output pin to the right type. This is only safe because all asset ptrs are type-compatible, the cast is done at resolution time
|
|
ConvertOutput->PinType.PinSubCategoryObject = TargetClass;
|
|
|
|
UEdGraphPin* OutputPin = FindPin(UK2Node_ConvertAssetImpl::OutputPinName);
|
|
bIsErrorFree &= OutputPin && CompilerContext.MovePinLinksToIntermediate(*OutputPin, *ConvertOutput).CanSafeConnect();
|
|
}
|
|
else
|
|
{
|
|
bIsErrorFree = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Create Convert Function
|
|
UK2Node_CallFunction* ConvertToObjectFunc = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
|
|
FName ConvertFunctionName = bIsClassType
|
|
? GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, Conv_SoftClassReferenceToClass)
|
|
: GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, Conv_SoftObjectReferenceToObject);
|
|
|
|
ConvertToObjectFunc->FunctionReference.SetExternalMember(ConvertFunctionName, UKismetSystemLibrary::StaticClass());
|
|
ConvertToObjectFunc->AllocateDefaultPins();
|
|
|
|
//Connect input to convert
|
|
UEdGraphPin* InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
|
|
const FName ConvertInputName = bIsClassType ? FName(TEXT("SoftClass")) : FName(TEXT("SoftObject"));
|
|
UEdGraphPin* ConvertInput = ConvertToObjectFunc->FindPin(ConvertInputName);
|
|
bIsErrorFree = InputPin && ConvertInput && CompilerContext.MovePinLinksToIntermediate(*InputPin, *ConvertInput).CanSafeConnect();
|
|
|
|
UEdGraphPin* ConvertOutput = ConvertToObjectFunc->GetReturnValuePin();
|
|
UEdGraphPin* InnerOutput = nullptr;
|
|
if (UObject::StaticClass() != TargetType)
|
|
{
|
|
//Create Cast Node
|
|
UK2Node_DynamicCast* CastNode = bIsClassType
|
|
? CompilerContext.SpawnIntermediateNode<UK2Node_ClassDynamicCast>(this, SourceGraph)
|
|
: CompilerContext.SpawnIntermediateNode<UK2Node_DynamicCast>(this, SourceGraph);
|
|
CastNode->SetPurity(true);
|
|
CastNode->TargetType = TargetType;
|
|
CastNode->AllocateDefaultPins();
|
|
|
|
// Connect Object/Class to Cast
|
|
UEdGraphPin* CastInput = CastNode->GetCastSourcePin();
|
|
bIsErrorFree &= ConvertOutput && CastInput && Schema->TryCreateConnection(ConvertOutput, CastInput);
|
|
|
|
// Connect output to cast
|
|
InnerOutput = CastNode->GetCastResultPin();
|
|
}
|
|
else
|
|
{
|
|
InnerOutput = ConvertOutput;
|
|
}
|
|
|
|
UEdGraphPin* OutputPin = FindPin(UK2Node_ConvertAssetImpl::OutputPinName);
|
|
bIsErrorFree &= OutputPin && InnerOutput && CompilerContext.MovePinLinksToIntermediate(*OutputPin, *InnerOutput).CanSafeConnect();
|
|
}
|
|
|
|
if (!bIsErrorFree)
|
|
{
|
|
CompilerContext.MessageLog.Error(*LOCTEXT("InternalConnectionError", "K2Node_ConvertAsset: Internal connection error. @@").ToString(), this);
|
|
}
|
|
|
|
BreakAllNodeLinks();
|
|
}
|
|
}
|
|
|
|
FText UK2Node_ConvertAsset::GetCompactNodeTitle() const
|
|
{
|
|
return FText::FromString(TEXT("\x2022"));
|
|
}
|
|
|
|
FText UK2Node_ConvertAsset::GetMenuCategory() const
|
|
{
|
|
return LOCTEXT("UK2Node_LoadAssetGetMenuCategory", "Utilities");
|
|
}
|
|
|
|
FText UK2Node_ConvertAsset::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
|
{
|
|
const bool bIsConvertToSoft = IsConvertToSoft();
|
|
|
|
if (bIsConvertToSoft)
|
|
{
|
|
return LOCTEXT("MakeSoftTitle", "Make Soft Reference");
|
|
}
|
|
|
|
return LOCTEXT("UK2Node_ConvertAssetGetNodeTitle", "Resolve Soft Reference");
|
|
}
|
|
|
|
FText UK2Node_ConvertAsset::GetKeywords() const
|
|
{
|
|
// Return old name here
|
|
return LOCTEXT("UK2Node_ConvertAssetGetKeywords", "Resolve Asset ID Convert Soft");
|
|
}
|
|
|
|
FText UK2Node_ConvertAsset::GetTooltipText() const
|
|
{
|
|
UEdGraphPin* InputPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
|
|
const bool bIsConvertToSoft = IsConvertToSoft();
|
|
if (bIsConvertToSoft)
|
|
{
|
|
return LOCTEXT("MakeSoftTooltip", "Takes a hard Class or Object reference and makes a Soft Reference.");
|
|
}
|
|
else if (InputPin && InputPin->LinkedTo.Num() > 0)
|
|
{
|
|
return LOCTEXT("UK2Node_ConvertAssetGetTooltipText", "Resolves a Soft Reference and gets the Class or Object it is pointing to. If the object isn't already loaded in memory this will return none.");
|
|
}
|
|
|
|
return LOCTEXT("UnknownTypeTooltip", "Resolves or makes a Soft Reference, connect a soft or hard reference to the input pin.");
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|