From ecc5b3e0e1944d2eff1014ee1abf650837778c72 Mon Sep 17 00:00:00 2001 From: Lumos Date: Sun, 22 Dec 2019 18:56:42 +0100 Subject: [PATCH] Example fix for the dynamic port "serialisation desync" problem. Not tested much with non-array types where "dynamicPortList" is set to true. Recommend further testing if applicable. --- Scripts/Editor/NodeEditorAction.cs | 4 +-- Scripts/Editor/NodeEditorGUILayout.cs | 2 ++ Scripts/Node.cs | 6 ++-- Scripts/NodeDataCache.cs | 40 ++++++++++++++++++++++++++- Scripts/NodePort.cs | 19 +++++++++++-- 5 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs index 2581676..b64ddfe 100644 --- a/Scripts/Editor/NodeEditorAction.cs +++ b/Scripts/Editor/NodeEditorAction.cs @@ -457,8 +457,8 @@ namespace XNodeEditor { XNode.Node newNodeIn, newNodeOut; if (substitutes.TryGetValue(inputPort.node, out newNodeIn) && substitutes.TryGetValue(outputPort.node, out newNodeOut)) { - newNodeIn.UpdateStaticPorts(); - newNodeOut.UpdateStaticPorts(); + newNodeIn.UpdatePorts(); + newNodeOut.UpdatePorts(); inputPort = newNodeIn.GetInputPort(inputPort.fieldName); outputPort = newNodeOut.GetOutputPort(outputPort.fieldName); } diff --git a/Scripts/Editor/NodeEditorGUILayout.cs b/Scripts/Editor/NodeEditorGUILayout.cs index f9333db..08fcf5e 100644 --- a/Scripts/Editor/NodeEditorGUILayout.cs +++ b/Scripts/Editor/NodeEditorGUILayout.cs @@ -326,6 +326,8 @@ namespace XNodeEditor { } list.list = dynamicPorts; list.DoLayoutList(); + + node.UpdatePorts(); } private static ReorderableList CreateReorderableList(string fieldName, List dynamicPorts, SerializedProperty arrayData, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType, XNode.Node.TypeConstraint typeConstraint, Action onCreation) { diff --git a/Scripts/Node.cs b/Scripts/Node.cs index a07679a..9ea7411 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -119,12 +119,12 @@ namespace XNode { protected void OnEnable() { if (graphHotfix != null) graph = graphHotfix; graphHotfix = null; - UpdateStaticPorts(); + UpdatePorts(); Init(); } - /// Update static ports to reflect class fields. This happens automatically on enable. - public void UpdateStaticPorts() { + /// Update all ports to reflect class fields. This happens automatically on enable or on redrawing the list of ports. + public void UpdatePorts() { NodeDataCache.UpdatePorts(this, ports); } diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index 02e35a1..c4bbc2e 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using UnityEditor; using UnityEngine; namespace XNode { @@ -9,7 +10,7 @@ namespace XNode { private static PortDataCache portDataCache; private static bool Initialized { get { return portDataCache != null; } } - /// Update static ports to reflect class fields. + /// Update static and dynamic ports to reflect class fields. public static void UpdatePorts(Node node, Dictionary ports) { if (!Initialized) BuildCache(); @@ -17,6 +18,8 @@ namespace XNode { Dictionary> removedPorts = new Dictionary>(); System.Type nodeType = node.GetType(); + List dynamicPorts = new List(); + List typePortCache; if (portDataCache.TryGetValue(nodeType, out typePortCache)) { for (int i = 0; i < typePortCache.Count; i++) { @@ -25,6 +28,7 @@ namespace XNode { } // Cleanup port dict - Remove nonexisting static ports - update static port types + // AND update dynamic ports too! // Loop through current node ports foreach (NodePort port in ports.Values.ToList()) { // If port still exists, check it it has been changed @@ -43,6 +47,10 @@ namespace XNode { port.ClearConnections(); ports.Remove(port.fieldName); } + // If the port is dynamic, flag it for reference updates + else { + dynamicPorts.Add(port); + } } // Add missing ports foreach (NodePort staticPort in staticPorts.Values) { @@ -60,6 +68,31 @@ namespace XNode { ports.Add(staticPort.fieldName, port); } } + + // Finally, make sure dynamic port settings correspond to the settings of their backing field + foreach (NodePort dynamicPort in dynamicPorts) { + string[] parts = dynamicPort.fieldName.Split(' '); + if (parts.Length != 2) { + Debug.LogError("Dynamic port name " + dynamicPort.fieldName + " is invalid."); + continue; + } + string backingPortName = parts[0]; + NodePort backingPort; + if (!staticPorts.TryGetValue(backingPortName, out backingPort)) { + Debug.LogError($"Could not find backing port \"{backingPortName}\" for port {dynamicPort.fieldName}"); + continue; + } + + // Update port constraints. Creating a new port instead will break the editor, mandating the need for setters. + dynamicPort.ValueType = backingPort.ValueType; + dynamicPort.direction = backingPort.direction; + dynamicPort.connectionType = backingPort.connectionType; + dynamicPort.typeConstraint = backingPort.typeConstraint; + + } + + + } /// Cache node types @@ -150,5 +183,10 @@ namespace XNode { this.Add(keys[i], values[i]); } } + + [MenuItem("TOOLS/LOL")] + public static void LOL() { + portDataCache = null; + } } } diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs index 58a3bd6..a41b667 100644 --- a/Scripts/NodePort.cs +++ b/Scripts/NodePort.cs @@ -19,9 +19,22 @@ namespace XNode { } } - public IO direction { get { return _direction; } } - public Node.ConnectionType connectionType { get { return _connectionType; } } - public Node.TypeConstraint typeConstraint { get { return _typeConstraint; } } + // public IO direction { get { return _direction; } } + // public Node.ConnectionType connectionType { get { return _connectionType; } } + // public Node.TypeConstraint typeConstraint { get { return _typeConstraint; } } + + public IO direction { + get { return _direction; } + internal set { _direction = value; } + } + public Node.ConnectionType connectionType { + get { return _connectionType; } + internal set { _connectionType = value; } + } + public Node.TypeConstraint typeConstraint { + get { return _typeConstraint; } + internal set { _typeConstraint = value; } + } /// Is this port connected to anytihng? public bool IsConnected { get { return connections.Count != 0; } }