| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Reflection;
 
- using UnityEngine;
 
- namespace XNode {
 
-     [Serializable]
 
-     public class NodePort {
 
-         public enum IO { Input, Output }
 
-         public int ConnectionCount { get { return connections.Count; } }
 
-         /// <summary> Return the first non-null connection </summary>
 
-         public NodePort Connection {
 
-             get {
 
-                 for (int i = 0; i < connections.Count; i++) {
 
-                     if (connections[i] != null) return connections[i].Port;
 
-                 }
 
-                 return null;
 
-             }
 
-         }
 
-         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; }
 
-         }
 
-         /// <summary> Is this port connected to anytihng? </summary>
 
-         public bool IsConnected { get { return connections.Count != 0; } }
 
-         public bool IsInput { get { return direction == IO.Input; } }
 
-         public bool IsOutput { get { return direction == IO.Output; } }
 
-         public string fieldName { get { return _fieldName; } }
 
-         public Node node { get { return _node; } }
 
-         public bool IsDynamic { get { return _dynamic; } }
 
-         public bool IsStatic { get { return !_dynamic; } }
 
-         public Type ValueType {
 
-             get {
 
-                 if (valueType == null && !string.IsNullOrEmpty(_typeQualifiedName)) valueType = Type.GetType(_typeQualifiedName, false);
 
-                 return valueType;
 
-             }
 
-             set {
 
-                 valueType = value;
 
-                 if (value != null) _typeQualifiedName = value.AssemblyQualifiedName;
 
-             }
 
-         }
 
-         private Type valueType;
 
-         [SerializeField] private string _fieldName;
 
-         [SerializeField] private Node _node;
 
-         [SerializeField] private string _typeQualifiedName;
 
-         [SerializeField] private List<PortConnection> connections = new List<PortConnection>();
 
-         [SerializeField] private IO _direction;
 
-         [SerializeField] private Node.ConnectionType _connectionType;
 
-         [SerializeField] private Node.TypeConstraint _typeConstraint;
 
-         [SerializeField] private bool _dynamic;
 
-         /// <summary> Construct a static targetless nodeport. Used as a template. </summary>
 
-         public NodePort(FieldInfo fieldInfo) {
 
-             _fieldName = fieldInfo.Name;
 
-             ValueType = fieldInfo.FieldType;
 
-             _dynamic = false;
 
-             var attribs = fieldInfo.GetCustomAttributes(false);
 
-             for (int i = 0; i < attribs.Length; i++) {
 
-                 if (attribs[i] is Node.InputAttribute) {
 
-                     _direction = IO.Input;
 
-                     _connectionType = (attribs[i] as Node.InputAttribute).connectionType;
 
-                     _typeConstraint = (attribs[i] as Node.InputAttribute).typeConstraint;
 
-                 } else if (attribs[i] is Node.OutputAttribute) {
 
-                     _direction = IO.Output;
 
-                     _connectionType = (attribs[i] as Node.OutputAttribute).connectionType;
 
-                     _typeConstraint = (attribs[i] as Node.OutputAttribute).typeConstraint;
 
-                 }
 
-             }
 
-         }
 
-         /// <summary> Copy a nodePort but assign it to another node. </summary>
 
-         public NodePort(NodePort nodePort, Node node) {
 
-             _fieldName = nodePort._fieldName;
 
-             ValueType = nodePort.valueType;
 
-             _direction = nodePort.direction;
 
-             _dynamic = nodePort._dynamic;
 
-             _connectionType = nodePort._connectionType;
 
-             _typeConstraint = nodePort._typeConstraint;
 
-             _node = node;
 
-         }
 
-         /// <summary> Construct a dynamic port. Dynamic ports are not forgotten on reimport, and is ideal for runtime-created ports. </summary>
 
-         public NodePort(string fieldName, Type type, IO direction, Node.ConnectionType connectionType, Node.TypeConstraint typeConstraint, Node node) {
 
-             _fieldName = fieldName;
 
-             this.ValueType = type;
 
-             _direction = direction;
 
-             _node = node;
 
-             _dynamic = true;
 
-             _connectionType = connectionType;
 
-             _typeConstraint = typeConstraint;
 
-         }
 
-         /// <summary> Checks all connections for invalid references, and removes them. </summary>
 
-         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)
 
-                     continue;
 
-                 connections.RemoveAt(i);
 
-             }
 
-         }
 
-         /// <summary> Return the output value of this node through its parent nodes GetValue override method. </summary>
 
-         /// <returns> <see cref="Node.GetValue(NodePort)"/> </returns>
 
-         public object GetOutputValue() {
 
-             if (direction == IO.Input) return null;
 
-             return node.GetValue(this);
 
-         }
 
-         /// <summary> Return the output value of the first connected port. Returns null if none found or invalid.</summary>
 
-         /// <returns> <see cref="NodePort.GetOutputValue"/> </returns>
 
-         public object GetInputValue() {
 
-             NodePort connectedPort = Connection;
 
-             if (connectedPort == null) return null;
 
-             return connectedPort.GetOutputValue();
 
-         }
 
-         /// <summary> Return the output values of all connected ports. </summary>
 
-         /// <returns> <see cref="NodePort.GetOutputValue"/> </returns>
 
-         public object[] GetInputValues() {
 
-             object[] objs = new object[ConnectionCount];
 
-             for (int i = 0; i < ConnectionCount; i++) {
 
-                 NodePort connectedPort = connections[i].Port;
 
-                 if (connectedPort == null) { // if we happen to find a null port, remove it and look again
 
-                     connections.RemoveAt(i);
 
-                     i--;
 
-                     continue;
 
-                 }
 
-                 objs[i] = connectedPort.GetOutputValue();
 
-             }
 
-             return objs;
 
-         }
 
-         /// <summary> Return the output value of the first connected port. Returns null if none found or invalid. </summary>
 
-         /// <returns> <see cref="NodePort.GetOutputValue"/> </returns>
 
-         public T GetInputValue<T>() {
 
-             object obj = GetInputValue();
 
-             return obj is T ? (T) obj : default(T);
 
-         }
 
-         /// <summary> Return the output values of all connected ports. </summary>
 
-         /// <returns> <see cref="NodePort.GetOutputValue"/> </returns>
 
-         public T[] GetInputValues<T>() {
 
-             object[] objs = GetInputValues();
 
-             T[] ts = new T[objs.Length];
 
-             for (int i = 0; i < objs.Length; i++) {
 
-                 if (objs[i] is T) ts[i] = (T) objs[i];
 
-             }
 
-             return ts;
 
-         }
 
-         /// <summary> Return true if port is connected and has a valid input. </summary>
 
-         /// <returns> <see cref="NodePort.GetOutputValue"/> </returns>
 
-         public bool TryGetInputValue<T>(out T value) {
 
-             object obj = GetInputValue();
 
-             if (obj is T) {
 
-                 value = (T) obj;
 
-                 return true;
 
-             } else {
 
-                 value = default(T);
 
-                 return false;
 
-             }
 
-         }
 
-         /// <summary> Return the sum of all inputs. </summary>
 
-         /// <returns> <see cref="NodePort.GetOutputValue"/> </returns>
 
-         public float GetInputSum(float fallback) {
 
-             object[] objs = GetInputValues();
 
-             if (objs.Length == 0) return fallback;
 
-             float result = 0;
 
-             for (int i = 0; i < objs.Length; i++) {
 
-                 if (objs[i] is float) result += (float) objs[i];
 
-             }
 
-             return result;
 
-         }
 
-         /// <summary> Return the sum of all inputs. </summary>
 
-         /// <returns> <see cref="NodePort.GetOutputValue"/> </returns>
 
-         public int GetInputSum(int fallback) {
 
-             object[] objs = GetInputValues();
 
-             if (objs.Length == 0) return fallback;
 
-             int result = 0;
 
-             for (int i = 0; i < objs.Length; i++) {
 
-                 if (objs[i] is int) result += (int) objs[i];
 
-             }
 
-             return result;
 
-         }
 
-         /// <summary> Connect this <see cref="NodePort"/> to another </summary>
 
-         /// <param name="port">The <see cref="NodePort"/> to connect to</param>
 
-         public void Connect(NodePort port) {
 
-             if (connections == null) connections = new List<PortConnection>();
 
-             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 UNITY_EDITOR
 
-             UnityEditor.Undo.RecordObject(node, "Connect Port");
 
-             UnityEditor.Undo.RecordObject(port.node, "Connect Port");
 
- #endif
 
-             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<PortConnection>();
 
-             if (!port.IsConnectedTo(this)) port.connections.Add(new PortConnection(this));
 
-             node.OnCreateConnection(this, port);
 
-             port.node.OnCreateConnection(this, port);
 
-         }
 
-         public List<NodePort> GetConnections() {
 
-             List<NodePort> result = new List<NodePort>();
 
-             for (int i = 0; i < connections.Count; i++) {
 
-                 NodePort port = GetConnection(i);
 
-                 if (port != null) result.Add(port);
 
-             }
 
-             return result;
 
-         }
 
-         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;
 
-         }
 
-         /// <summary> Get index of the connection connecting this and specified ports </summary>
 
-         public int GetConnectionIndex(NodePort port) {
 
-             for (int i = 0; i < ConnectionCount; i++) {
 
-                 if (connections[i].Port == port) return i;
 
-             }
 
-             return -1;
 
-         }
 
-         public bool IsConnectedTo(NodePort port) {
 
-             for (int i = 0; i < connections.Count; i++) {
 
-                 if (connections[i].Port == port) return true;
 
-             }
 
-             return false;
 
-         }
 
-         /// <summary> Returns true if this port can connect to specified port </summary>
 
-         public bool CanConnectTo(NodePort port) {
 
-             // Figure out which is input and which is output
 
-            
 
-             NodePort input = null, output = null;
 
-             if (IsInput) input = this;
 
-             else output = this;
 
-             if (port.IsInput) input = port;
 
-             else output = port;
 
-             // If there isn't one of each, they can't connect
 
-             if (input == null || output == null) return false;
 
-             // Check input type constraints
 
-             
 
- #if UNITY_EDITOR
 
-             // Debug.Log(input.node.GetType().ToString()+"___"+output.node.GetType().ToString());
 
-             if (!IsConflict( input,output))
 
-             {
 
-                 
 
-                 return false;
 
-             }
 
- #endif
 
-             if (input.typeConstraint == XNode.Node.TypeConstraint.Inherited && !input.ValueType.IsAssignableFrom(output.ValueType)) return false;
 
-             if (input.typeConstraint == XNode.Node.TypeConstraint.Strict && input.ValueType != output.ValueType) return false;
 
-             if (input.typeConstraint == XNode.Node.TypeConstraint.InheritedInverse && !output.ValueType.IsAssignableFrom(input.ValueType)) return false;
 
-             // Check output type constraints
 
-             if (output.typeConstraint == XNode.Node.TypeConstraint.Inherited && !input.ValueType.IsAssignableFrom(output.ValueType)) return false;
 
-             if (output.typeConstraint == XNode.Node.TypeConstraint.Strict && input.ValueType != output.ValueType) return false;
 
-             if (output.typeConstraint == XNode.Node.TypeConstraint.InheritedInverse && !output.ValueType.IsAssignableFrom(input.ValueType)) return false;
 
-             // Success
 
-            
 
-             
 
-             return true;
 
-         }
 
- #if UNITY_EDITOR
 
-         private bool IsConflict( NodePort input , NodePort output )
 
-         {
 
-             XNode.Node.CreateNodeMenuAttribute cma;
 
-             GetAttrib(input.node.GetType(), out cma);
 
-             if (cma != null && cma.isServerRecord)
 
-             {
 
-                 List<NodePort>  nodes=  output.GetConnections();
 
-                 for (int i = 0; i < nodes.Count; i++)
 
-                 {
 
-                     XNode.Node.CreateNodeMenuAttribute cma2;
 
-                     if (GetAttrib(nodes[i].node.GetType(), out cma2))
 
-                     {
 
-                         if (cma2.isServerRecord)
 
-                         {
 
-                             return false;
 
-                         }
 
-                     }
 
-                 }
 
-             }
 
-             return true;
 
-         }
 
-         public static bool GetAttrib<T>(Type classType, out T attribOut) where T : Attribute {
 
-             object[] attribs = classType.GetCustomAttributes(typeof(T), false);
 
-             return GetAttrib(attribs, out attribOut);
 
-         }
 
-         public static bool GetAttrib<T>(object[] attribs, out T attribOut) where T : Attribute {
 
-             for (int i = 0; i < attribs.Length; i++) {
 
-                 if (attribs[i] is T) {
 
-                     attribOut = attribs[i] as T;
 
-                     return true;
 
-                 }
 
-             }
 
-             attribOut = null;
 
-             return false;
 
-         }
 
- #endif
 
-         /// <summary> Disconnect this port from another port </summary>
 
-         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);
 
-                 }
 
-             }
 
-             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);
 
-                     }
 
-                 }
 
-             }
 
-             // Trigger OnRemoveConnection
 
-             node.OnRemoveConnection(this);
 
-             if (port != null) port.node.OnRemoveConnection(port);
 
-         }
 
-         /// <summary> Disconnect this port from another port </summary>
 
-         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);
 
-         }
 
-         public void ClearConnections() {
 
-             while (connections.Count > 0) {
 
-                 Disconnect(connections[0].Port);
 
-             }
 
-         }
 
-         /// <summary> Get reroute points for a given connection. This is used for organization </summary>
 
-         public List<Vector2> GetReroutePoints(int index) {
 
-             return connections[index].reroutePoints;
 
-         }
 
-         /// <summary> Swap connections with another node </summary>
 
-         public void SwapConnections(NodePort targetPort) {
 
-             int aConnectionCount = connections.Count;
 
-             int bConnectionCount = targetPort.connections.Count;
 
-             List<NodePort> portConnections = new List<NodePort>();
 
-             List<NodePort> targetPortConnections = new List<NodePort>();
 
-             // Cache port connections
 
-             for (int i = 0; i < aConnectionCount; i++)
 
-                 portConnections.Add(connections[i].Port);
 
-             // Cache target port connections
 
-             for (int i = 0; i < bConnectionCount; i++)
 
-                 targetPortConnections.Add(targetPort.connections[i].Port);
 
-             ClearConnections();
 
-             targetPort.ClearConnections();
 
-             // Add port connections to targetPort
 
-             for (int i = 0; i < portConnections.Count; i++)
 
-                 targetPort.Connect(portConnections[i]);
 
-             // Add target port connections to this one
 
-             for (int i = 0; i < targetPortConnections.Count; i++)
 
-                 Connect(targetPortConnections[i]);
 
-         }
 
-         /// <summary> Copy all connections pointing to a node and add them to this one </summary>
 
-         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;
 
-                 Connect(otherPort);
 
-             }
 
-         }
 
-         /// <summary> Move all connections pointing to this node, to another node </summary>
 
-         public void MoveConnections(NodePort targetPort) {
 
-             int connectionCount = connections.Count;
 
-             // Add connections to target port
 
-             for (int i = 0; i < connectionCount; i++) {
 
-                 PortConnection connection = targetPort.connections[i];
 
-                 NodePort otherPort = connection.Port;
 
-                 Connect(otherPort);
 
-             }
 
-             ClearConnections();
 
-         }
 
-         /// <summary> Swap connected nodes from the old list with nodes from the new list </summary>
 
-         public void Redirect(List<Node> oldNodes, List<Node> newNodes) {
 
-             foreach (PortConnection connection in connections) {
 
-                 int index = oldNodes.IndexOf(connection.node);
 
-                 if (index >= 0) connection.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;
 
-             /// <summary> Extra connection path points for organization </summary>
 
-             [SerializeField] public List<Vector2> reroutePoints = new List<Vector2>();
 
-             public PortConnection(NodePort port) {
 
-                 this.port = port;
 
-                 node = port.node;
 
-                 fieldName = port.fieldName;
 
-             }
 
-             /// <summary> Returns the port that this <see cref="PortConnection"/> points to </summary>
 
-             private NodePort GetPort() {
 
-                 if (node == null || string.IsNullOrEmpty(fieldName)) return null;
 
-                 return node.GetPort(fieldName);
 
-             }
 
-         }
 
-     }
 
- }
 
 
  |