diff --git a/Examples/Nodes/BaseNode.cs b/Examples/Nodes/BaseNode.cs index bd34ef1..d7ceb3e 100644 --- a/Examples/Nodes/BaseNode.cs +++ b/Examples/Nodes/BaseNode.cs @@ -3,6 +3,8 @@ [System.Serializable] public class BaseNode : Node { + [Input] public string input; + [Output] public string output; public bool concat; [TextArea] public string SomeString; @@ -10,11 +12,4 @@ public class BaseNode : Node { public Color col; public AnimationCurve anim; public Vector3 vec; - protected override void Init() { - inputs = new NodePort[2]; - inputs[0] = CreateNodeInput("IntInput", typeof(int)); - inputs[1] = CreateNodeInput("StringInput", typeof(string)); - outputs = new NodePort[1]; - outputs[0] = CreateNodeOutput("StringOutput", typeof(string)); - } } diff --git a/Examples/Nodes/MathNode.cs b/Examples/Nodes/MathNode.cs index 8529cbc..6b98c73 100644 --- a/Examples/Nodes/MathNode.cs +++ b/Examples/Nodes/MathNode.cs @@ -2,25 +2,11 @@ [System.Serializable] public class MathNode : Node { - + [Input] public float a; + [Input] public float b; + [Output] public float result; public enum ValueType { Float, Int } public enum MathType { Add, Subtract, Multiply, Divide} public ValueType valueType = ValueType.Float; public MathType mathType = MathType.Add; - - protected override void Init() { - inputs = new NodePort[2]; - inputs[0] = CreateNodeInput("A", typeof(float)); - inputs[1] = CreateNodeInput("B", typeof(float)); - outputs = new NodePort[1]; - outputs[0] = CreateNodeOutput("Result", typeof(float)); - } - - public void OnValidate() { - System.Type type = typeof(int); - if (valueType == ValueType.Float) type = typeof(float); - inputs[0].type = type; - inputs[1].type = type; - outputs[0].type = type; - } } diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs index c9bf764..84e1c08 100644 --- a/Scripts/Editor/NodeEditor.cs +++ b/Scripts/Editor/NodeEditor.cs @@ -14,11 +14,11 @@ public class NodeEditor { public virtual void OnNodeGUI() { portRects.Clear(); DrawNodePortsGUI(); - DrawDefaultNodeGUI(); + DrawDefaultNodeBody(); } /// Draws standard field editors for all public fields - protected void DrawDefaultNodeGUI() { + protected void DrawDefaultNodeBody() { FieldInfo[] fields = GetInspectorFields(target); for (int i = 0; i < fields.Length; i++) { Type fieldType = fields[i].FieldType; @@ -31,6 +31,9 @@ public class NodeEditor { EditorGUILayout.LabelField(headerAttrib.header); } + //Skip if field has input or output attribute + if (NodeEditorUtilities.HasAttrib(fieldAttribs) || NodeEditorUtilities.HasAttrib(fieldAttribs)) continue; + EditorGUI.BeginChangeCheck(); if (fieldType == typeof(int)) { fieldValue = EditorGUILayout.IntField(fieldName, (int)fieldValue); diff --git a/Scripts/Editor/NodeEditorUtilities.cs b/Scripts/Editor/NodeEditorUtilities.cs index 81c3e1c..4b26bc3 100644 --- a/Scripts/Editor/NodeEditorUtilities.cs +++ b/Scripts/Editor/NodeEditorUtilities.cs @@ -23,6 +23,15 @@ public static class NodeEditorUtilities { return false; } + public static bool HasAttrib(object[] attribs) where T : Attribute { + for (int i = 0; i < attribs.Length; i++) { + if (attribs[i].GetType() == typeof(T)) { + return true; + } + } + return false; + } + /// Return color based on type public static Color GetTypeColor(Type type) { UnityEngine.Random.InitState(type.Name.GetHashCode()); diff --git a/Scripts/Node.cs b/Scripts/Node.cs index e2bb06a..a9191b3 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -14,18 +14,21 @@ public abstract class Node { [SerializeField] private string nodeType; [SerializeField] public Rect position = new Rect(0,0,200,200); - [SerializeField] protected NodePort[] inputs = new NodePort[0]; - [SerializeField] protected NodePort[] outputs = new NodePort[0]; + [SerializeField] private NodePort[] inputs = new NodePort[0]; + [SerializeField] private NodePort[] outputs = new NodePort[0]; public int InputCount { get { return inputs.Length; } } public int OutputCount { get { return outputs.Length; } } protected Node() { nodeType = GetType().ToString(); + CachePorts(); Init(); } - protected abstract void Init(); + protected virtual void Init() { + + } public int GetInputId(NodePort input) { for (int i = 0; i < inputs.Length; i++) { @@ -75,4 +78,40 @@ public abstract class Node { public override int GetHashCode() { return JsonUtility.ToJson(this).GetHashCode(); } + + [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] + public class InputAttribute : Attribute { + public InputAttribute() { + } + } + + [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] + public class OutputAttribute : Attribute { + public OutputAttribute() { + } + } + + /// Use reflection to find all fields with or , and write to and + private void CachePorts() { + List inputPorts = new List(); + List outputPorts = new List(); + + System.Reflection.FieldInfo[] fieldInfo = GetType().GetFields(); + for (int i = 0; i < fieldInfo.Length; i++) { + //Get InputAttribute and OutputAttribute + object[] attribs = fieldInfo[i].GetCustomAttributes(false); + InputAttribute inputAttrib = null; + OutputAttribute outputAttrib = null; + for (int k = 0; k < attribs.Length; k++) { + if (attribs[k] is InputAttribute) inputAttrib = attribs[k] as InputAttribute; + 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)); + } + + inputs = inputPorts.ToArray(); + outputs = outputPorts.ToArray(); + } }