2019-12-26 15:33:43 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2019-09-17 19:12:19 -04:00
|
|
|
|
|
|
|
|
#include "RigVMModel/RigVMGraph.h"
|
2021-01-06 14:01:38 -04:00
|
|
|
#include "RigVMModel/RigVMFunctionLibrary.h"
|
2019-09-17 19:12:19 -04:00
|
|
|
#include "RigVMModel/RigVMController.h"
|
2020-12-07 07:55:48 -04:00
|
|
|
#include "RigVMModel/Nodes/RigVMLibraryNode.h"
|
2020-12-14 08:58:12 -04:00
|
|
|
#include "RigVMModel/Nodes/RigVMFunctionEntryNode.h"
|
|
|
|
|
#include "RigVMModel/Nodes/RigVMFunctionReturnNode.h"
|
2019-09-17 19:12:19 -04:00
|
|
|
#include "UObject/Package.h"
|
2021-11-18 08:00:07 -05:00
|
|
|
#include "RigVMTypeUtils.h"
|
2019-09-17 19:12:19 -04:00
|
|
|
|
|
|
|
|
URigVMGraph::URigVMGraph()
|
2020-01-22 17:58:55 -05:00
|
|
|
: DiagnosticsAST(nullptr)
|
|
|
|
|
, RuntimeAST(nullptr)
|
2022-03-30 05:21:45 -04:00
|
|
|
, bEditable(true)
|
2019-09-17 19:12:19 -04:00
|
|
|
{
|
2022-04-21 09:10:19 -04:00
|
|
|
SetExecuteContextStruct(FRigVMExecuteContext::StaticStruct());
|
2019-09-17 19:12:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TArray<URigVMNode*>& URigVMGraph::GetNodes() const
|
|
|
|
|
{
|
|
|
|
|
return Nodes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TArray<URigVMLink*>& URigVMGraph::GetLinks() const
|
|
|
|
|
{
|
|
|
|
|
return Links;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-07 07:55:48 -04:00
|
|
|
TArray<URigVMGraph*> URigVMGraph::GetContainedGraphs(bool bRecursive) const
|
|
|
|
|
{
|
|
|
|
|
TArray<URigVMGraph*> Graphs;
|
|
|
|
|
for (URigVMNode* Node : GetNodes())
|
|
|
|
|
{
|
2021-01-14 15:00:40 -04:00
|
|
|
if (URigVMCollapseNode* CollapseNode = Cast<URigVMCollapseNode>(Node))
|
2020-12-07 07:55:48 -04:00
|
|
|
{
|
2021-01-14 15:00:40 -04:00
|
|
|
Graphs.Add(CollapseNode->GetContainedGraph());
|
2020-12-07 07:55:48 -04:00
|
|
|
if (bRecursive)
|
|
|
|
|
{
|
2021-01-14 15:00:40 -04:00
|
|
|
Graphs.Append(CollapseNode->GetContainedGraph()->GetContainedGraphs(true));
|
2020-12-07 07:55:48 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Graphs;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-19 06:35:50 -04:00
|
|
|
URigVMGraph* URigVMGraph::GetParentGraph() const
|
|
|
|
|
{
|
|
|
|
|
if(URigVMCollapseNode* CollapseNode = Cast<URigVMCollapseNode>(GetOuter()))
|
|
|
|
|
{
|
|
|
|
|
return CollapseNode->GetGraph();
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
URigVMGraph* URigVMGraph::GetRootGraph() const
|
|
|
|
|
{
|
|
|
|
|
if(URigVMGraph* ParentGraph = GetParentGraph())
|
|
|
|
|
{
|
|
|
|
|
return ParentGraph->GetRootGraph();
|
|
|
|
|
}
|
|
|
|
|
return (URigVMGraph*)this;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 03:19:42 -04:00
|
|
|
bool URigVMGraph::IsRootGraph() const
|
|
|
|
|
{
|
|
|
|
|
return GetRootGraph() == this;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 08:58:12 -04:00
|
|
|
URigVMFunctionEntryNode* URigVMGraph::GetEntryNode() const
|
|
|
|
|
{
|
|
|
|
|
for (URigVMNode* Node : Nodes)
|
|
|
|
|
{
|
|
|
|
|
if (URigVMFunctionEntryNode* EntryNode = Cast<URigVMFunctionEntryNode>(Node))
|
|
|
|
|
{
|
|
|
|
|
return EntryNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
URigVMFunctionReturnNode* URigVMGraph::GetReturnNode() const
|
|
|
|
|
{
|
|
|
|
|
for (URigVMNode* Node : Nodes)
|
|
|
|
|
{
|
|
|
|
|
if (URigVMFunctionReturnNode* ReturnNode = Cast<URigVMFunctionReturnNode>(Node))
|
|
|
|
|
{
|
|
|
|
|
return ReturnNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-17 19:12:19 -04:00
|
|
|
TArray<FRigVMGraphVariableDescription> URigVMGraph::GetVariableDescriptions() const
|
|
|
|
|
{
|
|
|
|
|
TArray<FRigVMGraphVariableDescription> Variables;
|
|
|
|
|
for (URigVMNode* Node : Nodes)
|
|
|
|
|
{
|
|
|
|
|
if (URigVMVariableNode* VariableNode = Cast<URigVMVariableNode>(Node))
|
|
|
|
|
{
|
|
|
|
|
Variables.AddUnique(VariableNode->GetVariableDescription());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Variables;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-07 11:12:11 -04:00
|
|
|
FString URigVMGraph::GetNodePath() const
|
|
|
|
|
{
|
|
|
|
|
if (URigVMCollapseNode* CollapseNode = Cast<URigVMCollapseNode>(GetOuter()))
|
|
|
|
|
{
|
2020-12-14 08:58:12 -04:00
|
|
|
return CollapseNode->GetNodePath(true /* recursive */);
|
|
|
|
|
}
|
2022-05-31 04:27:20 -04:00
|
|
|
|
|
|
|
|
static constexpr TCHAR NodePathFormat[] = TEXT("%s::");
|
|
|
|
|
return FString::Printf(NodePathFormat, *GetName());
|
2020-12-14 08:58:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FString URigVMGraph::GetGraphName() const
|
|
|
|
|
{
|
|
|
|
|
if (URigVMCollapseNode* CollapseNode = Cast<URigVMCollapseNode>(GetOuter()))
|
|
|
|
|
{
|
|
|
|
|
return CollapseNode->GetNodePath(false /* recursive */);
|
2020-12-07 11:12:11 -04:00
|
|
|
}
|
2022-05-31 04:27:20 -04:00
|
|
|
return GetName();
|
2020-12-07 11:12:11 -04:00
|
|
|
}
|
|
|
|
|
|
2019-09-17 19:12:19 -04:00
|
|
|
URigVMNode* URigVMGraph::FindNodeByName(const FName& InNodeName) const
|
|
|
|
|
{
|
|
|
|
|
for (URigVMNode* Node : Nodes)
|
|
|
|
|
{
|
2020-09-01 14:07:48 -04:00
|
|
|
if (Node == nullptr)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-17 19:12:19 -04:00
|
|
|
if (Node->GetFName() == InNodeName)
|
|
|
|
|
{
|
|
|
|
|
return Node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
URigVMNode* URigVMGraph::FindNode(const FString& InNodePath) const
|
|
|
|
|
{
|
2020-12-14 08:58:12 -04:00
|
|
|
if (InNodePath.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-09 11:31:17 -05:00
|
|
|
FString Path = InNodePath;
|
2022-05-31 04:27:20 -04:00
|
|
|
|
|
|
|
|
if(IsRootGraph())
|
2021-11-09 11:31:17 -05:00
|
|
|
{
|
2022-05-31 04:27:20 -04:00
|
|
|
const FString MyNodePath = GetNodePath();
|
|
|
|
|
if(Path.StartsWith(MyNodePath))
|
2021-11-09 11:31:17 -05:00
|
|
|
{
|
2022-05-31 04:27:20 -04:00
|
|
|
Path.RightChopInline(MyNodePath.Len() + 1);
|
2021-11-09 11:31:17 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FString Left = Path, Right;
|
|
|
|
|
URigVMNode::SplitNodePathAtStart(Path, Left, Right);
|
2020-12-14 08:58:12 -04:00
|
|
|
|
|
|
|
|
if (Right.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
return FindNodeByName(*Left);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (URigVMLibraryNode* LibraryNode = Cast< URigVMLibraryNode>(FindNodeByName(*Left)))
|
|
|
|
|
{
|
|
|
|
|
return LibraryNode->GetContainedGraph()->FindNode(Right);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
2019-09-17 19:12:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
URigVMPin* URigVMGraph::FindPin(const FString& InPinPath) const
|
|
|
|
|
{
|
|
|
|
|
FString Left, Right;
|
|
|
|
|
if (!URigVMPin::SplitPinPathAtStart(InPinPath, Left, Right))
|
|
|
|
|
{
|
|
|
|
|
Left = InPinPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
URigVMNode* Node = FindNode(Left);
|
|
|
|
|
if (Node)
|
|
|
|
|
{
|
|
|
|
|
return Node->FindPin(Right);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
URigVMLink* URigVMGraph::FindLink(const FString& InLinkPinPathRepresentation) const
|
|
|
|
|
{
|
|
|
|
|
for(URigVMLink* Link : Links)
|
|
|
|
|
{
|
|
|
|
|
if(Link->GetPinPathRepresentation() == InLinkPinPathRepresentation)
|
|
|
|
|
{
|
|
|
|
|
return Link;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool URigVMGraph::IsNodeSelected(const FName& InNodeName) const
|
|
|
|
|
{
|
|
|
|
|
return SelectedNodes.Contains(InNodeName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TArray<FName>& URigVMGraph::GetSelectNodes() const
|
|
|
|
|
{
|
|
|
|
|
return SelectedNodes;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-03 13:20:52 -04:00
|
|
|
bool URigVMGraph::IsTopLevelGraph() const
|
|
|
|
|
{
|
|
|
|
|
if (GetOuter()->IsA<URigVMLibraryNode>())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-06 14:01:38 -04:00
|
|
|
URigVMFunctionLibrary* URigVMGraph::GetDefaultFunctionLibrary() const
|
|
|
|
|
{
|
|
|
|
|
if (DefaultFunctionLibraryPtr.IsValid())
|
|
|
|
|
{
|
|
|
|
|
return CastChecked<URigVMFunctionLibrary>(DefaultFunctionLibraryPtr.Get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (URigVMLibraryNode* OuterLibraryNode = Cast<URigVMLibraryNode>(GetOuter()))
|
|
|
|
|
{
|
|
|
|
|
if (URigVMGraph* OuterGraph = OuterLibraryNode->GetGraph())
|
|
|
|
|
{
|
|
|
|
|
return OuterGraph->GetDefaultFunctionLibrary();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void URigVMGraph::SetDefaultFunctionLibrary(URigVMFunctionLibrary* InFunctionLibrary)
|
|
|
|
|
{
|
|
|
|
|
DefaultFunctionLibraryPtr = InFunctionLibrary;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 03:19:42 -04:00
|
|
|
TArray<FRigVMExternalVariable> URigVMGraph::GetExternalVariables() const
|
|
|
|
|
{
|
|
|
|
|
TArray<FRigVMExternalVariable> Variables;
|
|
|
|
|
|
|
|
|
|
for(URigVMNode* Node : GetNodes())
|
|
|
|
|
{
|
|
|
|
|
if(URigVMLibraryNode* LibraryNode = Cast<URigVMLibraryNode>(Node))
|
|
|
|
|
{
|
|
|
|
|
TArray<FRigVMExternalVariable> LibraryVariables = LibraryNode->GetExternalVariables();
|
|
|
|
|
for(const FRigVMExternalVariable& LibraryVariable : LibraryVariables)
|
|
|
|
|
{
|
|
|
|
|
FRigVMExternalVariable::MergeExternalVariable(Variables, LibraryVariable);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(URigVMVariableNode* VariableNode = Cast<URigVMVariableNode>(Node))
|
|
|
|
|
{
|
2022-05-04 10:18:45 -04:00
|
|
|
// Make sure it is not a local variable or input argument
|
|
|
|
|
if (VariableNode->IsExternalVariable())
|
2021-05-11 17:13:58 -04:00
|
|
|
{
|
|
|
|
|
FRigVMExternalVariable::MergeExternalVariable(Variables, VariableNode->GetVariableDescription().ToExternalVariable());
|
|
|
|
|
}
|
2021-04-27 03:19:42 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Variables;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-27 11:50:32 -04:00
|
|
|
TArray<FRigVMGraphVariableDescription> URigVMGraph::GetLocalVariables(bool bIncludeInputArguments) const
|
|
|
|
|
{
|
|
|
|
|
if (bIncludeInputArguments)
|
|
|
|
|
{
|
|
|
|
|
TArray<FRigVMGraphVariableDescription> Variables;
|
|
|
|
|
Variables.Append(LocalVariables);
|
|
|
|
|
Variables.Append(GetInputArguments());
|
|
|
|
|
return Variables;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LocalVariables;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TArray<FRigVMGraphVariableDescription> URigVMGraph::GetInputArguments() const
|
|
|
|
|
{
|
|
|
|
|
TArray<FRigVMGraphVariableDescription> Inputs;
|
|
|
|
|
if (URigVMFunctionEntryNode* EntryNode = GetEntryNode())
|
|
|
|
|
{
|
|
|
|
|
for (URigVMPin* Pin : EntryNode->GetPins())
|
|
|
|
|
{
|
|
|
|
|
FRigVMGraphVariableDescription Description;
|
|
|
|
|
Description.Name = Pin->GetFName();
|
|
|
|
|
Description.CPPType = Pin->GetCPPType();
|
|
|
|
|
Description.CPPTypeObject = Pin->GetCPPTypeObject();
|
|
|
|
|
Inputs.Add(Description);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Inputs;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-24 10:42:43 -05:00
|
|
|
TArray<FRigVMGraphVariableDescription> URigVMGraph::GetOutputArguments() const
|
|
|
|
|
{
|
|
|
|
|
TArray<FRigVMGraphVariableDescription> Outputs;
|
|
|
|
|
if (URigVMFunctionReturnNode* ReturnNode = GetReturnNode())
|
|
|
|
|
{
|
|
|
|
|
for (URigVMPin* Pin : ReturnNode->GetPins())
|
|
|
|
|
{
|
|
|
|
|
FRigVMGraphVariableDescription Description;
|
|
|
|
|
Description.Name = Pin->GetFName();
|
|
|
|
|
Description.CPPType = Pin->GetCPPType();
|
|
|
|
|
Description.CPPTypeObject = Pin->GetCPPTypeObject();
|
|
|
|
|
Outputs.Add(Description);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Outputs;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-17 19:12:19 -04:00
|
|
|
FRigVMGraphModifiedEvent& URigVMGraph::OnModified()
|
|
|
|
|
{
|
|
|
|
|
return ModifiedEvent;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-21 09:10:19 -04:00
|
|
|
void URigVMGraph::SetExecuteContextStruct(UScriptStruct* InExecuteContextStruct)
|
|
|
|
|
{
|
|
|
|
|
check(InExecuteContextStruct);
|
|
|
|
|
ensure(InExecuteContextStruct->IsChildOf(FRigVMExecuteContext::StaticStruct()));
|
|
|
|
|
ExecuteContextStruct = InExecuteContextStruct;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UScriptStruct* URigVMGraph::GetExecuteContextStruct() const
|
|
|
|
|
{
|
|
|
|
|
if (URigVMGraph* RootGraph = GetRootGraph())
|
|
|
|
|
{
|
|
|
|
|
return RootGraph->ExecuteContextStruct.Get();
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-22 17:58:55 -05:00
|
|
|
void URigVMGraph::Notify(ERigVMGraphNotifType InNotifType, UObject* InSubject)
|
2019-09-17 19:12:19 -04:00
|
|
|
{
|
2020-01-22 17:58:55 -05:00
|
|
|
ModifiedEvent.Broadcast(InNotifType, this, InSubject);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-26 12:29:38 -04:00
|
|
|
TSharedPtr<FRigVMParserAST> URigVMGraph::GetDiagnosticsAST(bool bForceRefresh, TArray<URigVMLink*> InLinksToSkip)
|
2020-01-22 17:58:55 -05:00
|
|
|
{
|
2021-01-21 05:20:34 -04:00
|
|
|
// only refresh the diagnostics AST if have a different set of links to skip
|
|
|
|
|
if (!bForceRefresh && DiagnosticsAST.IsValid())
|
|
|
|
|
{
|
|
|
|
|
const TArray<URigVMLink*> PreviousLinksToSkip = DiagnosticsAST->GetSettings().LinksToSkip;
|
|
|
|
|
if (PreviousLinksToSkip.Num() < InLinksToSkip.Num())
|
|
|
|
|
{
|
|
|
|
|
bForceRefresh = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (int32 LinkIndex = 0; LinkIndex < InLinksToSkip.Num(); LinkIndex++)
|
|
|
|
|
{
|
|
|
|
|
if (PreviousLinksToSkip[LinkIndex] != InLinksToSkip[LinkIndex])
|
|
|
|
|
{
|
|
|
|
|
bForceRefresh = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-22 17:58:55 -05:00
|
|
|
if (DiagnosticsAST == nullptr || bForceRefresh)
|
|
|
|
|
{
|
|
|
|
|
FRigVMParserASTSettings Settings = FRigVMParserASTSettings::Fast();
|
2020-10-26 12:29:38 -04:00
|
|
|
Settings.LinksToSkip = InLinksToSkip;
|
2022-05-31 04:27:20 -04:00
|
|
|
DiagnosticsAST = MakeShareable(new FRigVMParserAST({this}, nullptr, Settings));
|
2020-01-22 17:58:55 -05:00
|
|
|
}
|
|
|
|
|
return DiagnosticsAST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSharedPtr<FRigVMParserAST> URigVMGraph::GetRuntimeAST(const FRigVMParserASTSettings& InSettings, bool bForceRefresh)
|
|
|
|
|
{
|
|
|
|
|
if (RuntimeAST == nullptr || bForceRefresh)
|
|
|
|
|
{
|
2022-05-31 04:27:20 -04:00
|
|
|
RuntimeAST = MakeShareable(new FRigVMParserAST({this}, nullptr, InSettings));
|
2020-01-22 17:58:55 -05:00
|
|
|
}
|
|
|
|
|
return RuntimeAST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void URigVMGraph::ClearAST(bool bClearDiagnostics, bool bClearRuntime)
|
|
|
|
|
{
|
|
|
|
|
if (bClearDiagnostics)
|
|
|
|
|
{
|
|
|
|
|
DiagnosticsAST.Reset();
|
|
|
|
|
}
|
|
|
|
|
if (bClearRuntime)
|
|
|
|
|
{
|
|
|
|
|
RuntimeAST.Reset();
|
|
|
|
|
}
|
2019-09-17 19:12:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool URigVMGraph::IsNameAvailable(const FString& InName)
|
|
|
|
|
{
|
|
|
|
|
for (URigVMNode* Node : Nodes)
|
|
|
|
|
{
|
|
|
|
|
if (Node->GetName() == InName)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void URigVMGraph::PrepareCycleChecking(URigVMPin* InPin, bool bAsInput)
|
|
|
|
|
{
|
2020-10-26 12:29:38 -04:00
|
|
|
TArray<URigVMLink*> LinksToSkip;
|
|
|
|
|
if (InPin)
|
|
|
|
|
{
|
|
|
|
|
LinksToSkip = InPin->GetLinks();
|
|
|
|
|
}
|
2021-01-21 05:20:34 -04:00
|
|
|
|
|
|
|
|
GetDiagnosticsAST(false, LinksToSkip)->PrepareCycleChecking(InPin);
|
2019-09-17 19:12:19 -04:00
|
|
|
}
|
|
|
|
|
|
2022-05-09 07:34:28 -04:00
|
|
|
bool URigVMGraph::CanLink(URigVMPin* InSourcePin, URigVMPin* InTargetPin, FString* OutFailureReason, const FRigVMByteCode* InByteCode, ERigVMPinDirection InUserLinkDirection, bool bInAllowWildcard)
|
2019-09-17 19:12:19 -04:00
|
|
|
{
|
2022-05-09 07:34:28 -04:00
|
|
|
if (!URigVMPin::CanLink(InSourcePin, InTargetPin, OutFailureReason, InByteCode, InUserLinkDirection, bInAllowWildcard))
|
2019-09-17 19:12:19 -04:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-01-22 17:58:55 -05:00
|
|
|
return GetDiagnosticsAST()->CanLink(InSourcePin, InTargetPin, OutFailureReason);
|
2019-09-17 19:12:19 -04:00
|
|
|
}
|
|
|
|
|
|