1
0
mirror of https://github.com/Siccity/xNode.git synced 2025-12-20 09:16:01 +08:00

Started work on NodeGraphExample

This commit is contained in:
Thor Brigsted 2017-09-27 23:41:01 +02:00
parent 63808eb6a2
commit f8a0bb8f7c
11 changed files with 129 additions and 99 deletions

9
Examples/NodeToy.meta Normal file
View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 52f863b8b4fc21f47b2af1dd63a719ff
folderAsset: yes
timeCreated: 1506460802
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary> Defines an example nodegraph. </summary>
[CreateAssetMenu(fileName = "NodeGraphExample", menuName = "Node Graph/Example")]
public class NodeGraphExample : NodeGraph {
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a6399826e2c44b447b32a3ed06646162
timeCreated: 1506460823
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 84fbc8acdc9656941b529a16e8bbe318
timeCreated: 1506462197
licenseType: Free
NativeFormatImporter:
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,4 +1,6 @@
[System.Serializable] using UnityEngine;
[System.Serializable]
public class MathNode : Node { public class MathNode : Node {
[Input] public float a; [Input] public float a;
[Input] public float b; [Input] public float b;
@ -9,4 +11,8 @@ public class MathNode : Node {
protected override void Init() { protected override void Init() {
name = "Math"; name = "Math";
} }
public override void OnCreateConnection(NodePort from, NodePort to) {
}
} }

View File

@ -14,7 +14,7 @@ public class NodeEditor {
public virtual void OnNodeGUI() { public virtual void OnNodeGUI() {
portRects.Clear(); portRects.Clear();
DrawDefaultNodePortsGUI(); DrawDefaultNodePortsGUI();
DrawDefaultNodeBody(); DrawDefaultNodeBodyGUI();
} }
/// <summary> Draws standard editors for all fields marked with <see cref="Node.InputAttribute"/> or <see cref="Node.OutputAttribute"/> </summary> /// <summary> Draws standard editors for all fields marked with <see cref="Node.InputAttribute"/> or <see cref="Node.OutputAttribute"/> </summary>
@ -42,75 +42,12 @@ public class NodeEditor {
} }
/// <summary> Draws standard field editors for all public fields </summary> /// <summary> Draws standard field editors for all public fields </summary>
protected void DrawDefaultNodeBody() { protected void DrawDefaultNodeBodyGUI() {
FieldInfo[] fields = GetInspectorFields(target); FieldInfo[] fields = GetInspectorFields(target);
for (int i = 0; i < fields.Length; i++) { for (int i = 0; i < fields.Length; i++) {
Type fieldType = fields[i].FieldType;
string fieldName = fields[i].Name;
string fieldPrettyName = fieldName.PrettifyCamelCase();
object fieldValue = fields[i].GetValue(target);
object[] fieldAttribs = fields[i].GetCustomAttributes(false); object[] fieldAttribs = fields[i].GetCustomAttributes(false);
HeaderAttribute headerAttrib;
if (NodeEditorUtilities.GetAttrib(fieldAttribs, out headerAttrib)) {
EditorGUILayout.LabelField(headerAttrib.header);
}
//Skip if field has input or output attribute
if (NodeEditorUtilities.HasAttrib<Node.InputAttribute>(fieldAttribs) || NodeEditorUtilities.HasAttrib<Node.OutputAttribute>(fieldAttribs)) continue; if (NodeEditorUtilities.HasAttrib<Node.InputAttribute>(fieldAttribs) || NodeEditorUtilities.HasAttrib<Node.OutputAttribute>(fieldAttribs)) continue;
DrawFieldInfoDrawerGUI(fields[i]);
EditorGUI.BeginChangeCheck();
if (fieldType == typeof(int)) {
fieldValue = EditorGUILayout.IntField(fieldPrettyName, (int)fieldValue);
}
else if (fieldType == typeof(bool)) {
fieldValue = EditorGUILayout.Toggle(fieldPrettyName, (bool)fieldValue);
}
else if (fieldType.IsEnum) {
fieldValue = EditorGUILayout.EnumPopup(fieldPrettyName, (Enum)fieldValue);
}
else if (fieldType == typeof(string)) {
if (fieldName == "name") continue; //Ignore 'name'
TextAreaAttribute textAreaAttrib;
if (NodeEditorUtilities.GetAttrib(fieldAttribs, out textAreaAttrib)) {
fieldValue = EditorGUILayout.TextArea(fieldValue != null ? (string)fieldValue : "");
}
else
fieldValue = EditorGUILayout.TextField(fieldPrettyName, fieldValue != null ? (string)fieldValue : "");
}
else if (fieldType == typeof(Rect)) {
if (fieldName == "position") continue; //Ignore 'position'
fieldValue = EditorGUILayout.RectField(fieldPrettyName, (Rect)fieldValue);
}
else if (fieldType == typeof(float)) {
fieldValue = EditorGUILayout.FloatField(fieldPrettyName, (float)fieldValue);
}
else if (fieldType == typeof(Vector2)) {
fieldValue = EditorGUILayout.Vector2Field(fieldPrettyName, (Vector2)fieldValue);
}
else if (fieldType == typeof(Vector3)) {
fieldValue = EditorGUILayout.Vector3Field(new GUIContent(fieldPrettyName), (Vector3)fieldValue);
}
else if (fieldType == typeof(Vector4)) {
fieldValue = EditorGUILayout.Vector4Field(fieldPrettyName, (Vector4)fieldValue);
}
else if (fieldType == typeof(Color)) {
fieldValue = EditorGUILayout.ColorField(fieldPrettyName, (Color)fieldValue);
}
else if (fieldType == typeof(AnimationCurve)) {
AnimationCurve curve = fieldValue != null ? (AnimationCurve)fieldValue : new AnimationCurve();
curve = EditorGUILayout.CurveField(fieldPrettyName, curve);
if (fieldValue != curve) fields[i].SetValue(target, curve);
}
else if (fieldType.IsSubclassOf(typeof(UnityEngine.Object)) || fieldType == typeof(UnityEngine.Object)) {
if (fieldName == "graph") continue; //Ignore 'graph'
fieldValue = EditorGUILayout.ObjectField(fieldPrettyName, (UnityEngine.Object)fieldValue, fieldType, true);
}
if (EditorGUI.EndChangeCheck()) {
fields[i].SetValue(target, fieldValue);
}
} }
EditorGUILayout.Space(); EditorGUILayout.Space();
} }
@ -145,6 +82,72 @@ public class NodeEditor {
private static FieldInfo[] GetInspectorFields(Node node) { private static FieldInfo[] GetInspectorFields(Node node) {
return node.GetType().GetFields().Where(f => f.IsPublic || f.GetCustomAttributes(typeof(SerializeField),false) != null).ToArray(); return node.GetType().GetFields().Where(f => f.IsPublic || f.GetCustomAttributes(typeof(SerializeField),false) != null).ToArray();
} }
private void DrawFieldInfoDrawerGUI(FieldInfo fieldInfo) {
Type fieldType = fieldInfo.FieldType;
string fieldName = fieldInfo.Name;
string fieldPrettyName = fieldName.PrettifyCamelCase();
object fieldValue = fieldInfo.GetValue(target);
object[] fieldAttribs = fieldInfo.GetCustomAttributes(false);
HeaderAttribute headerAttrib;
if (NodeEditorUtilities.GetAttrib(fieldAttribs, out headerAttrib)) {
EditorGUILayout.LabelField(headerAttrib.header);
}
EditorGUI.BeginChangeCheck();
if (fieldType == typeof(int)) {
fieldValue = EditorGUILayout.IntField(fieldPrettyName, (int)fieldValue);
}
else if (fieldType == typeof(bool)) {
fieldValue = EditorGUILayout.Toggle(fieldPrettyName, (bool)fieldValue);
}
else if (fieldType.IsEnum) {
fieldValue = EditorGUILayout.EnumPopup(fieldPrettyName, (Enum)fieldValue);
}
else if (fieldType == typeof(string)) {
if (fieldName == "name") return; //Ignore 'name'
TextAreaAttribute textAreaAttrib;
if (NodeEditorUtilities.GetAttrib(fieldAttribs, out textAreaAttrib)) {
fieldValue = EditorGUILayout.TextArea(fieldValue != null ? (string)fieldValue : "");
}
else
fieldValue = EditorGUILayout.TextField(fieldPrettyName, fieldValue != null ? (string)fieldValue : "");
}
else if (fieldType == typeof(Rect)) {
if (fieldName == "position") return; //Ignore 'position'
fieldValue = EditorGUILayout.RectField(fieldPrettyName, (Rect)fieldValue);
}
else if (fieldType == typeof(float)) {
fieldValue = EditorGUILayout.FloatField(fieldPrettyName, (float)fieldValue);
}
else if (fieldType == typeof(Vector2)) {
fieldValue = EditorGUILayout.Vector2Field(fieldPrettyName, (Vector2)fieldValue);
}
else if (fieldType == typeof(Vector3)) {
fieldValue = EditorGUILayout.Vector3Field(new GUIContent(fieldPrettyName), (Vector3)fieldValue);
}
else if (fieldType == typeof(Vector4)) {
fieldValue = EditorGUILayout.Vector4Field(fieldPrettyName, (Vector4)fieldValue);
}
else if (fieldType == typeof(Color)) {
fieldValue = EditorGUILayout.ColorField(fieldPrettyName, (Color)fieldValue);
}
else if (fieldType == typeof(AnimationCurve)) {
AnimationCurve curve = fieldValue != null ? (AnimationCurve)fieldValue : new AnimationCurve();
curve = EditorGUILayout.CurveField(fieldPrettyName, curve);
if (fieldValue != curve) fieldInfo.SetValue(target, curve);
}
else if (fieldType.IsSubclassOf(typeof(UnityEngine.Object)) || fieldType == typeof(UnityEngine.Object)) {
if (fieldName == "graph") return; //Ignore 'graph'
fieldValue = EditorGUILayout.ObjectField(fieldPrettyName, (UnityEngine.Object)fieldValue, fieldType, true);
}
if (EditorGUI.EndChangeCheck()) {
fieldInfo.SetValue(target, fieldValue);
}
}
} }
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]

View File

@ -18,9 +18,9 @@ public partial class NodeEditorWindow : EditorWindow {
private float _zoom = 1; private float _zoom = 1;
partial void OnEnable(); partial void OnEnable();
/// <summary> Create editor window </summary>
[MenuItem("Window/UNEC")] //[MenuItem("Window/UNEC")]
static NodeEditorWindow Init() { public static NodeEditorWindow Init() {
NodeEditorWindow w = CreateInstance<NodeEditorWindow>(); NodeEditorWindow w = CreateInstance<NodeEditorWindow>();
w.titleContent = new GUIContent("UNEC"); w.titleContent = new GUIContent("UNEC");
w.wantsMouseMove = true; w.wantsMouseMove = true;

View File

@ -26,9 +26,11 @@ public abstract class Node {
} }
/// <summary> Initialize node. Called on creation. </summary> /// <summary> Initialize node. Called on creation. </summary>
protected virtual void Init() { protected virtual void Init() { }
} /// <summary> Called whenever a connection is being made between two <see cref="NodePort"/>s</summary>
/// <param name="from">Output</param> <param name="to">Input</param>
public virtual void OnCreateConnection(NodePort from, NodePort to) { }
public int GetInputId(NodePort input) { public int GetInputId(NodePort input) {
for (int i = 0; i < inputs.Length; i++) { for (int i = 0; i < inputs.Length; i++) {

View File

@ -13,26 +13,11 @@ public abstract class NodeGraph : ScriptableObject {
[SerializeField] public string[] s_nodes; [SerializeField] public string[] s_nodes;
public T AddNode<T>() where T : Node { public T AddNode<T>() where T : Node {
T node = default(T); return AddNode(typeof(T)) as T;
return AddNode(node) as T;
} }
public Node AddNode(Type type) { public virtual Node AddNode(Type type) {
Node node = (Node)Activator.CreateInstance(type); Node node = (Node)Activator.CreateInstance(type);
return AddNode(node);
}
public Node AddNode(string type) {
Debug.Log(type);
Node node = (Node)Activator.CreateInstance(null,type).Unwrap();
return AddNode(node);
}
public Node AddNode(Node node) {
if (node == null) {
Debug.LogError("Node could node be instanced");
return null;
}
nodes.Add(node); nodes.Add(node);
node.graph = this; node.graph = this;
return node; return node;
@ -45,12 +30,9 @@ public abstract class NodeGraph : ScriptableObject {
nodes.Remove(node); nodes.Remove(node);
} }
/// <summary> Remove all nodes and connections from the graph </summary>
public void Clear() { public void Clear() {
nodes.Clear(); nodes.Clear();
} }
private class NodeTyper {
public string nodeType = "Node";
}
} }

View File

@ -37,6 +37,8 @@ public class NodePort {
_direction = direction; _direction = direction;
} }
/// <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) { public void Connect(NodePort port) {
if (connections == null) connections = new List<NodePort>(); if (connections == null) connections = new List<NodePort>();
if (port == null) { Debug.LogWarning("Cannot connect to null port"); return; } if (port == null) { Debug.LogWarning("Cannot connect to null port"); return; }
@ -45,6 +47,8 @@ public class NodePort {
if (direction == port.direction) { Debug.LogWarning("Cannot connect two " + (direction == IO.Input ? "input" : "output") + " connections"); return; } if (direction == port.direction) { Debug.LogWarning("Cannot connect two " + (direction == IO.Input ? "input" : "output") + " connections"); return; }
connections.Add(port); connections.Add(port);
port.connections.Add(this); port.connections.Add(this);
node.OnCreateConnection(this, port);
port.node.OnCreateConnection(this, port);
} }
public NodePort GetConnection(int i) { public NodePort GetConnection(int i) {
@ -66,10 +70,4 @@ public class NodePort {
} }
connections.Clear(); connections.Clear();
} }
[Serializable]
private class PortID {
public int nodeID;
public int portID;
}
} }