From e8947b7df4c27792f1c566ccfc996ccc0e69d2aa Mon Sep 17 00:00:00 2001 From: taoria <445625470@qq.com> Date: Wed, 27 Jul 2022 13:52:30 +0800 Subject: [PATCH] feature: runtime cache for running a batch of node --- .../Attribute/Ports/BatchInputAttribute.cs | 5 -- .../{Attribute.meta => Attributes.meta} | 0 .../DisableOnInspector.cs | 0 .../DisableOnInspector.cs.meta | 0 .../GraphUsageAttribute.cs | 0 .../GraphUsageAttribute.cs.meta | 0 .../InternalUsageAttribute.cs | 0 .../InternalUsageAttribute.cs.meta | 0 .../NodeAttribute.cs | 0 .../NodeAttribute.cs.meta | 0 .../PortTypeConversion.cs | 0 .../PortTypeConversion.cs.meta | 0 .../{Attribute => Attributes}/Ports.meta | 0 .../Attributes/Ports/BatchInputAttribute.cs | 5 ++ .../Ports/BatchInputAttribute.cs.meta | 0 .../Ports/BatchOutputAttribute.cs | 0 .../Ports/BatchOutputAttribute.cs.meta | 0 .../Ports/InputAttribute.cs | 0 .../Ports/InputAttribute.cs.meta | 0 .../Ports/OutputAttribute.cs | 0 .../Ports/OutputAttribute.cs.meta | 0 .../Ports/PortAttribute.cs | 1 + .../Ports/PortAttribute.cs.meta | 0 .../RuntimeNodeAttribute.cs | 0 .../RuntimeNodeAttribute.cs.meta | 0 .../ShowInNodeViewAttribute.cs | 0 .../ShowInNodeViewAttribute.cs.meta | 0 .../ViewComponentAttribute.cs | 0 .../ViewComponentAttribute.cs.meta | 0 .../Runtime/Components/RuntimeGraph.cs | 65 +++++++++++++++---- .../Runtime/RuntimeCache/RuntimeCache.cs | 3 + .../Editor/Inspector/NodeInspectorInNode.cs | 2 +- .../Editor/NodeViews/NodeView.cs | 5 +- 33 files changed, 66 insertions(+), 20 deletions(-) delete mode 100644 TNode/TNodeCore/Runtime/Attribute/Ports/BatchInputAttribute.cs rename TNode/TNodeCore/Runtime/{Attribute.meta => Attributes.meta} (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/DisableOnInspector.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/DisableOnInspector.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/GraphUsageAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/GraphUsageAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/InternalUsageAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/InternalUsageAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/NodeAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/NodeAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/PortTypeConversion.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/PortTypeConversion.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports.meta (100%) create mode 100644 TNode/TNodeCore/Runtime/Attributes/Ports/BatchInputAttribute.cs rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/BatchInputAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/BatchOutputAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/BatchOutputAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/InputAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/InputAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/OutputAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/OutputAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/PortAttribute.cs (96%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/Ports/PortAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/RuntimeNodeAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/RuntimeNodeAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/ShowInNodeViewAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/ShowInNodeViewAttribute.cs.meta (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/ViewComponentAttribute.cs (100%) rename TNode/TNodeCore/Runtime/{Attribute => Attributes}/ViewComponentAttribute.cs.meta (100%) diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/BatchInputAttribute.cs b/TNode/TNodeCore/Runtime/Attribute/Ports/BatchInputAttribute.cs deleted file mode 100644 index 76217b7..0000000 --- a/TNode/TNodeCore/Runtime/Attribute/Ports/BatchInputAttribute.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace TNodeCore.Attribute.Ports{ - public class BatchInputAttribute{ - - } -} \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attribute.meta b/TNode/TNodeCore/Runtime/Attributes.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute.meta rename to TNode/TNodeCore/Runtime/Attributes.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/DisableOnInspector.cs b/TNode/TNodeCore/Runtime/Attributes/DisableOnInspector.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/DisableOnInspector.cs rename to TNode/TNodeCore/Runtime/Attributes/DisableOnInspector.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/DisableOnInspector.cs.meta b/TNode/TNodeCore/Runtime/Attributes/DisableOnInspector.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/DisableOnInspector.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/DisableOnInspector.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/GraphUsageAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/GraphUsageAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/GraphUsageAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/GraphUsageAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/GraphUsageAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/GraphUsageAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/GraphUsageAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/GraphUsageAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/InternalUsageAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/InternalUsageAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/InternalUsageAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/InternalUsageAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/InternalUsageAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/InternalUsageAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/InternalUsageAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/InternalUsageAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/NodeAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/NodeAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/NodeAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/NodeAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/NodeAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/NodeAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/NodeAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/NodeAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/PortTypeConversion.cs b/TNode/TNodeCore/Runtime/Attributes/PortTypeConversion.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/PortTypeConversion.cs rename to TNode/TNodeCore/Runtime/Attributes/PortTypeConversion.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/PortTypeConversion.cs.meta b/TNode/TNodeCore/Runtime/Attributes/PortTypeConversion.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/PortTypeConversion.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/PortTypeConversion.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports.meta b/TNode/TNodeCore/Runtime/Attributes/Ports.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports.meta rename to TNode/TNodeCore/Runtime/Attributes/Ports.meta diff --git a/TNode/TNodeCore/Runtime/Attributes/Ports/BatchInputAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/Ports/BatchInputAttribute.cs new file mode 100644 index 0000000..47f51fd --- /dev/null +++ b/TNode/TNodeCore/Runtime/Attributes/Ports/BatchInputAttribute.cs @@ -0,0 +1,5 @@ +namespace TNode.TNodeCore.Runtime.Attributes.Ports{ + public class BatchInputAttribute{ + + } +} \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/BatchInputAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/Ports/BatchInputAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports/BatchInputAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/Ports/BatchInputAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/BatchOutputAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/Ports/BatchOutputAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports/BatchOutputAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/Ports/BatchOutputAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/BatchOutputAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/Ports/BatchOutputAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports/BatchOutputAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/Ports/BatchOutputAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/InputAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports/InputAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/InputAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports/InputAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/OutputAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports/OutputAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/OutputAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports/OutputAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/PortAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs similarity index 96% rename from TNode/TNodeCore/Runtime/Attribute/Ports/PortAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs index fe49e84..d23eb6a 100644 --- a/TNode/TNodeCore/Runtime/Attribute/Ports/PortAttribute.cs +++ b/TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs @@ -22,6 +22,7 @@ namespace TNodeCore.Attribute.Ports{ public readonly string Name; public readonly PortNameHandling NameHandling; public Type HandledType; + public bool Multiple = true; public TypeHandling TypeHandling{ get; set; } public PortAttribute(string name,PortNameHandling nameHandling=PortNameHandling.Auto,TypeHandling typeHandling=TypeHandling.Declared){ this.Name = name; diff --git a/TNode/TNodeCore/Runtime/Attribute/Ports/PortAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/Ports/PortAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/RuntimeNodeAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/RuntimeNodeAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/RuntimeNodeAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/RuntimeNodeAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/RuntimeNodeAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/RuntimeNodeAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/RuntimeNodeAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/RuntimeNodeAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/ShowInNodeViewAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/ShowInNodeViewAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/ShowInNodeViewAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/ShowInNodeViewAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/ShowInNodeViewAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/ShowInNodeViewAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/ShowInNodeViewAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/ShowInNodeViewAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Attribute/ViewComponentAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/ViewComponentAttribute.cs similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/ViewComponentAttribute.cs rename to TNode/TNodeCore/Runtime/Attributes/ViewComponentAttribute.cs diff --git a/TNode/TNodeCore/Runtime/Attribute/ViewComponentAttribute.cs.meta b/TNode/TNodeCore/Runtime/Attributes/ViewComponentAttribute.cs.meta similarity index 100% rename from TNode/TNodeCore/Runtime/Attribute/ViewComponentAttribute.cs.meta rename to TNode/TNodeCore/Runtime/Attributes/ViewComponentAttribute.cs.meta diff --git a/TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs b/TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs index 0cdd8ea..2ac7881 100644 --- a/TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs +++ b/TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs @@ -17,6 +17,8 @@ namespace TNodeCore.Components{ [NonSerialized] public readonly List TopologicalOrder = new List(); public readonly List EntryNodes = new List(); + public readonly Dictionary OutputCached = new Dictionary(); + private bool _isCachingOutput = false; /// /// elements are read only ,do not modify them /// @@ -30,24 +32,52 @@ namespace TNodeCore.Components{ node.NodeData.Process(); } } - public void DependencyTraversal(RuntimeNode runtimeNode){ + //Cache outport info in the graph tool so that we can directly access it in the traversal + public void StartCachingPort(){ + _isCachingOutput = true; + } + public void EndCachingPort(){ + _isCachingOutput = false; + OutputCached.Clear(); + } + public void ResolveDependency(RuntimeNode runtimeNode,int dependencyLevel=0){ var links = runtimeNode.InputLink; foreach (var link in links){ var outputNode = RuntimeNodes[link.outPort.nodeDataId]; - DependencyTraversal(outputNode); + ResolveDependency(outputNode,dependencyLevel+1); HandlingLink(link); } + + if (dependencyLevel > DependencyLevelMax){ + throw new Exception("Dependency anomaly detected,check if there is a loop in the graph"); + } + + + //if the runtime node has no output ,it will not be processed + if (runtimeNode.OutputLink.Count == 0 && dependencyLevel != 0){ + return; + } runtimeNode.NodeData.Process(); + + } - + + private const int DependencyLevelMax = 1145; + public void HandlingLink(NodeLink nodeLink){ + //out node is node output data + //in node is node receive data var inNode = RuntimeNodes[nodeLink.inPort.nodeDataId]; var outNode = RuntimeNodes[nodeLink.outPort.nodeDataId]; - //out node is node output data - //in node is node receive data - var outValue = outNode.GetOutput(nodeLink.outPort.portEntryName); - + + //TODO looks like this string would be too long to make a cache + + var cachedKey = $"{outNode.NodeData.id}-{nodeLink.inPort.portEntryName}"; + var outValue = OutputCached.ContainsKey(cachedKey) ? OutputCached[cachedKey] : outNode.GetOutput(nodeLink.outPort.portEntryName);; + if (_isCachingOutput){ + OutputCached[cachedKey] = outValue; + } inNode.SetInput(nodeLink.inPort.portEntryName, outValue); } public GraphTool(List list, Dictionary graphNodes){ @@ -125,12 +155,12 @@ namespace TNodeCore.Components{ return null; } //DFS search for resolving dependency - public bool ResolveDependency(NodeData startNode){ + public bool RunOnDependency(NodeData startNode){ if(!_build) Build(); if (_graphTool == null) return false; - _graphTool.DependencyTraversal(Get(startNode)); + _graphTool.ResolveDependency(Get(startNode)); return true; } public bool ResolveDependency(){ @@ -152,10 +182,20 @@ namespace TNodeCore.Components{ } public List GetRuntimeNodesOfType(){ - return RuntimeNodes.Values.Where(x => x.NodeType == typeof(T)).ToList(); + return RuntimeNodes.Values.Where(x => typeof(T).IsAssignableFrom(x.NodeType)).ToList(); } public List GetRuntimeNodesOfType(Type type){ - return RuntimeNodes.Values.Where(x => x.NodeType == type).ToList(); + return RuntimeNodes.Values.Where(x => type.IsAssignableFrom(type)).ToList(); + } + public void RunNodesOfType(Type t){ + var nodes = GetRuntimeNodesOfType(t); + _graphTool.StartCachingPort(); + foreach (var runtimeNode in nodes){ + RunOnDependency(runtimeNode.NodeData); + } + _graphTool.EndCachingPort(); + + } private void ModifyOrCreateOutNode(NodeLink linkData){ var outNodeId = linkData.outPort.nodeDataId; @@ -170,7 +210,7 @@ namespace TNodeCore.Components{ public void OnValidate(){ if(runtimeBlackboardData==null||runtimeBlackboardData.GetType()==typeof(BlackboardData)){ if (graphData != null) - runtimeBlackboardData = graphData.blackboardData.Clone() as BlackboardData; + runtimeBlackboardData = graphData.blackboardData?.Clone() as BlackboardData; } } @@ -186,6 +226,7 @@ namespace TNodeCore.Components{ public void Start(){ Build(); + } public virtual void RuntimeExecute(){ _graphTool.DirectlyTraversal(); diff --git a/TNode/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs b/TNode/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs index 8d0a3e6..d00cfb9 100644 --- a/TNode/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs +++ b/TNode/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs @@ -267,6 +267,9 @@ namespace TNodeCore.RuntimeCache{ return (T) method.Invoke(data); } public static object GetValue(this IModel data, string path,Type type=null){ + if(!RuntimeCache.Instance.CachedDelegatesForGettingValue.ContainsKey(type??data.GetType())){ + return null; + } var dic = RuntimeCache.Instance.CachedDelegatesForGettingValue[type ?? data.GetType()]; var method = dic.ContainsKey(path) ? dic[path] : null; return method?.Invoke(data); diff --git a/TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs b/TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs index 8581d05..561a006 100644 --- a/TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs +++ b/TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs @@ -80,7 +80,7 @@ namespace TNode.Editor.Inspector{ if(!test.IsRuntimeGraph) return; var runtimeGraph = test.GetRuntimeGraph(); if (runtimeGraph != null){ - var res = runtimeGraph.ResolveDependency(_data); + var res = runtimeGraph.RunOnDependency(_data); } _data.OnTest(); } diff --git a/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs b/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs index 8fac55f..7f07be9 100644 --- a/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs +++ b/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs @@ -105,7 +105,8 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{ foreach (var propertyInfo in propertyInfos){ if (propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true).FirstOrDefault() is OutputAttribute attribute){ - Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,Port.Capacity.Multi,BuildPortType(attribute,propertyInfo)); + + Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,attribute.Multiple?Port.Capacity.Multi:Port.Capacity.Single,BuildPortType(attribute,propertyInfo)); this.outputContainer.Add(port); var portName = ObjectNames.NicifyVariableName(BuildPortName(attribute,propertyInfo)); port.portName = portName; @@ -115,7 +116,7 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{ } foreach (var propertyInfo in propertyInfos){ if(propertyInfo.GetCustomAttributes(typeof(InputAttribute),true).FirstOrDefault() is InputAttribute attribute){ - Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,Port.Capacity.Single,BuildPortType(attribute,propertyInfo)); + Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,attribute.Multiple?Port.Capacity.Multi:Port.Capacity.Single,BuildPortType(attribute,propertyInfo)); this.inputContainer.Add(port); var portName = BuildPortName(attribute,propertyInfo); port.portName = portName;