| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704 | 
							- using System;
 
- using System.Collections.Generic;
 
- using UnityEngine;
 
- namespace XNode
 
- {
 
-     /// <summary>
 
-     /// Base class for all nodes
 
-     /// </summary>
 
-     /// <example>
 
-     /// Classes extending this class will be considered as valid nodes by xNode.
 
-     /// <code>
 
-     /// [System.Serializable]
 
-     /// public class Adder : Node {
 
-     ///     [Input] public float a;
 
-     ///     [Input] public float b;
 
-     ///     [Output] public float result;
 
-     ///
 
-     ///     // GetValue should be overridden to return a value for any specified output port
 
-     ///     public override object GetValue(NodePort port) {
 
-     ///         return a + b;
 
-     ///     }
 
-     /// }
 
-     /// </code>
 
-     /// </example>
 
-     [Serializable]
 
-     public abstract class Node : ScriptableObject
 
-     {
 
-         /// <summary> Used by <see cref="InputAttribute"/> and <see cref="OutputAttribute"/> to determine when to display the field value associated with a <see cref="NodePort"/> </summary>
 
-         public enum ShowBackingValue
 
-         {
 
-             /// <summary> Never show the backing value </summary>
 
-             Never,
 
-             /// <summary> Show the backing value only when the port does not have any active connections </summary>
 
-             Unconnected,
 
-             /// <summary> Always show the backing value </summary>
 
-             Always
 
-         }
 
-         public enum ConnectionType
 
-         {
 
-             /// <summary> Allow multiple connections</summary>
 
-             Multiple,
 
-             /// <summary> always override the current connection </summary>
 
-             Override,
 
-         }
 
-         /// <summary> Tells which types of input to allow </summary>
 
-         public enum TypeConstraint
 
-         {
 
-             /// <summary> Allow all types of input</summary>
 
-             None,
 
-             /// <summary> Allow connections where input value type is assignable from output value type (eg. ScriptableObject --> Object)</summary>
 
-             Inherited,
 
-             /// <summary> Allow only similar types </summary>
 
-             Strict,
 
-             /// <summary> Allow connections where output value type is assignable from input value type (eg. Object --> ScriptableObject)</summary>
 
-             InheritedInverse,
 
-         }
 
-         public virtual bool IsRemove()
 
-         {
 
-             return true;
 
-         }
 
-         #region Obsolete
 
-         [Obsolete("Use DynamicPorts instead")]
 
-         public IEnumerable<NodePort> InstancePorts
 
-         {
 
-             get { return DynamicPorts; }
 
-         }
 
-         [Obsolete("Use DynamicOutputs instead")]
 
-         public IEnumerable<NodePort> InstanceOutputs
 
-         {
 
-             get { return DynamicOutputs; }
 
-         }
 
-         [Obsolete("Use DynamicInputs instead")]
 
-         public IEnumerable<NodePort> InstanceInputs
 
-         {
 
-             get { return DynamicInputs; }
 
-         }
 
-         [Obsolete("Use AddDynamicInput instead")]
 
-         public NodePort AddInstanceInput(Type type, ConnectionType connectionType = ConnectionType.Multiple, TypeConstraint typeConstraint = TypeConstraint.None,
 
-             string fieldName = null)
 
-         {
 
-             return AddDynamicInput(type, connectionType, typeConstraint, fieldName);
 
-         }
 
-         [Obsolete("Use AddDynamicOutput instead")]
 
-         public NodePort AddInstanceOutput(Type type, ConnectionType connectionType = ConnectionType.Multiple, TypeConstraint typeConstraint = TypeConstraint.None,
 
-             string fieldName = null)
 
-         {
 
-             return AddDynamicOutput(type, connectionType, typeConstraint, fieldName);
 
-         }
 
-         [Obsolete("Use AddDynamicPort instead")]
 
-         private NodePort AddInstancePort(Type type, NodePort.IO direction, ConnectionType connectionType = ConnectionType.Multiple, TypeConstraint typeConstraint = TypeConstraint.None,
 
-             string fieldName = null)
 
-         {
 
-             return AddDynamicPort(type, direction, connectionType, typeConstraint, fieldName);
 
-         }
 
-         [Obsolete("Use RemoveDynamicPort instead")]
 
-         public void RemoveInstancePort(string fieldName)
 
-         {
 
-             RemoveDynamicPort(fieldName);
 
-         }
 
-         [Obsolete("Use RemoveDynamicPort instead")]
 
-         public void RemoveInstancePort(NodePort port)
 
-         {
 
-             RemoveDynamicPort(port);
 
-         }
 
-         [Obsolete("Use ClearDynamicPorts instead")]
 
-         public void ClearInstancePorts()
 
-         {
 
-             ClearDynamicPorts();
 
-         }
 
-         #endregion
 
-         /// <summary> Iterate over all ports on this node. </summary>
 
-         public IEnumerable<NodePort> Ports
 
-         {
 
-             get
 
-             {
 
-                 foreach (NodePort port in ports.Values) yield return port;
 
-             }
 
-         }
 
-         /// <summary> Iterate over all outputs on this node. </summary>
 
-         public IEnumerable<NodePort> Outputs
 
-         {
 
-             get
 
-             {
 
-                 foreach (NodePort port in Ports)
 
-                 {
 
-                     if (port.IsOutput) yield return port;
 
-                 }
 
-             }
 
-         }
 
-         /// <summary> Iterate over all inputs on this node. </summary>
 
-         public IEnumerable<NodePort> Inputs
 
-         {
 
-             get
 
-             {
 
-                 foreach (NodePort port in Ports)
 
-                 {
 
-                     if (port.IsInput) yield return port;
 
-                 }
 
-             }
 
-         }
 
-         /// <summary> Iterate over all dynamic ports on this node. </summary>
 
-         public IEnumerable<NodePort> DynamicPorts
 
-         {
 
-             get
 
-             {
 
-                 foreach (NodePort port in Ports)
 
-                 {
 
-                     if (port.IsDynamic) yield return port;
 
-                 }
 
-             }
 
-         }
 
-         /// <summary> Iterate over all dynamic outputs on this node. </summary>
 
-         public IEnumerable<NodePort> DynamicOutputs
 
-         {
 
-             get
 
-             {
 
-                 foreach (NodePort port in Ports)
 
-                 {
 
-                     if (port.IsDynamic && port.IsOutput) yield return port;
 
-                 }
 
-             }
 
-         }
 
-         /// <summary> Iterate over all dynamic inputs on this node. </summary>
 
-         public IEnumerable<NodePort> DynamicInputs
 
-         {
 
-             get
 
-             {
 
-                 foreach (NodePort port in Ports)
 
-                 {
 
-                     if (port.IsDynamic && port.IsInput) yield return port;
 
-                 }
 
-             }
 
-         }
 
-         /// <summary> Parent <see cref="NodeGraph"/> </summary>
 
-         [SerializeField] public NodeGraph graph;
 
-         /// <summary> Position on the <see cref="NodeGraph"/> </summary>
 
-         [SerializeField] public Vector2 position;
 
-         [NodeSerialize("GUID")] [SerializeField]
 
-         public int guid;
 
-         [HideInInspector] [SerializeField] private int uniqueID;
 
-         /// <summary>
 
-         /// 唯一ID,首次创建的时候赋值
 
-         /// </summary>
 
-         public int UniqueID
 
-         {
 
-             get
 
-             {
 
-                 if (uniqueID == 0)
 
-                 {
 
-                     uniqueID = GetInstanceID();
 
-                 }
 
-                 return uniqueID;
 
-             }
 
-             set
 
-             {
 
-                 if (UniqueID == 0)
 
-                 {
 
-                     uniqueID = value;
 
-                 }
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// 复制组件的时候调用
 
-         /// </summary>
 
-         public void ResetUniqueID()
 
-         {
 
-             uniqueID = GetInstanceID();
 
-         }
 
-         /// <summary> It is recommended not to modify these at hand. Instead, see <see cref="InputAttribute"/> and <see cref="OutputAttribute"/> </summary>
 
-         [SerializeField] private NodePortDictionary ports = new NodePortDictionary();
 
-         /// <summary> Used during node instantiation to fix null/misconfigured graph during OnEnable/Init. Set it before instantiating a node. Will automatically be unset during OnEnable </summary>
 
-         public static NodeGraph graphHotfix;
 
-         protected void OnEnable()
 
-         {
 
-             if (graphHotfix != null) graph = graphHotfix;
 
-             graphHotfix = null;
 
-             UpdatePorts();
 
-             Init();
 
-         }
 
-         /// <summary> Update static ports and dynamic ports managed by DynamicPortLists to reflect class fields. This happens automatically on enable or on redrawing a dynamic port list. </summary>
 
-         public void UpdatePorts()
 
-         {
 
-             NodeDataCache.UpdatePorts(this, ports);
 
-         }
 
-         /// <summary> Initialize node. Called on enable. </summary>
 
-         public virtual void Init()
 
-         {
 
-         }
 
-         /// <summary> Checks all connections for invalid references, and removes them. </summary>
 
-         public void VerifyConnections()
 
-         {
 
-             foreach (NodePort port in Ports) port.VerifyConnections();
 
-         }
 
-         #region Dynamic Ports
 
-         /// <summary> Convenience function. </summary>
 
-         /// <seealso cref="AddInstancePort"/>
 
-         /// <seealso cref="AddInstanceOutput"/>
 
-         public NodePort AddDynamicInput(Type type, ConnectionType connectionType = ConnectionType.Multiple, TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null)
 
-         {
 
-             return AddDynamicPort(type, NodePort.IO.Input, connectionType, typeConstraint, fieldName);
 
-         }
 
-         /// <summary> Convenience function. </summary>
 
-         /// <seealso cref="AddInstancePort"/>
 
-         /// <seealso cref="AddInstanceInput"/>
 
-         public NodePort AddDynamicOutput(Type type, ConnectionType connectionType = ConnectionType.Multiple, TypeConstraint typeConstraint = TypeConstraint.None,
 
-             string fieldName = null)
 
-         {
 
-             return AddDynamicPort(type, NodePort.IO.Output, connectionType, typeConstraint, fieldName);
 
-         }
 
-         /// <summary> Add a dynamic, serialized port to this node. </summary>
 
-         /// <seealso cref="AddDynamicInput"/>
 
-         /// <seealso cref="AddDynamicOutput"/>
 
-         private NodePort AddDynamicPort(Type type, NodePort.IO direction, ConnectionType connectionType = ConnectionType.Multiple, TypeConstraint typeConstraint = TypeConstraint.None,
 
-             string fieldName = null)
 
-         {
 
-             if (fieldName == null)
 
-             {
 
-                 fieldName = "dynamicInput_0";
 
-                 int i = 0;
 
-                 while (HasPort(fieldName)) fieldName = "dynamicInput_" + (++i);
 
-             }
 
-             else if (HasPort(fieldName))
 
-             {
 
-                 Debug.LogWarning("Port '" + fieldName + "' already exists in " + name, this);
 
-                 return ports[fieldName];
 
-             }
 
-             NodePort port = new NodePort(fieldName, type, direction, connectionType, typeConstraint, this);
 
-             ports.Add(fieldName, port);
 
-             return port;
 
-         }
 
-         /// <summary> Remove an dynamic port from the node </summary>
 
-         public void RemoveDynamicPort(string fieldName)
 
-         {
 
-             NodePort dynamicPort = GetPort(fieldName);
 
-             if (dynamicPort == null) throw new ArgumentException("port " + fieldName + " doesn't exist");
 
-             RemoveDynamicPort(GetPort(fieldName));
 
-         }
 
-         /// <summary> Remove an dynamic port from the node </summary>
 
-         public void RemoveDynamicPort(NodePort port)
 
-         {
 
-             if (port == null) throw new ArgumentNullException("port");
 
-             else if (port.IsStatic) throw new ArgumentException("cannot remove static port");
 
-             port.ClearConnections();
 
-             ports.Remove(port.fieldName);
 
-         }
 
-         /// <summary> Removes all dynamic ports from the node </summary>
 
-         [ContextMenu("Clear Dynamic Ports")]
 
-         public void ClearDynamicPorts()
 
-         {
 
-             List<NodePort> dynamicPorts = new List<NodePort>(DynamicPorts);
 
-             foreach (NodePort port in dynamicPorts)
 
-             {
 
-                 RemoveDynamicPort(port);
 
-             }
 
-         }
 
-         #endregion
 
-         #region Ports
 
-         /// <summary> Returns output port which matches fieldName </summary>
 
-         public NodePort GetOutputPort(string fieldName)
 
-         {
 
-             NodePort port = GetPort(fieldName);
 
-             if (port == null || port.direction != NodePort.IO.Output) return null;
 
-             else return port;
 
-         }
 
-         /// <summary> Returns input port which matches fieldName </summary>
 
-         public NodePort GetInputPort(string fieldName)
 
-         {
 
-             NodePort port = GetPort(fieldName);
 
-             if (port == null || port.direction != NodePort.IO.Input) return null;
 
-             else return port;
 
-         }
 
-         /// <summary> Returns port which matches fieldName </summary>
 
-         public NodePort GetPort(string fieldName)
 
-         {
 
-             NodePort port;
 
-             if (ports.TryGetValue(fieldName, out port)) return port;
 
-             else return null;
 
-         }
 
-         public bool HasPort(string fieldName)
 
-         {
 
-             return ports.ContainsKey(fieldName);
 
-         }
 
-         #endregion
 
-         #region Inputs/Outputs
 
-         /// <summary> Return input value for a specified port. Returns fallback value if no ports are connected </summary>
 
-         /// <param name="fieldName">Field name of requested input port</param>
 
-         /// <param name="fallback">If no ports are connected, this value will be returned</param>
 
-         public T GetInputValue<T>(string fieldName, T fallback = default(T))
 
-         {
 
-             NodePort port = GetPort(fieldName);
 
-             if (port != null && port.IsConnected) return port.GetInputValue<T>();
 
-             else return fallback;
 
-         }
 
-         /// <summary> Return all input values for a specified port. Returns fallback value if no ports are connected </summary>
 
-         /// <param name="fieldName">Field name of requested input port</param>
 
-         /// <param name="fallback">If no ports are connected, this value will be returned</param>
 
-         public T[] GetInputValues<T>(string fieldName, params T[] fallback)
 
-         {
 
-             NodePort port = GetPort(fieldName);
 
-             if (port != null && port.IsConnected) return port.GetInputValues<T>();
 
-             else return fallback;
 
-         }
 
-         /// <summary> Returns a value based on requested port output. Should be overridden in all derived nodes with outputs. </summary>
 
-         /// <param name="port">The requested port.</param>
 
-         public virtual object GetValue(NodePort port)
 
-         {
 
-             Debug.LogWarning("No GetValue(NodePort port) override defined for " + GetType());
 
-             return null;
 
-         }
 
-         #endregion
 
-         /// <summary> Called after a connection between two <see cref="NodePort"/>s is created </summary>
 
-         /// <param name="from">Output</param> <param name="to">Input</param>
 
-         public virtual void OnCreateConnection(NodePort from, NodePort to)
 
-         {
 
-         }
 
-         /// <summary> Called after a connection is removed from this port </summary>
 
-         /// <param name="port">Output or Input</param>
 
-         public virtual void OnRemoveConnection(NodePort port)
 
-         {
 
-         }
 
-         /// <summary> Disconnect everything from this node </summary>
 
-         public void ClearConnections()
 
-         {
 
-             foreach (NodePort port in Ports) port.ClearConnections();
 
-         }
 
-         #region Attributes
 
-         [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property)]
 
-         public class NodeSerializeAttribute : Attribute
 
-         {
 
-             public string showName;
 
-             public string tooltip;
 
-             public int showType;
 
-             public bool isDisable;
 
-             public NodeSerializeAttribute(string showName, string tooltip = "", int showType = 0, bool isDisable = false)
 
-             {
 
-                 this.showName = showName;
 
-                 this.tooltip = tooltip;
 
-                 this.showType = showType;
 
-                 this.isDisable = isDisable;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// 这里暂时用来处理RandomNode的
 
-         /// </summary>
 
-         [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property)]
 
-         public class NodeSerializeAttributeSpecial : Attribute
 
-         {
 
-         }
 
-         // [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property)]
 
-         // public class DisabledAttribute : Attribute
 
-         // {
 
-         // }
 
-         /// <summary> Mark a serializable field as an input port. You can access this through <see cref="GetInputPort(string)"/> </summary>
 
-         [AttributeUsage(AttributeTargets.Field)]
 
-         public class InputAttribute : Attribute
 
-         {
 
-             public ShowBackingValue backingValue;
 
-             public ConnectionType connectionType;
 
-             [Obsolete("Use dynamicPortList instead")]
 
-             public bool instancePortList
 
-             {
 
-                 get { return dynamicPortList; }
 
-                 set { dynamicPortList = value; }
 
-             }
 
-             public bool dynamicPortList;
 
-             public TypeConstraint typeConstraint;
 
-             /// <summary> Mark a serializable field as an input port. You can access this through <see cref="GetInputPort(string)"/> </summary>
 
-             /// <param name="backingValue">Should we display the backing value for this port as an editor field? </param>
 
-             /// <param name="connectionType">Should we allow multiple connections? </param>
 
-             /// <param name="typeConstraint">Constrains which input connections can be made to this port </param>
 
-             /// <param name="dynamicPortList">If true, will display a reorderable list of inputs instead of a single port. Will automatically add and display values for lists and arrays </param>
 
-             public InputAttribute(ShowBackingValue backingValue = ShowBackingValue.Unconnected, ConnectionType connectionType = ConnectionType.Multiple,
 
-                 TypeConstraint typeConstraint = TypeConstraint.None, bool dynamicPortList = false)
 
-             {
 
-                 this.backingValue = backingValue;
 
-                 this.connectionType = connectionType;
 
-                 this.dynamicPortList = dynamicPortList;
 
-                 this.typeConstraint = typeConstraint;
 
-             }
 
-         }
 
-         /// <summary> Mark a serializable field as an output port. You can access this through <see cref="GetOutputPort(string)"/> </summary>
 
-         [AttributeUsage(AttributeTargets.Field)]
 
-         public class OutputAttribute : Attribute
 
-         {
 
-             public ShowBackingValue backingValue;
 
-             public ConnectionType connectionType;
 
-             [Obsolete("Use dynamicPortList instead")]
 
-             public bool instancePortList
 
-             {
 
-                 get { return dynamicPortList; }
 
-                 set { dynamicPortList = value; }
 
-             }
 
-             public bool dynamicPortList;
 
-             public TypeConstraint typeConstraint;
 
-             /// <summary> Mark a serializable field as an output port. You can access this through <see cref="GetOutputPort(string)"/> </summary>
 
-             /// <param name="backingValue">Should we display the backing value for this port as an editor field? </param>
 
-             /// <param name="connectionType">Should we allow multiple connections? </param>
 
-             /// <param name="typeConstraint">Constrains which input connections can be made from this port </param>
 
-             /// <param name="dynamicPortList">If true, will display a reorderable list of outputs instead of a single port. Will automatically add and display values for lists and arrays </param>
 
-             public OutputAttribute(ShowBackingValue backingValue = ShowBackingValue.Never, ConnectionType connectionType = ConnectionType.Multiple, TypeConstraint typeConstraint = TypeConstraint.None,
 
-                 bool dynamicPortList = false)
 
-             {
 
-                 this.backingValue = backingValue;
 
-                 this.connectionType = connectionType;
 
-                 this.dynamicPortList = dynamicPortList;
 
-                 this.typeConstraint = typeConstraint;
 
-             }
 
-             /// <summary> Mark a serializable field as an output port. You can access this through <see cref="GetOutputPort(string)"/> </summary>
 
-             /// <param name="backingValue">Should we display the backing value for this port as an editor field? </param>
 
-             /// <param name="connectionType">Should we allow multiple connections? </param>
 
-             /// <param name="dynamicPortList">If true, will display a reorderable list of outputs instead of a single port. Will automatically add and display values for lists and arrays </param>
 
-             [Obsolete("Use constructor with TypeConstraint")]
 
-             public OutputAttribute(ShowBackingValue backingValue, ConnectionType connectionType, bool dynamicPortList) : this(backingValue, connectionType, TypeConstraint.None, dynamicPortList)
 
-             {
 
-             }
 
-         }
 
-         /// <summary> Manually supply node class with a context menu path </summary>
 
-         [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true)]
 
-         public class CreateNodeMenuAttribute : Attribute
 
-         {
 
-             public string menuName;
 
-             public int order;
 
-             public bool isServerRecord;
 
-             public string tooltip = "帮助文本默认在[CreateNodeMenuAttribute]中配置,暂时由程序维护,有更好的意见可以及时反馈";
 
-             public string showName;
 
-             /// <summary> Manually supply node class with a context menu path </summary>
 
-             /// <param name="menuName"> Path to this node in the context menu. Null or empty hides it. </param>
 
-             public CreateNodeMenuAttribute(string menuName)
 
-             {
 
-                 this.menuName = menuName;
 
-                 this.order = 0;
 
-             }
 
-             /// <summary> Manually supply node class with a context menu path </summary>
 
-             /// <param name="menuName"> Path to this node in the context menu. Null or empty hides it. </param>
 
-             /// <param name="order"> The order by which the menu items are displayed. </param>
 
-             public CreateNodeMenuAttribute(string menuName, int order)
 
-             {
 
-                 this.menuName = menuName;
 
-                 this.order = order;
 
-             }
 
-             public CreateNodeMenuAttribute(string menuName, int order, bool isServerRecord, string tooltip, string showName)
 
-             {
 
-                 this.menuName = menuName;
 
-                 this.order = order;
 
-                 this.isServerRecord = isServerRecord;
 
-                 this.tooltip = tooltip;
 
-                 this.showName = showName;
 
-             }
 
-         }
 
-         [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true)]
 
-         public class CreateDialogueNodeMenuAttribute : Attribute
 
-         {
 
-             public string menuName;
 
-             public int order;
 
-             public bool isServerRecord;
 
-             public string tooltip;
 
-             public string showName;
 
-             /// <summary> Manually supply node class with a context menu path </summary>
 
-             /// <param name="menuName"> Path to this node in the context menu. Null or empty hides it. </param>
 
-             public CreateDialogueNodeMenuAttribute(string menuName)
 
-             {
 
-                 this.menuName = menuName;
 
-                 this.order = 0;
 
-             }
 
-             /// <summary> Manually supply node class with a context menu path </summary>
 
-             /// <param name="menuName"> Path to this node in the context menu. Null or empty hides it. </param>
 
-             /// <param name="order"> The order by which the menu items are displayed. </param>
 
-             public CreateDialogueNodeMenuAttribute(string menuName, int order)
 
-             {
 
-                 this.menuName = menuName;
 
-                 this.order = order;
 
-             }
 
-             public CreateDialogueNodeMenuAttribute(string menuName, int order, bool isServerRecord, string tooltip, string showName)
 
-             {
 
-                 this.menuName = menuName;
 
-                 this.order = order;
 
-                 this.isServerRecord = isServerRecord;
 
-                 this.tooltip = tooltip;
 
-                 this.showName = showName;
 
-             }
 
-         }
 
-         /// <summary> Prevents Node of the same type to be added more than once (configurable) to a NodeGraph </summary>
 
-         [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
 
-         public class DisallowMultipleNodesAttribute : Attribute
 
-         {
 
-             // TODO: Make inheritance work in such a way that applying [DisallowMultipleNodes(1)] to type NodeBar : Node
 
-             //       while type NodeFoo : NodeBar exists, will let you add *either one* of these nodes, but not both.
 
-             public int max;
 
-             /// <summary> Prevents Node of the same type to be added more than once (configurable) to a NodeGraph </summary>
 
-             /// <param name="max"> How many nodes to allow. Defaults to 1. </param>
 
-             public DisallowMultipleNodesAttribute(int max = 1)
 
-             {
 
-                 this.max = max;
 
-             }
 
-         }
 
-         /// <summary> Specify a color for this node type </summary>
 
-         [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
 
-         public class NodeTintAttribute : Attribute
 
-         {
 
-             public Color color;
 
-             /// <summary> Specify a color for this node type </summary>
 
-             /// <param name="r"> Red [0.0f .. 1.0f] </param>
 
-             /// <param name="g"> Green [0.0f .. 1.0f] </param>
 
-             /// <param name="b"> Blue [0.0f .. 1.0f] </param>
 
-             public NodeTintAttribute(float r, float g, float b)
 
-             {
 
-                 color = new Color(r, g, b);
 
-             }
 
-             /// <summary> Specify a color for this node type </summary>
 
-             /// <param name="hex"> HEX color value </param>
 
-             public NodeTintAttribute(string hex)
 
-             {
 
-                 ColorUtility.TryParseHtmlString(hex, out color);
 
-             }
 
-             /// <summary> Specify a color for this node type </summary>
 
-             /// <param name="r"> Red [0 .. 255] </param>
 
-             /// <param name="g"> Green [0 .. 255] </param>
 
-             /// <param name="b"> Blue [0 .. 255] </param>
 
-             public NodeTintAttribute(byte r, byte g, byte b)
 
-             {
 
-                 color = new Color32(r, g, b, byte.MaxValue);
 
-             }
 
-         }
 
-         /// <summary> Specify a width for this node type </summary>
 
-         [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
 
-         public class NodeWidthAttribute : Attribute
 
-         {
 
-             public int width;
 
-             /// <summary> Specify a width for this node type </summary>
 
-             /// <param name="width"> Width </param>
 
-             public NodeWidthAttribute(int width)
 
-             {
 
-                 this.width = width;
 
-             }
 
-         }
 
-         #endregion
 
-         [Serializable]
 
-         private class NodePortDictionary : Dictionary<string, NodePort>, ISerializationCallbackReceiver
 
-         {
 
-             [SerializeField] private List<string> keys = new List<string>();
 
-             [SerializeField] private List<NodePort> values = new List<NodePort>();
 
-             public void OnBeforeSerialize()
 
-             {
 
-                 keys.Clear();
 
-                 values.Clear();
 
-                 foreach (KeyValuePair<string, NodePort> pair in this)
 
-                 {
 
-                     keys.Add(pair.Key);
 
-                     values.Add(pair.Value);
 
-                 }
 
-             }
 
-             public void OnAfterDeserialize()
 
-             {
 
-                 this.Clear();
 
-                 if (keys.Count != values.Count)
 
-                     throw new Exception("there are " + keys.Count + " keys and " + values.Count + " values after deserialization. Make sure that both key and value types are serializable.");
 
-                 for (int i = 0; i < keys.Count; i++)
 
-                     this.Add(keys[i], values[i]);
 
-             }
 
-         }
 
-     }
 
- }
 
 
  |