using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEditor; using UnityEngine; /// Base class to derive custom Node editors from. Use this to create your own custom inspectors and editors for your nodes. public class NodeEditor { /// Fires every whenever a node was modified through the editor public static Action onUpdateNode; public Node target; /// Draws the node GUI. /// Port handle positions need to be returned to the NodeEditorWindow public void OnNodeGUI(out Dictionary portPositions) { OnHeaderGUI(); OnBodyGUI(out portPositions); } protected virtual void OnHeaderGUI() { GUI.color = Color.white; string title = NodeEditorUtilities.PrettifyCamelCase(target.name); GUILayout.Label(title, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30)); } /// Draws standard field editors for all public fields protected virtual void OnBodyGUI(out Dictionary portPositions) { portPositions = new Dictionary(); EditorGUI.BeginChangeCheck(); FieldInfo[] fields = GetInspectorFields(target); for (int i = 0; i < fields.Length; i++) { switch (fields[i].Name) { case "graph": case "position": case "inputs": case "outputs": continue; } NodeEditorGUILayout.PropertyField(target, fields[i], portPositions); } //If user changed a value, notify other scripts through onUpdateNode if (EditorGUI.EndChangeCheck()) { if (onUpdateNode != null) onUpdateNode(target); } } private static FieldInfo[] GetInspectorFields(Node node) { return node.GetType().GetFields().Where(f => f.IsPublic || f.GetCustomAttributes(typeof(SerializeField), false) != null).ToArray(); } public virtual int GetWidth() { return 200; } } [AttributeUsage(AttributeTargets.Class)] public class CustomNodeEditorAttribute : Attribute { public Type inspectedType { get { return _inspectedType; } } private Type _inspectedType; public string contextMenuName { get { return _contextMenuName; } } private string _contextMenuName; /// Tells a NodeEditor which Node type it is an editor for /// Type that this editor can edit /// Path to the node public CustomNodeEditorAttribute(Type inspectedType, string contextMenuName) { _inspectedType = inspectedType; _contextMenuName = contextMenuName; } }