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();
+ }
}