From f6af4e7390bb7294ddc67cb6215975ca2996910c Mon Sep 17 00:00:00 2001 From: taoria <445625470@qq.com> Date: Tue, 23 Aug 2022 20:02:34 +0800 Subject: [PATCH] fix: fix runtime conditional node bug --- Samples/AddNode.cs | 25 --- Samples/HelloBlackboard.cs | 4 +- Samples/New HelloGraph.asset | 153 +++++------------- Samples/Nodes.meta | 3 + Samples/Nodes/AddNode.cs | 15 ++ Samples/{ => Nodes}/AddNode.cs.meta | 0 Samples/Nodes/CheckSizeNode.cs | 28 ++++ Samples/Nodes/CheckSizeNode.cs.meta | 3 + Samples/TestScene.unity | 2 +- .../GraphEditorCreator/GraphEditorCreator.cs | 4 +- TNodeCore/Runtime/Components/RuntimeGraph.cs | 4 +- TNodeCore/Runtime/Models/ConditionalNode.cs | 32 +++- .../Runtime/RuntimeCache/RuntimeCache.cs | 51 +++++- .../RuntimeModels/ConditionalRuntimeNode.cs | 10 +- .../Runtime/RuntimeModels/StaticGraph.cs | 4 +- TNodeCore/Runtime/Tools/GraphTool.cs | 7 +- .../Editor/NodeGraphView/DataGraphView.cs | 5 +- .../Editor/NodeViews/NodeView.cs | 133 +++++++-------- Tests/StaticGraphTest.cs | 64 +++++++- 19 files changed, 310 insertions(+), 237 deletions(-) delete mode 100644 Samples/AddNode.cs create mode 100644 Samples/Nodes.meta create mode 100644 Samples/Nodes/AddNode.cs rename Samples/{ => Nodes}/AddNode.cs.meta (100%) create mode 100644 Samples/Nodes/CheckSizeNode.cs create mode 100644 Samples/Nodes/CheckSizeNode.cs.meta diff --git a/Samples/AddNode.cs b/Samples/AddNode.cs deleted file mode 100644 index 4b651fc..0000000 --- a/Samples/AddNode.cs +++ /dev/null @@ -1,25 +0,0 @@ - -using System.Collections.Generic; -using System.Runtime.InteropServices; -using TNodeCore.Runtime; -using TNodeCore.Runtime.Attributes; -using TNodeCore.Runtime.Attributes.Ports; -using TNodeCore.Runtime.Models; -using UnityEngine; - -namespace Samples{ - [GraphUsage(typeof(HelloGraph),"Math")] - public class AddNode:NodeData{ - [Input] - public Vector3 A{ get; set; } - [Input] - public Vector2 B{ get; set; } - [Output] - public Vector3 Res{ get; set; } - - public override void Process(){ - Res = A + (Vector3)B; - this.Log($"{Res}"); - } - } -} \ No newline at end of file diff --git a/Samples/HelloBlackboard.cs b/Samples/HelloBlackboard.cs index a7b19c7..2b7cf58 100644 --- a/Samples/HelloBlackboard.cs +++ b/Samples/HelloBlackboard.cs @@ -10,8 +10,8 @@ namespace TNode.Samples{ public class HelloBlackboard:BlackboardData{ public string HelloString; public GameObject HelloGameObject; - public List V3S; - public List V2S; + public List Value; + } } \ No newline at end of file diff --git a/Samples/New HelloGraph.asset b/Samples/New HelloGraph.asset index b4c5b29..0a2b498 100644 --- a/Samples/New HelloGraph.asset +++ b/Samples/New HelloGraph.asset @@ -17,64 +17,31 @@ MonoBehaviour: - id: 1 - id: 2 - id: 3 - - id: 4 - - id: 5 - - id: 6 nodeLinks: - - inPort: - portEntryName: B - nodeDataId: 94327133-34e1-47bb-a365-0782120c581e - outPort: - portEntryName: Value - nodeDataId: 07c1f545-719b-4f9b-9f4c-dc3883c02423 - inPort: portEntryName: A - nodeDataId: 94327133-34e1-47bb-a365-0782120c581e + nodeDataId: 4300534d-023d-4b56-a0cb-39e197e68845 outPort: portEntryName: Value - nodeDataId: 72477a0c-2399-47c1-ba04-495add218335 - - inPort: - portEntryName: A - nodeDataId: 134adf78-f8ba-4888-8362-4a2ca0df2c69 - outPort: - portEntryName: Res - nodeDataId: 94327133-34e1-47bb-a365-0782120c581e + nodeDataId: 6dba1aab-0db9-45a0-b3f7-e8fe9c47c168 - inPort: portEntryName: B - nodeDataId: 134adf78-f8ba-4888-8362-4a2ca0df2c69 + nodeDataId: 4300534d-023d-4b56-a0cb-39e197e68845 outPort: portEntryName: Value - nodeDataId: 9b6e59e3-cc30-4697-a310-8f1195631ec9 + nodeDataId: 5fd53e10-e727-45e3-8458-04a6ec8581c4 - inPort: portEntryName: A - nodeDataId: 8d01abf2-f69a-4884-a6a1-99903ed96b7a + nodeDataId: f236a611-cc64-4fce-88d2-40baf7f4a490 outPort: - portEntryName: Value - nodeDataId: 72477a0c-2399-47c1-ba04-495add218335 - - inPort: - portEntryName: B - nodeDataId: 8d01abf2-f69a-4884-a6a1-99903ed96b7a - outPort: - portEntryName: Value - nodeDataId: 07c1f545-719b-4f9b-9f4c-dc3883c02423 - - inPort: - portEntryName: A - nodeDataId: d4ff4eb9-dd02-4712-90dc-898223d1758f - outPort: - portEntryName: Res - nodeDataId: 8d01abf2-f69a-4884-a6a1-99903ed96b7a - - inPort: - portEntryName: B - nodeDataId: d4ff4eb9-dd02-4712-90dc-898223d1758f - outPort: - portEntryName: Value - nodeDataId: 07c1f545-719b-4f9b-9f4c-dc3883c02423 + portEntryName: C + nodeDataId: 4300534d-023d-4b56-a0cb-39e197e68845 blackboardData: - id: 7 + id: 4 sceneReference: editorModels: [] graphViewModel: - id: 8 + id: 5 references: version: 1 00000000: @@ -82,105 +49,62 @@ MonoBehaviour: data: positionInView: serializedVersion: 2 - x: 550 - y: 218 + x: 674 + y: 261 width: 0 height: 0 - id: 72477a0c-2399-47c1-ba04-495add218335 + id: 6dba1aab-0db9-45a0-b3f7-e8fe9c47c168 nodeName: entryPoint: 0 isTest: 0 - blackboardDragTypeString: UnityEngine.Vector3, UnityEngine.CoreModule, Version=0.0.0.0, - Culture=neutral, PublicKeyToken=null - blackDragData: V3S.0 + blackboardDragTypeString: System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + blackDragData: Value.0 isListElement: 1 00000001: - type: {class: AddNode, ns: Samples, asm: Assembly-CSharp} - data: - positionInView: - serializedVersion: 2 - x: 906 - y: 29 - width: 0 - height: 0 - id: d4ff4eb9-dd02-4712-90dc-898223d1758f - nodeName: AddNode - entryPoint: 0 - isTest: 0 - 00000002: type: {class: BlackboardDragNode, ns: TNodeCore.Runtime.Models, asm: Taoria.TNodeCore.Runtime} data: positionInView: serializedVersion: 2 - x: 574 - y: 306 + x: 674 + y: 330 width: 0 height: 0 - id: 07c1f545-719b-4f9b-9f4c-dc3883c02423 + id: 5fd53e10-e727-45e3-8458-04a6ec8581c4 nodeName: entryPoint: 0 isTest: 0 - blackboardDragTypeString: UnityEngine.Vector2, UnityEngine.CoreModule, Version=0.0.0.0, - Culture=neutral, PublicKeyToken=null - blackDragData: V2S.0 + blackboardDragTypeString: System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + blackDragData: Value.1 isListElement: 1 - 00000003: - type: {class: AddNode, ns: Samples, asm: Assembly-CSharp} - data: - positionInView: - serializedVersion: 2 - x: 733 - y: 52 - width: 0 - height: 0 - id: 8d01abf2-f69a-4884-a6a1-99903ed96b7a - nodeName: AddNode - entryPoint: 0 - isTest: 0 - 00000004: - type: {class: BlackboardDragNode, ns: TNodeCore.Runtime.Models, asm: Taoria.TNodeCore.Runtime} - data: - positionInView: - serializedVersion: 2 - x: 817 - y: 387 - width: 0 - height: 0 - id: 9b6e59e3-cc30-4697-a310-8f1195631ec9 - nodeName: - entryPoint: 0 - isTest: 0 - blackboardDragTypeString: UnityEngine.Vector2, UnityEngine.CoreModule, Version=0.0.0.0, - Culture=neutral, PublicKeyToken=null - blackDragData: V2S.0 - isListElement: 1 - 00000005: - type: {class: AddNode, ns: Samples, asm: Assembly-CSharp} + 00000002: + type: {class: AddNode, ns: Samples.Nodes, asm: Assembly-CSharp} data: positionInView: serializedVersion: 2 - x: 669.5 - y: 198.5 + x: 774 + y: 252 width: 0 height: 0 - id: 94327133-34e1-47bb-a365-0782120c581e + id: 4300534d-023d-4b56-a0cb-39e197e68845 nodeName: AddNode entryPoint: 0 isTest: 0 - 00000006: - type: {class: AddNode, ns: Samples, asm: Assembly-CSharp} + 00000003: + type: {class: CheckSizeNode, ns: Samples.Nodes, asm: Assembly-CSharp} data: positionInView: serializedVersion: 2 - x: 1007 - y: 199 + x: 904 + y: 252 width: 0 height: 0 - id: 134adf78-f8ba-4888-8362-4a2ca0df2c69 - nodeName: AddNode + id: f236a611-cc64-4fce-88d2-40baf7f4a490 + nodeName: CheckSizeNode entryPoint: 0 isTest: 0 - 00000007: + 00000004: type: {class: HelloBlackboard, ns: TNode.Samples, asm: Assembly-CSharp} data: positionInView: @@ -192,11 +116,10 @@ MonoBehaviour: id: HelloString: HelloGameObject: {fileID: 0} - V3S: - - {x: 0, y: 0, z: 0} - V2S: - - {x: 4, y: 4} - 00000008: + Value: + - 11 + - 102.1 + 00000005: type: {class: GraphViewModel, ns: TNode.TNodeCore.Editor.Models, asm: Taoria.TNodeCore.Runtime} data: positionInView: @@ -207,5 +130,5 @@ MonoBehaviour: height: 0 id: persistScale: 1 - persistOffset: {x: -169, y: 62} + persistOffset: {x: -136, y: 40} isBlackboardOn: 1 diff --git a/Samples/Nodes.meta b/Samples/Nodes.meta new file mode 100644 index 0000000..c21203f --- /dev/null +++ b/Samples/Nodes.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f50f5cbc213948329c1087add634caa6 +timeCreated: 1661237859 \ No newline at end of file diff --git a/Samples/Nodes/AddNode.cs b/Samples/Nodes/AddNode.cs new file mode 100644 index 0000000..bbac497 --- /dev/null +++ b/Samples/Nodes/AddNode.cs @@ -0,0 +1,15 @@ +using TNodeCore.Runtime.Attributes; +using TNodeCore.Runtime.Attributes.Ports; +using TNodeCore.Runtime.Models; + +namespace Samples.Nodes{ + [GraphUsage(typeof(HelloGraph),"Math")] + public class AddNode:NodeData{ + [Input] + public float A{ get; set; } + [Input] + public float B{ get; set; } + + [Output] public float C => A + B; + } +} \ No newline at end of file diff --git a/Samples/AddNode.cs.meta b/Samples/Nodes/AddNode.cs.meta similarity index 100% rename from Samples/AddNode.cs.meta rename to Samples/Nodes/AddNode.cs.meta diff --git a/Samples/Nodes/CheckSizeNode.cs b/Samples/Nodes/CheckSizeNode.cs new file mode 100644 index 0000000..2643fb3 --- /dev/null +++ b/Samples/Nodes/CheckSizeNode.cs @@ -0,0 +1,28 @@ +using TNode.TNodeCore.Runtime.Models; +using TNodeCore.Runtime.Attributes; +using TNodeCore.Runtime.Attributes.Ports; +using TNodeCore.Runtime.Models; + +namespace Samples.Nodes{ + [GraphUsage(typeof(HelloGraph),"Math")] + public class CheckSizeNode:ConditionalNode{ + [Input] + public float A{ get; set; } + + [Output] + public TransitionCondition Bigger(){ + return new TransitionCondition(){ + Condition = A>0, + Priority = 0 + }; + } + [Output] + public TransitionCondition SmallerOrEqual(){ + return new TransitionCondition(){ + Condition = A<=0, + Priority = 0 + }; + } + + } +} \ No newline at end of file diff --git a/Samples/Nodes/CheckSizeNode.cs.meta b/Samples/Nodes/CheckSizeNode.cs.meta new file mode 100644 index 0000000..87c1642 --- /dev/null +++ b/Samples/Nodes/CheckSizeNode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7f1f136a46d34c1ab5bcc8bc1a43fe5f +timeCreated: 1661237873 \ No newline at end of file diff --git a/Samples/TestScene.unity b/Samples/TestScene.unity index 39fafd2..7c81e19 100644 --- a/Samples/TestScene.unity +++ b/Samples/TestScene.unity @@ -219,7 +219,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 325720a2ce64404d917fff20d22e80f2, type: 3} m_Name: m_EditorClassIdentifier: - graphData: {fileID: 11400000, guid: f55ebad0b05015a4f873ac78896d95d3, type: 2} + graphData: {fileID: 0} runtimeBlackboardData: id: 0 references: diff --git a/TNodeCore/Editor/Tools/GraphEditorCreator/GraphEditorCreator.cs b/TNodeCore/Editor/Tools/GraphEditorCreator/GraphEditorCreator.cs index be2baee..a585c06 100644 --- a/TNodeCore/Editor/Tools/GraphEditorCreator/GraphEditorCreator.cs +++ b/TNodeCore/Editor/Tools/GraphEditorCreator/GraphEditorCreator.cs @@ -19,8 +19,8 @@ namespace TNodeCore.Editor.Tools.GraphEditorCreator{ private TextField _graphClassNameTextField; private Button _createButton; private readonly SourceGeneratorForGraphEditor _sourceGeneratorForGraphEditor = new SourceGeneratorForGraphEditor(); - [MenuItem("Assets/CreateProp/TNodeCore/CreateProp New Graph Editor")] - [MenuItem("TNodeCore/CreateProp New Graph Editor")] + [MenuItem("Assets/Create/TNodeCore/Create New Graph Editor")] + [MenuItem("TNodeCore/Create New Graph Editor")] public static void ShowExample() { GraphEditorCreator wnd = GetWindow(); diff --git a/TNodeCore/Runtime/Components/RuntimeGraph.cs b/TNodeCore/Runtime/Components/RuntimeGraph.cs index 30483ea..333fda9 100644 --- a/TNodeCore/Runtime/Components/RuntimeGraph.cs +++ b/TNodeCore/Runtime/Components/RuntimeGraph.cs @@ -179,10 +179,10 @@ namespace TNodeCore.Runtime.Components{ _runtimeNodeEnumerator = _graphTool.DeepFirstSearchWithCondition(); break; case AccessMethod.StateTransition: - _runtimeNodeEnumerator = _graphTool.IterateDirectlyTraversal(); + _runtimeNodeEnumerator = _graphTool.IterateNext(); break; case AccessMethod.Dependency: - _runtimeNodeEnumerator = _graphTool.IterateNext(); + _runtimeNodeEnumerator = _graphTool.IterateDirectlyTraversal(); break; } diff --git a/TNodeCore/Runtime/Models/ConditionalNode.cs b/TNodeCore/Runtime/Models/ConditionalNode.cs index 21e8c82..f946a72 100644 --- a/TNodeCore/Runtime/Models/ConditionalNode.cs +++ b/TNodeCore/Runtime/Models/ConditionalNode.cs @@ -1,14 +1,36 @@ using TNodeCore.Runtime; using TNodeCore.Runtime.Attributes.Ports; using TNodeCore.Runtime.Models; +using Unity.Plastic.Newtonsoft.Json.Serialization; namespace TNode.TNodeCore.Runtime.Models{ public class ConditionalNode:NodeData{ - [Input] - public object In{ get; set; } + + } + public class TransitionCondition:IBaseTransition{ + + + public Func DataFunc; + + public bool Condition{ get; set; } + public int Priority{ get; set; } + public object GetValue(){ + return DataFunc(); + } } - public struct TransitionCondition{ - public bool Condition; - public int Priority; + public class TransitionCondition:IBaseTransition{ + public Func DataFunc; + public bool Condition{ get; set; } + public int Priority{ get; set; } + public object GetValue(){ + return DataFunc.Invoke(); + } } + public interface IBaseTransition{ + public bool Condition{ get; set; } + public int Priority{ get; set; } + + public object GetValue(); + } + } \ No newline at end of file diff --git a/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs b/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs index 27ed998..8fc673a 100644 --- a/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs +++ b/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs @@ -31,14 +31,8 @@ namespace TNodeCore.Runtime.RuntimeCache{ if (method == null){ throw new Exception("Method not found for name " + name); } - if (method.ReturnType != typeof(void)){ - Type = method.ReturnType; - Get = (Func)Delegate.CreateDelegate(typeof(Func), null, method); - } - else{ - Type = method.GetParameters()[0].ParameterType; - Set = (Action)Delegate.CreateDelegate(typeof(Action), null, method); - } + Type = method.MethodPortType(); + Get = (Func)Delegate.CreateDelegate(typeof(Func), null, method); } } @@ -448,6 +442,47 @@ namespace TNodeCore.Runtime.RuntimeCache{ var method = RuntimeCache.Instance.CachedDelegatesForSettingValue[type??data.GetType()][path]; method.Invoke(data,value); } + + public static Type MethodPortType(this MethodInfo info){ + if (info.ReturnType == typeof(void)){ + return info.GetParameters()[0].ParameterType; + } + else{ + return info.ReturnType; + } + } + + public static Type MemberPortType(this MemberInfo memberInfo){ + if (memberInfo is FieldInfo){ + throw new Exception("FieldInfo is not supported as Port"); + } + + if (memberInfo is MethodInfo methodInfo){ + return MethodPortType(methodInfo); + } + + if (memberInfo is PropertyInfo propertyInfo){ + return propertyInfo.PropertyType; + } + + return memberInfo.DeclaringType; + } + + public static object GetPortValue(this MemberInfo memberInfo,Model data){ + if (memberInfo is FieldInfo){ + throw new Exception("FieldInfo is not supported as Port"); + } + + if (memberInfo is MethodInfo methodInfo){ + return methodInfo.Invoke(data, null); + } + + if (memberInfo is PropertyInfo propertyInfo){ + return propertyInfo.GetValue(data); + } + + return null; + } } } \ No newline at end of file diff --git a/TNodeCore/Runtime/RuntimeModels/ConditionalRuntimeNode.cs b/TNodeCore/Runtime/RuntimeModels/ConditionalRuntimeNode.cs index c10be12..a1f1f68 100644 --- a/TNodeCore/Runtime/RuntimeModels/ConditionalRuntimeNode.cs +++ b/TNodeCore/Runtime/RuntimeModels/ConditionalRuntimeNode.cs @@ -22,7 +22,10 @@ namespace TNodeCore.Runtime{ } foreach (var port in transitionPort){ if(GetPortDirection(port)==Direction.Input) continue; - _possibleTransition.Add(new Tuple>(port,() => (TransitionCondition)GetOutput(port)) ); + var ids = OutputLinks.Where(x => x.outPort.portEntryName == port).Select(x => x.inPort.nodeDataId); + var enumerable1 = ids as string[] ?? ids.ToArray(); + if(enumerable1.FirstOrDefault()!=null) + _possibleTransition.Add(new Tuple>(enumerable1.FirstOrDefault(),() => (TransitionCondition)GetOutput(port)) ); } } else{ @@ -32,10 +35,7 @@ namespace TNodeCore.Runtime{ public string[] GetConditionalNextIds(){ var ports = _possibleTransition.Where(x => x.Item2().Condition); - var portNames = ports.Select(x => x.Item1); - //Search output links to found the link contains portNames as outport's name - var outputLinks = OutputLinks.Where(x => portNames.Contains(x.outPort.portEntryName)); - return outputLinks.Select(x => x.inPort.nodeDataId).ToArray(); + return ports.Select(x => x.Item1).ToArray(); } public string GetNextNodeId(){ diff --git a/TNodeCore/Runtime/RuntimeModels/StaticGraph.cs b/TNodeCore/Runtime/RuntimeModels/StaticGraph.cs index b648526..7042311 100644 --- a/TNodeCore/Runtime/RuntimeModels/StaticGraph.cs +++ b/TNodeCore/Runtime/RuntimeModels/StaticGraph.cs @@ -59,10 +59,10 @@ namespace TNodeCore.Runtime.RuntimeModels{ _runtimeNodeEnumerator = _graphTool.DeepFirstSearchWithCondition(); break; case AccessMethod.StateTransition: - _runtimeNodeEnumerator = _graphTool.IterateDirectlyTraversal(); + _runtimeNodeEnumerator = _graphTool.IterateNext(); break; case AccessMethod.Dependency: - _runtimeNodeEnumerator = _graphTool.IterateNext(); + _runtimeNodeEnumerator = _graphTool.IterateDirectlyTraversal(); break; } diff --git a/TNodeCore/Runtime/Tools/GraphTool.cs b/TNodeCore/Runtime/Tools/GraphTool.cs index e577173..e5e7c62 100644 --- a/TNodeCore/Runtime/Tools/GraphTool.cs +++ b/TNodeCore/Runtime/Tools/GraphTool.cs @@ -83,7 +83,12 @@ namespace TNode.TNodeCore.Runtime.Tools{ while(currentNode.OutputLinks.Any()){ if (currentNode is ConditionalRuntimeNode conditionalRuntimeNode){ - currentNode = RuntimeNodes[conditionalRuntimeNode.GetNextNodeId()]; + var id = conditionalRuntimeNode.GetNextNodeId(); + if (id != null && id.Trim(' ').Length > 0){ + Debug.Log(currentNode.NodeData+" is going to run "+id); + currentNode = RuntimeNodes[conditionalRuntimeNode.GetNextNodeId()]; + } + } else{ var link = currentNode.OutputLinks.FirstOrDefault(); diff --git a/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs b/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs index 90d2fe4..697183e 100644 --- a/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs +++ b/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs @@ -191,7 +191,7 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{ Vector2 editorPosition = Owner==null?Vector2.zero:Owner.position.position; //Remove all the previous menu items evt.menu.MenuItems().Clear(); - evt.menu.AppendAction("CreateProp Node", dma => { + evt.menu.AppendAction("Create Node", dma => { var dmaPos = dma.eventInfo.mousePosition+editorPosition; var searchWindow = ScriptableObject.CreateInstance(); var targetPos = this.viewTransform.matrix.inverse.MultiplyPoint(dma.eventInfo.localMousePosition); @@ -200,10 +200,9 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{ searchWindow.Setup(typeof(T),this,Owner,targetPos); - Debug.Log(targetPos); SearchWindow.Open(searchWindowContext, searchWindow); }); - evt.menu.AppendAction("CreateProp PlacematModel",dma=> { + evt.menu.AppendAction("Create PlacematModel",dma=> { //find placemat container var container = GetPlacematContainer(); var targetPos = this.viewTransform.matrix.inverse.MultiplyPoint(dma.eventInfo.localMousePosition); diff --git a/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs b/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs index d2c5372..9c00ffb 100644 --- a/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs +++ b/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs @@ -116,18 +116,18 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{ this.RefreshExpandedState(); } - protected virtual string BuildPortName(PortAttribute portAttribute,PropertyInfo propertyInfo,params object[] args){ + protected virtual string BuildPortName(PortAttribute portAttribute,MemberInfo memberInfo,params object[] args){ switch (portAttribute.NameHandling){ case PortNameHandling.Auto: - return portAttribute.Name.Trim(' ').Length>0?portAttribute.Name:propertyInfo.Name; + return portAttribute.Name.Trim(' ').Length>0?portAttribute.Name:memberInfo.Name; case PortNameHandling.Manual: return portAttribute.Name; case PortNameHandling.MemberName: - return propertyInfo.Name; + return memberInfo.Name; case PortNameHandling.Format: - return String.Format(propertyInfo.Name, args); + return String.Format(memberInfo.Name, args); case PortNameHandling.MemberType: - return propertyInfo.PropertyType.Name; + return memberInfo.MemberPortType().Name; default: throw new ArgumentOutOfRangeException(); } @@ -152,28 +152,32 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{ throw new Exception("Member is not a property or field"); } - protected virtual Type BuildPortType(PortAttribute portAttribute,PropertyInfo propertyInfo){ - - - switch (portAttribute.TypeHandling){ + protected virtual Type BuildPortType(PortAttribute portAttribute,MemberInfo propertyInfo){ + + switch (portAttribute.TypeHandling){ case TypeHandling.Declared : - return propertyInfo.PropertyType; + return propertyInfo.MemberPortType(); case TypeHandling.Implemented: - return propertyInfo.GetValue(_data)?.GetType(); + return propertyInfo.GetPortValue(_data)?.GetType(); case TypeHandling.Specified: return portAttribute.HandledType??typeof(object); case TypeHandling.Path: var type = GetDataType(portAttribute.TypePath); - return type; default: throw new ArgumentOutOfRangeException(); } - } - protected virtual Type BuildGroupPortType(PortAttribute portAttribute,PropertyInfo propertyInfo,int index){ - var iList = propertyInfo.GetValue(_data) as IList; + + protected virtual Type BuildGroupPortType(PortAttribute portAttribute,MemberInfo propertyInfo,int index){ + IList iList = null; + if (propertyInfo is PropertyInfo propertyInfo1){ + iList = propertyInfo1.GetValue(_data) as IList; + } + else if (propertyInfo is MethodInfo methodInfo){ + iList = methodInfo.Invoke(_data,null) as IList; + } if (iList is Array array){ switch (portAttribute.TypeHandling){ case TypeHandling.Declared: @@ -204,9 +208,7 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{ throw new ArgumentOutOfRangeException(); } } - return null; - } /// @@ -214,67 +216,71 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{ /// protected virtual void BuildInputAndOutputPort(){ var propertyInfos = _data.GetType().GetProperties(); - + var methodInfos = _data.GetType().GetMethods(); foreach (var propertyInfo in propertyInfos){ if (propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true).FirstOrDefault() is OutputAttribute attribute){ - if (attribute.Group == false){ - Port port = new CustomPort(Orientation.Horizontal, Direction.Output, - attribute.Multiple ? Port.Capacity.Multi : Port.Capacity.Single, - BuildPortType(attribute, propertyInfo)); - BuildPort(port, attribute, propertyInfo,outputContainer); - } - else{ - var propertyValue = propertyInfo.GetValue(_data); - if (propertyValue is IList list){ - for (var i = 0; i < list.Count; i++){ - var port = new CustomPort(Orientation.Horizontal, Direction.Output, - Port.Capacity.Single, - BuildGroupPortType(attribute, propertyInfo,i)); - BuildGroupPort(port, attribute, propertyInfo,outputContainer,list[i],i); - } - } - } + BuildPortFromAttributeAndPropertyInfo(attribute,propertyInfo,Direction.Output); } } foreach (var propertyInfo in propertyInfos){ if(propertyInfo.GetCustomAttributes(typeof(InputAttribute),true).FirstOrDefault() is InputAttribute attribute){ - if (attribute.Group == false){ - Port port = new CustomPort - (Orientation.Horizontal, - Direction.Input,attribute.Multiple?Port.Capacity.Multi: Port.Capacity.Single,BuildPortType(attribute,propertyInfo)); - BuildPort(port,attribute,propertyInfo,inputContainer); + BuildPortFromAttributeAndPropertyInfo(attribute, propertyInfo); + } + } + + foreach (var method in methodInfos){ + if (method.GetCustomAttribute() != null){ + var portAtt = method.GetCustomAttribute(); + if (portAtt is InputAttribute input){ + BuildPortFromAttributeAndPropertyInfo(input,method); } - else{ - var propertyValue = propertyInfo.GetValue(_data); - if (propertyValue is IList list){ - - for (var i = 0; i < list.Count; i++){ - var port = new CustomPort(Orientation.Horizontal, Direction.Input, - Port.Capacity.Single, - BuildGroupPortType(attribute, propertyInfo,i)); - BuildGroupPort(port, attribute, propertyInfo,inputContainer,list[i],i); - - } - } + + if (portAtt is OutputAttribute output){ + BuildPortFromAttributeAndPropertyInfo(output,method,Direction.Output); } + } + } } - private void BuildPort(Port port, PortAttribute attribute, PropertyInfo propertyInfo,VisualElement portContainer){ + private void BuildPortFromAttributeAndPropertyInfo(PortAttribute attribute, MemberInfo propertyInfo,Direction direction = Direction.Input){ + if (attribute.Group == false){ + Port port = new CustomPort + (Orientation.Horizontal, + direction, attribute.Multiple ? Port.Capacity.Multi : Port.Capacity.Single, + BuildPortType(attribute, propertyInfo)); + BuildPort(port, attribute, propertyInfo, direction==Direction.Input?inputContainer:outputContainer); + } + else{ + var propertyValue = propertyInfo.GetPortValue(_data); + + if (propertyValue is IList list){ + for (var i = 0; i < list.Count; i++){ + var port = new CustomPort(Orientation.Horizontal, direction, + attribute.Multiple ? Port.Capacity.Multi : Port.Capacity.Single, + BuildGroupPortType(attribute, propertyInfo, i)); + BuildGroupPort(port, attribute, propertyInfo, direction==Direction.Input?inputContainer:outputContainer, list[i], i); + } + } + } + } + + + private void BuildPort(Port port, PortAttribute attribute, MemberInfo memberInfo,VisualElement portContainer){ portContainer.Add(port); - var portName = ObjectNames.NicifyVariableName(BuildPortName(attribute, propertyInfo)); + var portName = ObjectNames.NicifyVariableName(BuildPortName(attribute, memberInfo)); port.portName = portName; - port.name = propertyInfo.Name; - var colorAtt = propertyInfo.PropertyType.GetCustomAttribute(); + port.name = memberInfo.Name; + PortColorAttribute colorAtt = null; + colorAtt = memberInfo.MemberPortType().GetCustomAttribute(); if (colorAtt != null){ var color = colorAtt.Color; port.portColor = color; } } - - private void BuildGroupPort(Port port, PortAttribute attribute, PropertyInfo propertyInfo, + private void BuildGroupPort(Port port, PortAttribute attribute, MemberInfo propertyInfo, VisualElement portContainer,object currentElement,int index = 0){ portContainer.Add(port); port.name = propertyInfo.Name + ":" + index; @@ -286,26 +292,23 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{ port.portName = ObjectNames.NicifyVariableName(BuildGroupPortName(attribute, propertyInfo, index)); } } - } - - private string BuildGroupPortName(PortAttribute attribute, PropertyInfo propertyInfo, int index){ + private string BuildGroupPortName(PortAttribute attribute, MemberInfo memberInfo, int index){ switch (attribute.NameHandling){ case PortNameHandling.Auto: - return (attribute.Name.Trim(' ').Length>0?attribute.Name:propertyInfo.Name)+":"+index; + return (attribute.Name.Trim(' ').Length>0?attribute.Name:memberInfo.Name)+":"+index; case PortNameHandling.Manual: return attribute.Name+":"+index;; case PortNameHandling.MemberName: - return propertyInfo.Name+":"+index; + return memberInfo.Name+":"+index; case PortNameHandling.Format: throw new NotImplementedException(); case PortNameHandling.MemberType: - return propertyInfo.PropertyType.Name+":"+index; + return memberInfo.MemberPortType().Name + ":" + index; default: throw new ArgumentOutOfRangeException(); } } - public void StartARenameTitleTextField(){ var textField = new TextField{ value = title, diff --git a/Tests/StaticGraphTest.cs b/Tests/StaticGraphTest.cs index e498dab..026d920 100644 --- a/Tests/StaticGraphTest.cs +++ b/Tests/StaticGraphTest.cs @@ -17,12 +17,14 @@ namespace Tests{ } [GraphUsage(typeof(GraphDataForTest))] internal class TestNode : NodeData{ - [Input] public int Input{ get; set; } + [Input] public object Input{ get; set; } [Output] public int Output{ get; set; } } [GraphUsage(typeof(GraphDataForTest))] internal class TestConditionalNode : ConditionalNode{ public bool TestCondition = false; + [Input] + public object In{ get; set; } [Output] public TransitionCondition Output(){ return new TransitionCondition(){ @@ -185,5 +187,65 @@ namespace Tests{ staticGraph2.MoveNext(); Assert.AreNotEqual(node6,staticGraph2.CurrentNode()); } + + [Test] + public void TestStaticGraphDirectlyNext(){ + GraphData graphData = ScriptableObject.CreateInstance(); + var node1 = NodeCreator.InstantiateNodeData(); + var node2 = NodeCreator.InstantiateNodeData(); + var node3 = NodeCreator.InstantiateNodeData(); + var node4 = NodeCreator.InstantiateNodeData(); + var node5 = NodeCreator.InstantiateNodeData(); + var node6 = NodeCreator.InstantiateNodeData(); + + + graphData.NodeDictionary.Add(node1.id,node1); + graphData.NodeDictionary.Add(node2.id,node2); + graphData.NodeDictionary.Add(node3.id,node3); + graphData.NodeDictionary.Add(node4.id,node4); + graphData.NodeDictionary.Add(node5.id,node5); + graphData.NodeDictionary.Add(node6.id,node6); + + + + //Link node1 to node2 + graphData.NodeLinks.Add(new NodeLink(new PortInfo{ + portEntryName = "Input", + nodeDataId = node2.id + },new PortInfo{ + portEntryName = "Output", + nodeDataId = node1.id + })); + + //Link node2 to node3 + graphData.NodeLinks.Add(new NodeLink(new PortInfo{ + portEntryName = "In", + nodeDataId = node3.id + },new PortInfo{ + portEntryName = "Output", + nodeDataId = node2.id + })); + //Link node3 to node6 + graphData.NodeLinks.Add(new NodeLink(new PortInfo{ + portEntryName = "Input", + nodeDataId = node6.id + },new PortInfo{ + portEntryName = "Output", + nodeDataId = node3.id + })); + + node3.TestCondition = true; + + var staticGraph = new StaticGraph(graphData); + staticGraph.AccessMethod = AccessMethod.StateTransition; + staticGraph.ResetState(); + + Assert.AreEqual(node1,staticGraph.CurrentNode()); + staticGraph.MoveNext(); + Assert.AreEqual(node2,staticGraph.CurrentNode()); + staticGraph.MoveNext(); + Assert.AreEqual(node3,staticGraph.CurrentNode()); + staticGraph.MoveNext(); + } } } \ No newline at end of file