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 {
public Node target;
/// Draws the node GUI.
/// Port handle positions need to be returned to the NodeEditorWindow
public virtual void OnNodeGUI(out Dictionary portPositions) {
DrawDefaultHeaderGUI();
DrawDefaultNodeBodyGUI(out portPositions);
}
protected void DrawDefaultHeaderGUI() {
GUI.color = Color.white;
GUILayout.Label(target.name, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
}
/// Draws standard field editors for all public fields
protected void DrawDefaultNodeBodyGUI(out Dictionary portPositions) {
portPositions = new Dictionary();
FieldInfo[] fields = GetInspectorFields(target);
for (int i = 0; i < fields.Length; i++) {
object[] fieldAttribs = fields[i].GetCustomAttributes(false);
if (fields[i].Name == "graph" || fields[i].Name == "rect") continue;
NodeEditorGUILayout.PropertyField(target, fields[i], portPositions);
}
}
/// Draw node port GUI using automatic layouting. Returns port handle position.
protected Vector2 DrawNodePortGUI(NodePort port) {
GUIStyle style = port.direction == NodePort.IO.Input ? NodeEditorResources.styles.inputPort : NodeEditorResources.styles.outputPort;
Rect rect = GUILayoutUtility.GetRect(new GUIContent(port.fieldName.PrettifyCamelCase()), style);
return DrawNodePortGUI(rect, port);
}
/// Draw node port GUI in rect. Returns port handle position.
protected Vector2 DrawNodePortGUI(Rect rect, NodePort port) {
GUIStyle style = port.direction == NodePort.IO.Input ? NodeEditorResources.styles.inputPort : NodeEditorResources.styles.outputPort;
GUI.Label(rect, new GUIContent(port.fieldName.PrettifyCamelCase()), style);
Vector2 handlePoint = rect.center;
switch (port.direction) {
case NodePort.IO.Input:
handlePoint.x = rect.xMin;
break;
case NodePort.IO.Output:
handlePoint.x = rect.xMax;
break;
}
Color col = GUI.color;
Rect handleRect = new Rect(handlePoint.x - 8, handlePoint.y - 8, 16, 16);
GUI.color = new Color32(90, 97, 105, 255);
GUI.DrawTexture(handleRect, NodeEditorResources.dotOuter);
GUI.color = NodeEditorPreferences.GetTypeColor(port.type);
GUI.DrawTexture(handleRect, NodeEditorResources.dot);
GUI.color = col;
return handlePoint;
}
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;
}
}