mirror of
https://github.com/Siccity/xNode.git
synced 2025-12-20 01:06:01 +08:00
Initial NodeGraphEditor implementation
This commit is contained in:
parent
dcff69979c
commit
4ea25f6aee
@ -7,7 +7,9 @@ using XNode;
|
||||
|
||||
namespace XNodeEditor {
|
||||
/// <summary> Base class to derive custom Node editors from. Use this to create your own custom inspectors and editors for your nodes. </summary>
|
||||
public class NodeEditor {
|
||||
[CustomNodeEditor(typeof(Node))]
|
||||
public class NodeEditor : XNodeInternal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute> {
|
||||
|
||||
/// <summary> Fires every whenever a node was modified through the editor </summary>
|
||||
public static Action<Node> onUpdateNode;
|
||||
public Node target;
|
||||
@ -45,17 +47,21 @@ namespace XNodeEditor {
|
||||
public virtual int GetWidth() {
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class CustomNodeEditorAttribute : Attribute {
|
||||
public Type inspectedType { get { return _inspectedType; } }
|
||||
private Type _inspectedType;
|
||||
/// <summary> Tells a NodeEditor which Node type it is an editor for </summary>
|
||||
/// <param name="inspectedType">Type that this editor can edit</param>
|
||||
/// <param name="contextMenuName">Path to the node</param>
|
||||
public CustomNodeEditorAttribute(Type inspectedType) {
|
||||
_inspectedType = inspectedType;
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class CustomNodeEditorAttribute : Attribute,
|
||||
INodeEditorAttrib {
|
||||
private Type inspectedType;
|
||||
/// <summary> Tells a NodeEditor which Node type it is an editor for </summary>
|
||||
/// <param name="inspectedType">Type that this editor can edit</param>
|
||||
/// <param name="contextMenuName">Path to the node</param>
|
||||
public CustomNodeEditorAttribute(Type inspectedType) {
|
||||
this.inspectedType = inspectedType;
|
||||
}
|
||||
|
||||
public Type GetInspectedType() {
|
||||
return inspectedType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Scripts/Editor/NodeEditorBase.cs
Normal file
41
Scripts/Editor/NodeEditorBase.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using XNode;
|
||||
using XNodeEditor;
|
||||
|
||||
namespace XNodeInternal {
|
||||
/// <summary> Handles caching of custom editor classes and their target types. Accessible with GetEditor(Type type) </summary>
|
||||
public class NodeEditorBase<T, A> where A : Attribute, NodeEditorBase<T, A>.INodeEditorAttrib where T : class {
|
||||
/// <summary> Custom editors defined with [CustomNodeEditor] </summary>
|
||||
private static Dictionary<Type, T> editors;
|
||||
|
||||
public static T GetEditor(Type type) {
|
||||
if (type == null) return null;
|
||||
if (editors == null) CacheCustomEditors();
|
||||
if (editors.ContainsKey(type)) return editors[type];
|
||||
//If type isn't found, try base type
|
||||
return GetEditor(type.BaseType);
|
||||
}
|
||||
|
||||
private static void CacheCustomEditors() {
|
||||
editors = new Dictionary<Type, T>();
|
||||
|
||||
//Get all classes deriving from NodeEditor via reflection
|
||||
Type[] nodeEditors = NodeEditorWindow.GetDerivedTypes(typeof(T));
|
||||
for (int i = 0; i < nodeEditors.Length; i++) {
|
||||
var attribs = nodeEditors[i].GetCustomAttributes(typeof(A), false);
|
||||
if (attribs == null || attribs.Length == 0) continue;
|
||||
if (nodeEditors[i].IsAbstract) continue;
|
||||
A attrib = attribs[0] as A;
|
||||
editors.Add(attrib.GetInspectedType(), Activator.CreateInstance(nodeEditors[i]) as T);
|
||||
}
|
||||
}
|
||||
|
||||
public interface INodeEditorAttrib {
|
||||
Type GetInspectedType();
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Scripts/Editor/NodeEditorBase.cs.meta
Normal file
13
Scripts/Editor/NodeEditorBase.cs.meta
Normal file
@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e85122ded59aceb4eb4b1bd9d9202642
|
||||
timeCreated: 1511353946
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -193,7 +193,7 @@ namespace XNodeEditor {
|
||||
Node node = graph.nodes[n];
|
||||
Type nodeType = node.GetType();
|
||||
|
||||
NodeEditor nodeEditor = GetNodeEditor(nodeType);
|
||||
NodeEditor nodeEditor = NodeEditor.GetEditor(nodeType);
|
||||
nodeEditor.target = node;
|
||||
nodeEditor.serializedObject = new SerializedObject(node);
|
||||
NodeEditor.portPositions = new Dictionary<NodePort, Vector2>();
|
||||
|
||||
@ -10,40 +10,18 @@ using XNode;
|
||||
namespace XNodeEditor {
|
||||
/// <summary> Contains reflection-related info </summary>
|
||||
public partial class NodeEditorWindow {
|
||||
/// <summary> Custom node editors defined with [CustomNodeInspector] </summary>
|
||||
[NonSerialized] private static Dictionary<Type, NodeEditor> customNodeEditor;
|
||||
/// <summary> Custom node tint colors defined with [NodeColor(r, g, b)] </summary>
|
||||
public static Dictionary<Type, Color> nodeTint { get { return _nodeTint != null ? _nodeTint : _nodeTint = GetNodeTint(); } }
|
||||
[NonSerialized] private static Dictionary<Type, Color> _nodeTint;
|
||||
[NonSerialized] private static Dictionary<Type, Color> _nodeTint;
|
||||
/// <summary> All available node types </summary>
|
||||
public static Type[] nodeTypes { get { return _nodeTypes != null ? _nodeTypes : _nodeTypes = GetNodeTypes(); } }
|
||||
[NonSerialized] private static Type[] _nodeTypes = null;
|
||||
|
||||
public static NodeEditor GetNodeEditor(Type node) {
|
||||
if (customNodeEditor == null) CacheCustomNodeEditors();
|
||||
if (customNodeEditor.ContainsKey(node)) return customNodeEditor[node];
|
||||
return customNodeEditor[typeof(Node)];
|
||||
}
|
||||
[NonSerialized] private static Type[] _nodeTypes = null;
|
||||
|
||||
public static Type[] GetNodeTypes() {
|
||||
//Get all classes deriving from Node via reflection
|
||||
return GetDerivedTypes(typeof(Node));
|
||||
}
|
||||
|
||||
public static void CacheCustomNodeEditors() {
|
||||
customNodeEditor = new Dictionary<Type, NodeEditor>();
|
||||
customNodeEditor.Add(typeof(Node), new NodeEditor());
|
||||
//Get all classes deriving from NodeEditor via reflection
|
||||
Type[] nodeEditors = GetDerivedTypes(typeof(NodeEditor));
|
||||
for (int i = 0; i < nodeEditors.Length; i++) {
|
||||
var attribs = nodeEditors[i].GetCustomAttributes(typeof(CustomNodeEditorAttribute), false);
|
||||
if (attribs == null || attribs.Length == 0) continue;
|
||||
if (nodeEditors[i].IsAbstract) continue;
|
||||
CustomNodeEditorAttribute attrib = attribs[0] as CustomNodeEditorAttribute;
|
||||
customNodeEditor.Add(attrib.inspectedType, Activator.CreateInstance(nodeEditors[i]) as NodeEditor);
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<Type, Color> GetNodeTint() {
|
||||
Dictionary<Type, Color> tints = new Dictionary<Type, Color>();
|
||||
for (int i = 0; i < nodeTypes.Length; i++) {
|
||||
@ -121,7 +99,6 @@ namespace XNodeEditor {
|
||||
FieldInfo sectionsField = type.GetField("m_Sections", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
IList sections = sectionsField.GetValue(window) as IList;
|
||||
|
||||
|
||||
//Iterate through sections and check contents
|
||||
Type sectionType = sectionsField.FieldType.GetGenericArguments() [0];
|
||||
FieldInfo sectionContentField = sectionType.GetField("content", BindingFlags.Instance | BindingFlags.Public);
|
||||
|
||||
38
Scripts/Editor/NodeGraphEditor.cs
Normal file
38
Scripts/Editor/NodeGraphEditor.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using XNode;
|
||||
|
||||
namespace XNodeEditor {
|
||||
/// <summary> Base class to derive custom Node Graph editors from. Use this to override how graphs are drawn in the editor. </summary>
|
||||
[CustomNodeGraphEditor(typeof(NodeGraph))]
|
||||
public class NodeGraphEditor : XNodeInternal.NodeEditorBase<NodeGraphEditor, NodeGraphEditor.CustomNodeGraphEditorAttribute> {
|
||||
/// <summary> Custom node editors defined with [CustomNodeGraphEditor] </summary>
|
||||
[NonSerialized] private static Dictionary<Type, NodeGraphEditor> editors;
|
||||
|
||||
public NodeGraph target;
|
||||
public SerializedObject serializedObject;
|
||||
|
||||
public virtual Texture2D GetGridTexture() {
|
||||
return NodeEditorPreferences.gridTexture;
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class CustomNodeGraphEditorAttribute : Attribute,
|
||||
INodeEditorAttrib {
|
||||
private Type inspectedType;
|
||||
/// <summary> Tells a NodeEditor which Node type it is an editor for </summary>
|
||||
/// <param name="inspectedType">Type that this editor can edit</param>
|
||||
/// <param name="contextMenuName">Path to the node</param>
|
||||
public CustomNodeGraphEditorAttribute(Type inspectedType) {
|
||||
this.inspectedType = inspectedType;
|
||||
}
|
||||
|
||||
public Type GetInspectedType() {
|
||||
return inspectedType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Scripts/Editor/NodeGraphEditor.cs.meta
Normal file
12
Scripts/Editor/NodeGraphEditor.cs.meta
Normal file
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ddcbb5432255d3247a0718b15a9c193c
|
||||
timeCreated: 1505462176
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
x
Reference in New Issue
Block a user