diff --git a/Examples/NodeToy/NodeGraphExample.asset b/Examples/NodeToy/NodeGraphExample.asset index c44ea50..7fa3bac 100644 Binary files a/Examples/NodeToy/NodeGraphExample.asset and b/Examples/NodeToy/NodeGraphExample.asset differ diff --git a/Scripts/Node.cs b/Scripts/Node.cs index d563231..1963d3b 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -26,6 +26,40 @@ public abstract class Node : ScriptableObject { Init(); } + + /// Checks all connections for invalid references, and removes them. + public void VerifyConnections() { + for (int i = 0; i < InputCount; i++) { + inputs[i].VerifyConnections(); + } + for (int i = 0; i < OutputCount; i++) { + outputs[i].VerifyConnections(); + } + } + + /// Returns input or output port which matches fieldName + public NodePort GetPortByFieldName(string fieldName) { + NodePort port = GetOutputByFieldName(fieldName); + if (port != null) return port; + else return GetInputByFieldName(fieldName); + } + + /// Returns output port which matches fieldName + public NodePort GetOutputByFieldName(string fieldName) { + for (int i = 0; i < OutputCount; i++) { + if (outputs[i].fieldName == fieldName) return outputs[i]; + } + return null; + } + + /// Returns input port which matches fieldName + public NodePort GetInputByFieldName(string fieldName) { + for (int i = 0; i < InputCount; i++) { + if (inputs[i].fieldName == fieldName) return inputs[i]; + } + return null; + } + /// Initialize node. Called on creation. protected virtual void Init() { name = GetType().Name; } @@ -48,13 +82,6 @@ public abstract class Node : ScriptableObject { return -1; } - public NodePort CreateNodeInput(string name, Type type) { - return new NodePort(name, type, this, NodePort.IO.Input); - } - public NodePort CreateNodeOutput(string name, Type type) { - return new NodePort(name, type, this, NodePort.IO.Output); - } - public void ClearConnections() { for (int i = 0; i < inputs.Count; i++) { inputs[i].ClearConnections(); @@ -96,8 +123,8 @@ public abstract class Node : ScriptableObject { else if (attribs[k] is OutputAttribute) outputAttrib = attribs[k] as OutputAttribute; } if (inputAttrib != null && outputAttrib != null) Debug.LogError("Field " + fieldInfo + " cannot be both input and output."); - else if (inputAttrib != null) inputPorts.Add(new NodePort(fieldInfo[i].Name, fieldInfo[i].FieldType, this, NodePort.IO.Input)); - else if (outputAttrib != null) outputPorts.Add(new NodePort(fieldInfo[i].Name, fieldInfo[i].FieldType, this, NodePort.IO.Output)); + else if (inputAttrib != null) inputPorts.Add(new NodePort(fieldInfo[i], this)); + else if (outputAttrib != null) outputPorts.Add(new NodePort(fieldInfo[i], this)); } inputs = inputPorts; diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs index d61ec99..9e3c7d8 100644 --- a/Scripts/NodeGraph.cs +++ b/Scripts/NodeGraph.cs @@ -44,6 +44,14 @@ public abstract class NodeGraph : ScriptableObject, ISerializationCallbackReceiv for (int i = 0; i < nodes.Count; i++) { nodes[i].graph = this; } + VerifyConnections(); + } + + /// Checks all connections for invalid references, and removes them. + public void VerifyConnections() { + for (int i = 0; i < nodes.Count; i++) { + nodes[i].VerifyConnections(); + } } } diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs index c0df2bb..937c0d1 100644 --- a/Scripts/NodePort.cs +++ b/Scripts/NodePort.cs @@ -2,10 +2,11 @@ using System.Collections.Generic; using UnityEngine; using System; +using System.Reflection; [Serializable] public class NodePort { - public enum IO { Input, Output} + public enum IO { Input, Output } public int ConnectionCount { get { return connections.Count; } } /// Return the first connection @@ -18,24 +19,40 @@ public class NodePort { public bool IsOutput { get { return direction == IO.Output; } } public Node node { get; private set; } - public string name { get { return _name; } } + [SerializeField] public string name; public bool enabled { get { return _enabled; } set { _enabled = value; } } - public string id { get { return _id; } } + public string fieldName { get { return _fieldName; } } + [SerializeField] private List connections = new List(); - [SerializeField] private string asdf; - [SerializeField] private string _id; + [SerializeField] private string _fieldName; [SerializeField] public Type type; - [SerializeField] private string _name; [SerializeField] private bool _enabled = true; [SerializeField] private IO _direction; - public NodePort(string name, Type type, Node node, IO direction) { - _name = name; - this.type = type; + public NodePort(FieldInfo fieldInfo, Node node) { + _fieldName = fieldInfo.Name; + name = _fieldName; + type = fieldInfo.FieldType; this.node = node; - _direction = direction; - _id = node.GetInstanceID() + _name; + + var attribs = fieldInfo.GetCustomAttributes(false); + for (int i = 0; i < attribs.Length; i++) { + if (attribs[i] is Node.InputAttribute) _direction = IO.Input; + else if (attribs[i] is Node.InputAttribute) _direction = IO.Output; + } + } + + /// Checks all connections for invalid references, and removes them. + public void VerifyConnections() { + for (int i = 0; i < connections.Count; i++) { + if (connections[i].node != null && + !string.IsNullOrEmpty(connections[i].fieldName) && + connections[i].node.GetPortByFieldName(connections[i].fieldName) != null) + continue; + Debug.LogWarning("Removed invalid connection"); + connections.RemoveAt(i); + } } /// Connect this to another @@ -86,22 +103,22 @@ public class NodePort { [Serializable] public class PortConnection { [SerializeField] public Node node; - [SerializeField] public string portID; + [SerializeField] public string fieldName; public NodePort Port { get { return port != null ? port : port = GetPort(); } } [NonSerialized] private NodePort port; public PortConnection(NodePort port) { this.port = port; node = port.node; - portID = port.id; + fieldName = port.fieldName; } private NodePort GetPort() { for (int i = 0; i < node.OutputCount; i++) { - if (node.outputs[i].id == portID) return node.outputs[i]; + if (node.outputs[i].fieldName == fieldName) return node.outputs[i]; } for (int i = 0; i < node.InputCount; i++) { - if (node.inputs[i].id == portID) return node.inputs[i]; + if (node.inputs[i].fieldName == fieldName) return node.inputs[i]; } return null; }