From 803b327522a46af00b3467ded3268f9e3c06dda6 Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Fri, 7 Jun 2019 02:56:05 +0200 Subject: [PATCH] Swapped GetConnections for ReadOnlyCollection. Performance is much faster but i'm having issues initializing connectionCache and rerouteCache --- Scripts/NodePort.cs | 176 +++++++++++++++++++++++--------------------- 1 file changed, 91 insertions(+), 85 deletions(-) diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs index 24e4941..0ae467a 100644 --- a/Scripts/NodePort.cs +++ b/Scripts/NodePort.cs @@ -1,19 +1,21 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Reflection; using UnityEngine; +using UnityEngine.Serialization; namespace XNode { [Serializable] - public class NodePort { + public class NodePort : ISerializationCallbackReceiver { public enum IO { Input, Output } - public int ConnectionCount { get { return connections.Count; } } + public int ConnectionCount { get { return connectionCache.Count; } } /// Return the first non-null connection public NodePort Connection { get { - for (int i = 0; i < connections.Count; i++) { - if (connections[i] != null) return connections[i].Port; + for (int i = 0; i < connectionCache.Count; i++) { + if (connectionCache[i] != null) return connectionCache[i]; } return null; } @@ -22,9 +24,10 @@ namespace XNode { public IO direction { get { return _direction; } } public Node.ConnectionType connectionType { get { return _connectionType; } } public Node.TypeConstraint typeConstraint { get { return _typeConstraint; } } + public ReadOnlyCollection Connections { get; private set; } /// Is this port connected to anytihng? - public bool IsConnected { get { return connections.Count != 0; } } + public bool IsConnected { get { return connectionCache.Count != 0; } } public bool IsInput { get { return direction == IO.Input; } } public bool IsOutput { get { return direction == IO.Output; } } @@ -53,8 +56,12 @@ namespace XNode { [SerializeField] private Node.TypeConstraint _typeConstraint; [SerializeField] private bool _dynamic; + public List connectionCache = new List(); + public Dictionary> rerouteCache = new Dictionary>(); + /// Construct a static targetless nodeport. Used as a template. public NodePort(FieldInfo fieldInfo) { + Debug.Log("Create, " + connectionCache + ", " + rerouteCache, node); _fieldName = fieldInfo.Name; ValueType = fieldInfo.FieldType; _dynamic = false; @@ -73,6 +80,7 @@ namespace XNode { /// Copy a nodePort but assign it to another node. public NodePort(NodePort nodePort, Node node) { + Debug.Log("Create"); _fieldName = nodePort._fieldName; ValueType = nodePort.valueType; _direction = nodePort.direction; @@ -84,6 +92,7 @@ namespace XNode { /// Construct a dynamic port. Dynamic ports are not forgotten on reimport, and is ideal for runtime-created ports. public NodePort(string fieldName, Type type, IO direction, Node.ConnectionType connectionType, Node.TypeConstraint typeConstraint, Node node) { + Debug.Log("Create"); _fieldName = fieldName; this.ValueType = type; _direction = direction; @@ -93,14 +102,37 @@ namespace XNode { _typeConstraint = typeConstraint; } + public void OnBeforeSerialize() { + connections = new List(); + for (int i = 0; i < connectionCache.Count; i++) { + List reroutes; + if (rerouteCache.TryGetValue(connectionCache[i], out reroutes)) { + connections.Add(new PortConnection(connectionCache[i], reroutes)); + } else { + connections.Add(new PortConnection(connectionCache[i])); + } + } + } + + public void OnAfterDeserialize() { + connectionCache.Clear(); + rerouteCache.Clear(); + for (int i = 0; i < connections.Count; i++) { + NodePort port = connections[i].GetPort(); + connectionCache.Add(port); + rerouteCache.Add(port, connections[i].reroutePoints); + } + Connections = new ReadOnlyCollection(connectionCache); + } + /// Checks all connections for invalid references, and removes them. public void VerifyConnections() { - for (int i = connections.Count - 1; i >= 0; i--) { - if (connections[i].node != null && - !string.IsNullOrEmpty(connections[i].fieldName) && - connections[i].node.GetPort(connections[i].fieldName) != null) + for (int i = connectionCache.Count - 1; i >= 0; i--) { + if (connectionCache[i].node != null && + !string.IsNullOrEmpty(connectionCache[i].fieldName) && + connectionCache[i].node.GetPort(connectionCache[i].fieldName) != null) continue; - connections.RemoveAt(i); + connectionCache.RemoveAt(i); } } @@ -124,9 +156,9 @@ namespace XNode { public object[] GetInputValues() { object[] objs = new object[ConnectionCount]; for (int i = 0; i < ConnectionCount; i++) { - NodePort connectedPort = connections[i].Port; + NodePort connectedPort = connectionCache[i]; if (connectedPort == null) { // if we happen to find a null port, remove it and look again - connections.RemoveAt(i); + connectionCache.RemoveAt(i); i--; continue; } @@ -193,56 +225,41 @@ namespace XNode { /// Connect this to another /// The to connect to public void Connect(NodePort port) { - if (connections == null) connections = new List(); if (port == null) { Debug.LogWarning("Cannot connect to null port"); return; } if (port == this) { Debug.LogWarning("Cannot connect port to self."); return; } if (IsConnectedTo(port)) { Debug.LogWarning("Port already connected. "); return; } if (direction == port.direction) { Debug.LogWarning("Cannot connect two " + (direction == IO.Input ? "input" : "output") + " connections"); return; } if (port.connectionType == Node.ConnectionType.Override && port.ConnectionCount != 0) { port.ClearConnections(); } if (connectionType == Node.ConnectionType.Override && ConnectionCount != 0) { ClearConnections(); } - connections.Add(new PortConnection(port)); - if (port.connections == null) port.connections = new List(); - if (!port.IsConnectedTo(this)) port.connections.Add(new PortConnection(this)); + connectionCache.Add(port); + port.connectionCache.Add(this); node.OnCreateConnection(this, port); port.node.OnCreateConnection(this, port); } + [Obsolete("Use Connections property instead")] public List GetConnections() { List result = new List(); - for (int i = 0; i < connections.Count; i++) { - NodePort port = GetConnection(i); - if (port != null) result.Add(port); + for (int i = 0; i < connectionCache.Count; i++) { + NodePort port = connectionCache[i]; + result.Add(port); } return result; } + [Obsolete("Use Connections[i] instead")] public NodePort GetConnection(int i) { - //If the connection is broken for some reason, remove it. - if (connections[i].node == null || string.IsNullOrEmpty(connections[i].fieldName)) { - connections.RemoveAt(i); - return null; - } - NodePort port = connections[i].node.GetPort(connections[i].fieldName); - if (port == null) { - connections.RemoveAt(i); - return null; - } - return port; + return connectionCache[i]; } + [Obsolete("Use Connections.IndexOf(port) instead")] /// Get index of the connection connecting this and specified ports public int GetConnectionIndex(NodePort port) { - for (int i = 0; i < ConnectionCount; i++) { - if (connections[i].Port == port) return i; - } - return -1; + return connectionCache.IndexOf(port); } public bool IsConnectedTo(NodePort port) { - for (int i = 0; i < connections.Count; i++) { - if (connections[i].Port == port) return true; - } - return false; + return connectionCache.Contains(port); } /// Returns true if this port can connect to specified port @@ -265,17 +282,13 @@ namespace XNode { /// Disconnect this port from another port public void Disconnect(NodePort port) { // Remove this ports connection to the other - for (int i = connections.Count - 1; i >= 0; i--) { - if (connections[i].Port == port) { - connections.RemoveAt(i); - } + for (int i = connectionCache.Count - 1; i >= 0; i--) { + connectionCache.Remove(port); } if (port != null) { // Remove the other ports connection to this port - for (int i = 0; i < port.connections.Count; i++) { - if (port.connections[i].Port == this) { - port.connections.RemoveAt(i); - } + for (int i = 0; i < port.connectionCache.Count; i++) { + port.connectionCache.Remove(this); } } // Trigger OnRemoveConnection @@ -285,49 +298,44 @@ namespace XNode { /// Disconnect this port from another port public void Disconnect(int i) { - // Remove the other ports connection to this port - NodePort otherPort = connections[i].Port; - if (otherPort != null) { - for (int k = 0; k < otherPort.connections.Count; k++) { - if (otherPort.connections[k].Port == this) { - otherPort.connections.RemoveAt(i); - } - } - } - // Remove this ports connection to the other - connections.RemoveAt(i); - - // Trigger OnRemoveConnection - node.OnRemoveConnection(this); - if (otherPort != null) otherPort.node.OnRemoveConnection(otherPort); + Disconnect(connectionCache[i]); } + /// Disconnect all ports from this port public void ClearConnections() { - while (connections.Count > 0) { - Disconnect(connections[0].Port); + for (int i = connectionCache.Count - 1; i >= 0; i--) { + Disconnect(connectionCache[i]); } } + /// Get reroute points for a given connection. This is used for organization + public List GetReroutePoints(NodePort port) { + List reroutes = new List(); + Debug.Log(port + " " + rerouteCache, node); + rerouteCache.TryGetValue(port, out reroutes); + return reroutes; + } + /// Get reroute points for a given connection. This is used for organization public List GetReroutePoints(int index) { - return connections[index].reroutePoints; + return GetReroutePoints(connectionCache[index]); } /// Swap connections with another node public void SwapConnections(NodePort targetPort) { - int aConnectionCount = connections.Count; - int bConnectionCount = targetPort.connections.Count; + int aConnectionCount = connectionCache.Count; + int bConnectionCount = targetPort.connectionCache.Count; List portConnections = new List(); List targetPortConnections = new List(); // Cache port connections for (int i = 0; i < aConnectionCount; i++) - portConnections.Add(connections[i].Port); + portConnections.Add(connectionCache[i]); // Cache target port connections for (int i = 0; i < bConnectionCount; i++) - targetPortConnections.Add(targetPort.connections[i].Port); + targetPortConnections.Add(targetPort.connectionCache[i]); ClearConnections(); targetPort.ClearConnections(); @@ -346,20 +354,18 @@ namespace XNode { public void AddConnections(NodePort targetPort) { int connectionCount = targetPort.ConnectionCount; for (int i = 0; i < connectionCount; i++) { - PortConnection connection = targetPort.connections[i]; - NodePort otherPort = connection.Port; + NodePort otherPort = targetPort.connectionCache[i]; Connect(otherPort); } } /// Move all connections pointing to this node, to another node public void MoveConnections(NodePort targetPort) { - int connectionCount = connections.Count; + int connectionCount = connectionCache.Count; // Add connections to target port for (int i = 0; i < connectionCount; i++) { - PortConnection connection = targetPort.connections[i]; - NodePort otherPort = connection.Port; + NodePort otherPort = targetPort.connectionCache[i]; Connect(otherPort); } ClearConnections(); @@ -367,31 +373,31 @@ namespace XNode { /// Swap connected nodes from the old list with nodes from the new list public void Redirect(List oldNodes, List newNodes) { - foreach (PortConnection connection in connections) { - int index = oldNodes.IndexOf(connection.node); - if (index >= 0) connection.node = newNodes[index]; + foreach (NodePort port in connectionCache) { + int index = oldNodes.IndexOf(port._node); + if (index >= 0) port._node = newNodes[index]; } } [Serializable] private class PortConnection { - [SerializeField] public string fieldName; - [SerializeField] public Node node; - public NodePort Port { get { return port != null ? port : port = GetPort(); } } - - [NonSerialized] private NodePort port; + [SerializeField] private string fieldName; + [SerializeField] private Node node; /// Extra connection path points for organization [SerializeField] public List reroutePoints = new List(); public PortConnection(NodePort port) { - this.port = port; node = port.node; fieldName = port.fieldName; } - /// Returns the port that this points to - private NodePort GetPort() { - if (node == null || string.IsNullOrEmpty(fieldName)) return null; + public PortConnection(NodePort port, List reroutePoints) { + node = port.node; + fieldName = port.fieldName; + this.reroutePoints = reroutePoints; + } + + public NodePort GetPort() { return node.GetPort(fieldName); } }