You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Implemented unresolve as well as re-resolve node on already typed pins Added UI in contextual menu to re-type pins #rb sara.schvartzman #jira UE-125892 #preflight https://horde.devtools.epicgames.com/job/622f488f505788e09ffffbe4 [CL 19372564 by Helge Mathee in ue5-main branch]
365 lines
8.7 KiB
C++
365 lines
8.7 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "RigVMModel/Nodes/RigVMTemplateNode.h"
|
|
|
|
#include "RigVMModel/RigVMController.h"
|
|
|
|
URigVMTemplateNode::URigVMTemplateNode()
|
|
: Super()
|
|
, TemplateNotation(NAME_None)
|
|
, ResolvedFunctionName()
|
|
, CachedTemplate(nullptr)
|
|
, CachedFunction(nullptr)
|
|
{
|
|
}
|
|
|
|
UScriptStruct* URigVMTemplateNode::GetScriptStruct() const
|
|
{
|
|
if(const FRigVMFunction* Function = GetResolvedFunction())
|
|
{
|
|
return Function->Struct;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
FString URigVMTemplateNode::GetNodeTitle() const
|
|
{
|
|
if(!IsResolved())
|
|
{
|
|
if(const FRigVMTemplate* Template = GetTemplate())
|
|
{
|
|
return Template->GetName().ToString();
|
|
}
|
|
}
|
|
|
|
FString ResolvedNodeTitle = Super::GetNodeTitle();
|
|
|
|
const int32 BracePos = ResolvedNodeTitle.Find(TEXT(" ("));
|
|
if(BracePos != INDEX_NONE)
|
|
{
|
|
ResolvedNodeTitle = ResolvedNodeTitle.Left(BracePos);
|
|
}
|
|
|
|
return ResolvedNodeTitle;
|
|
}
|
|
|
|
FName URigVMTemplateNode::GetMethodName() const
|
|
{
|
|
if(const FRigVMFunction* Function = GetResolvedFunction())
|
|
{
|
|
return Function->GetMethodName();
|
|
}
|
|
return NAME_None;
|
|
}
|
|
|
|
FText URigVMTemplateNode::GetToolTipText() const
|
|
{
|
|
if(const FRigVMTemplate* Template = GetTemplate())
|
|
{
|
|
const TArray<int32> PermutationIndices = GetResolvedPermutationIndices();
|
|
return Template->GetTooltipText(PermutationIndices);
|
|
}
|
|
return Super::GetToolTipText();
|
|
}
|
|
|
|
FText URigVMTemplateNode::GetToolTipTextForPin(const URigVMPin* InPin) const
|
|
{
|
|
const FText SuperToolTip = Super::GetToolTipTextForPin(InPin);
|
|
if (const FRigVMTemplate* Template = GetTemplate())
|
|
{
|
|
const URigVMPin* RootPin = InPin->GetRootPin();
|
|
if (RootPin->IsWildCard())
|
|
{
|
|
if (const FRigVMTemplateArgument* Arg = Template->FindArgument(RootPin->GetFName()))
|
|
{
|
|
const TArray<int32> PermutationIndices = GetResolvedPermutationIndices();
|
|
const FString SupportedTypesJoined = FString::Join(Arg->GetSupportedTypeStrings(PermutationIndices), TEXT("\n"));
|
|
FString Tooltip = TEXT("Supported Types:\n\n") + SupportedTypesJoined;
|
|
|
|
if(!SuperToolTip.IsEmpty())
|
|
{
|
|
Tooltip += TEXT("\n\n") + SuperToolTip.ToString();
|
|
}
|
|
|
|
return FText::FromString(Tooltip);
|
|
}
|
|
}
|
|
}
|
|
return SuperToolTip;
|
|
}
|
|
|
|
FName URigVMTemplateNode::GetNotation() const
|
|
{
|
|
return TemplateNotation;
|
|
}
|
|
|
|
bool URigVMTemplateNode::SupportsType(const URigVMPin* InPin, const FString& InCPPType, FString* OutCPPType)
|
|
{
|
|
static const FString WildCardCPPType = RigVMTypeUtils::GetWildCardCPPType();
|
|
static const FString WildCardArrayCPPType = RigVMTypeUtils::ArrayTypeFromBaseType(WildCardCPPType);
|
|
|
|
const URigVMPin* RootPin = InPin->GetRootPin();
|
|
|
|
// we always support the unknown type
|
|
if(((InCPPType == WildCardCPPType) && !InPin->IsArray()) ||
|
|
((InCPPType == WildCardArrayCPPType) && InPin->IsArray()))
|
|
{
|
|
if(const FRigVMTemplate* Template = GetTemplate())
|
|
{
|
|
if(const FRigVMTemplateArgument* Argument = Template->FindArgument(RootPin->GetFName()))
|
|
{
|
|
// support this only on non-singleton arguments
|
|
if(Argument->IsSingleton())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(OutCPPType)
|
|
{
|
|
*OutCPPType = InCPPType;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
FString CPPType = InCPPType;
|
|
|
|
if(InPin->GetParentPin() == RootPin && RootPin->IsArray())
|
|
{
|
|
CPPType = RigVMTypeUtils::ArrayTypeFromBaseType(CPPType);
|
|
}
|
|
|
|
if (const FRigVMTemplate* Template = GetTemplate())
|
|
{
|
|
const FString CacheKey = RootPin->GetName() + TEXT("|") + CPPType;
|
|
if (const TPair<bool, FRigVMTemplateArgument::FType>* CachedResult = SupportedTypesCache.Find(CacheKey))
|
|
{
|
|
if(OutCPPType)
|
|
{
|
|
*OutCPPType = CachedResult->Value.CPPType;
|
|
}
|
|
return CachedResult->Key;
|
|
}
|
|
|
|
FRigVMTemplate::FTypeMap Types;
|
|
|
|
for (URigVMPin* Pin : GetPins())
|
|
{
|
|
if (Pin == RootPin)
|
|
{
|
|
continue;
|
|
}
|
|
if (Pin->IsWildCard())
|
|
{
|
|
continue;
|
|
}
|
|
Types.Add(Pin->GetFName(), Pin->GetTemplateArgumentType());
|
|
}
|
|
|
|
FRigVMTemplateArgument::FType ResolvedType;
|
|
bool bSupportsType = false;
|
|
if(RootPin->IsWildCard())
|
|
{
|
|
bSupportsType = Template->ArgumentSupportsType(RootPin->GetFName(), CPPType, Types, &ResolvedType);
|
|
}
|
|
else
|
|
{
|
|
FRigVMTemplate::FTypeMap ResolvedTypes;
|
|
bSupportsType = Template->ResolveArgument(RootPin->GetFName(), FRigVMTemplateArgument::FType(CPPType), ResolvedTypes);
|
|
if(bSupportsType)
|
|
{
|
|
ResolvedType = ResolvedTypes.FindChecked(RootPin->GetFName());
|
|
}
|
|
}
|
|
|
|
SupportedTypesCache.Add(CacheKey, TPair<bool, FRigVMTemplateArgument::FType>(bSupportsType, ResolvedType));
|
|
if(OutCPPType)
|
|
{
|
|
*OutCPPType = ResolvedType.CPPType;
|
|
}
|
|
return bSupportsType;
|
|
}
|
|
|
|
if(RootPin->GetCPPType() == CPPType)
|
|
{
|
|
if(OutCPPType)
|
|
{
|
|
*OutCPPType = CPPType;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool URigVMTemplateNode::GetTypeMapForNewPinType(const URigVMPin* InPin, const FString& InCPPType, UObject* InCPPTypeObject,
|
|
FRigVMTemplate::FTypeMap& OutTypes) const
|
|
{
|
|
check(InPin);
|
|
check(InPin->GetNode() == this);
|
|
check(InPin->IsRootPin());
|
|
|
|
if(const FRigVMTemplate* Template = GetTemplate())
|
|
{
|
|
OutTypes = GetResolvedTypes();
|
|
const FRigVMTemplateArgument::FType ExpectedType(InCPPType, InCPPTypeObject);
|
|
return GetTemplate()->ResolveArgument(InPin->GetFName(), ExpectedType, OutTypes);
|
|
}
|
|
|
|
OutTypes.Reset();
|
|
return false;
|
|
}
|
|
|
|
TArray<int32> URigVMTemplateNode::GetResolvedPermutationIndices(FRigVMTemplate::FTypeMap* OutTypes) const
|
|
{
|
|
if (const FRigVMTemplate* Template = GetTemplate())
|
|
{
|
|
FRigVMTemplate::FTypeMap Types = GetResolvedTypes();
|
|
TArray<int32> PermutationIndices;
|
|
Template->Resolve(Types, PermutationIndices, false);
|
|
|
|
if (OutTypes)
|
|
{
|
|
*OutTypes = Types;
|
|
}
|
|
|
|
return PermutationIndices;
|
|
}
|
|
return TArray<int32>();
|
|
}
|
|
|
|
TArray<const FRigVMFunction*> URigVMTemplateNode::GetResolvedPermutations(FRigVMTemplate::FTypeMap* OutTypes) const
|
|
{
|
|
TArray<int32> Indices = GetResolvedPermutationIndices(OutTypes);
|
|
TArray<const FRigVMFunction*> Functions;
|
|
for(const int32 Index : Indices)
|
|
{
|
|
Functions.Add(GetTemplate()->GetPermutation(Index));
|
|
}
|
|
return Functions;
|
|
}
|
|
|
|
const FRigVMTemplate* URigVMTemplateNode::GetTemplate() const
|
|
{
|
|
if(CachedTemplate == nullptr)
|
|
{
|
|
CachedTemplate = FRigVMRegistry::Get().FindTemplate(TemplateNotation);
|
|
}
|
|
return CachedTemplate;
|
|
}
|
|
|
|
FRigVMTemplate::FTypeMap URigVMTemplateNode::GetResolvedTypes() const
|
|
{
|
|
FRigVMTemplate::FTypeMap Types;
|
|
for (URigVMPin* Pin : GetPins())
|
|
{
|
|
if (Pin->IsWildCard())
|
|
{
|
|
continue;
|
|
}
|
|
Types.Add(Pin->GetFName(), Pin->GetTemplateArgumentType());
|
|
}
|
|
return Types;
|
|
}
|
|
|
|
const FRigVMFunction* URigVMTemplateNode::GetResolvedFunction() const
|
|
{
|
|
if(CachedFunction == nullptr)
|
|
{
|
|
if(!ResolvedFunctionName.IsEmpty())
|
|
{
|
|
CachedFunction = FRigVMRegistry::Get().FindFunction(*ResolvedFunctionName);
|
|
}
|
|
|
|
if(CachedFunction == nullptr)
|
|
{
|
|
TArray<int32> PermutationIndices = GetResolvedPermutationIndices();
|
|
if(PermutationIndices.Num() == 1)
|
|
{
|
|
CachedFunction = GetTemplate()->GetPermutation(PermutationIndices[0]);
|
|
}
|
|
}
|
|
}
|
|
return CachedFunction;
|
|
}
|
|
|
|
bool URigVMTemplateNode::IsResolved() const
|
|
{
|
|
return GetScriptStruct() != nullptr;
|
|
}
|
|
|
|
bool URigVMTemplateNode::IsFullyUnresolved() const
|
|
{
|
|
check(GetTemplate());
|
|
|
|
// all permutations are available means we haven't resolved any wildcard pin
|
|
return GetResolvedPermutations().Num() == GetTemplate()->NumPermutations();
|
|
}
|
|
|
|
TArray<UScriptStruct*> URigVMTemplateNode::GetSupportedUnitStructs() const
|
|
{
|
|
if(const FRigVMTemplate* Template = GetTemplate())
|
|
{
|
|
return URigVMController::GetUnitStructsForTemplate(Template->GetNotation());
|
|
}
|
|
return TArray<UScriptStruct*>();
|
|
}
|
|
|
|
FString URigVMTemplateNode::GetInitialDefaultValueForPin(const FName& InRootPinName, const TArray<int32>& InPermutationIndices) const
|
|
{
|
|
if(GetTemplate() == nullptr)
|
|
{
|
|
return FString();
|
|
}
|
|
|
|
TArray<int32> PermutationIndices = InPermutationIndices;
|
|
if(PermutationIndices.IsEmpty())
|
|
{
|
|
PermutationIndices = GetResolvedPermutationIndices();
|
|
}
|
|
|
|
FString DefaultValue;
|
|
|
|
for(const int32 PermutationIndex : PermutationIndices)
|
|
{
|
|
const FRigVMFunction* Permutation = GetTemplate()->GetPermutation(PermutationIndex);
|
|
check(Permutation);
|
|
|
|
const TSharedPtr<FStructOnScope> StructOnScope = MakeShareable(new FStructOnScope(Permutation->Struct));
|
|
const FRigVMStruct* DefaultStruct = (const FRigVMStruct*)StructOnScope->GetStructMemory();
|
|
|
|
const FString NewDefaultValue = DefaultStruct->ExportToFullyQualifiedText(
|
|
Cast<UScriptStruct>(StructOnScope->GetStruct()), InRootPinName);
|
|
|
|
if(!NewDefaultValue.IsEmpty())
|
|
{
|
|
if(DefaultValue.IsEmpty())
|
|
{
|
|
DefaultValue = NewDefaultValue;
|
|
}
|
|
else if(!NewDefaultValue.Equals(DefaultValue))
|
|
{
|
|
return FString();
|
|
}
|
|
}
|
|
}
|
|
|
|
return DefaultValue;
|
|
}
|
|
|
|
void URigVMTemplateNode::InvalidateCache()
|
|
{
|
|
SupportedTypesCache.Reset();
|
|
CachedFunction = nullptr;
|
|
|
|
for(URigVMPin* Pin : GetPins())
|
|
{
|
|
if(Pin->IsWildCard())
|
|
{
|
|
ResolvedFunctionName.Reset();
|
|
break;
|
|
}
|
|
}
|
|
}
|