mirror of
https://github.com/Siccity/xNode.git
synced 2025-12-20 09:16:01 +08:00
Put NodeEditorReflection into its own static class
This commit is contained in:
parent
93fa101af8
commit
891ecebc3f
@ -49,7 +49,7 @@ namespace XNodeEditor {
|
||||
public virtual int GetWidth() {
|
||||
Type type = target.GetType();
|
||||
int width;
|
||||
if (NodeEditorWindow.nodeWidth.TryGetValue(type, out width)) return width;
|
||||
if (type.TryGetAttributeWidth(out width)) return width;
|
||||
else return 208;
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ namespace XNodeEditor {
|
||||
// Try get color from [NodeTint] attribute
|
||||
Type type = target.GetType();
|
||||
Color color;
|
||||
if (NodeEditorWindow.nodeTint.TryGetValue(type, out color)) return color;
|
||||
if (type.TryGetAttributeTint(out color)) return color;
|
||||
// Return default color (grey)
|
||||
else return DEFAULTCOLOR;
|
||||
}
|
||||
@ -84,7 +84,7 @@ namespace XNodeEditor {
|
||||
// Custom sctions if only one node is selected
|
||||
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
|
||||
XNode.Node node = Selection.activeObject as XNode.Node;
|
||||
NodeEditorWindow.AddCustomContextMenuItems(menu, node);
|
||||
menu.AddCustomContextMenuItems(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ namespace XNodeEditor.Internal {
|
||||
editorTypes = new Dictionary<Type, Type>();
|
||||
|
||||
//Get all classes deriving from NodeEditor via reflection
|
||||
Type[] nodeEditors = XNodeEditor.NodeEditorWindow.GetDerivedTypes(typeof(T));
|
||||
Type[] nodeEditors = typeof(T).GetDerivedTypes();
|
||||
for (int i = 0; i < nodeEditors.Length; i++) {
|
||||
if (nodeEditors[i].IsAbstract) continue;
|
||||
var attribs = nodeEditors[i].GetCustomAttributes(typeof(A), false);
|
||||
|
||||
@ -141,7 +141,7 @@ namespace XNodeEditor {
|
||||
|
||||
Color backgroundColor = new Color32(90, 97, 105, 255);
|
||||
Color tint;
|
||||
if (NodeEditorWindow.nodeTint.TryGetValue(port.node.GetType(), out tint)) backgroundColor *= tint;
|
||||
if (port.node.GetType().TryGetAttributeTint(out tint)) backgroundColor *= tint;
|
||||
Color col = NodeEditorWindow.current.graphEditor.GetPortColor(port);
|
||||
DrawPortHandle(rect, backgroundColor, col);
|
||||
|
||||
@ -153,7 +153,7 @@ namespace XNodeEditor {
|
||||
|
||||
private static System.Type GetType(SerializedProperty property) {
|
||||
System.Type parentType = property.serializedObject.targetObject.GetType();
|
||||
System.Reflection.FieldInfo fi = NodeEditorWindow.GetFieldInfo(parentType, property.name);
|
||||
System.Reflection.FieldInfo fi = parentType.GetFieldInfo(property.name);
|
||||
return fi.FieldType;
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ namespace XNodeEditor {
|
||||
|
||||
Color backgroundColor = new Color32(90, 97, 105, 255);
|
||||
Color tint;
|
||||
if (NodeEditorWindow.nodeTint.TryGetValue(port.node.GetType(), out tint)) backgroundColor *= tint;
|
||||
if (port.node.GetType().TryGetAttributeTint(out tint)) backgroundColor *= tint;
|
||||
Color col = NodeEditorWindow.current.graphEditor.GetPortColor(port);
|
||||
DrawPortHandle(rect, backgroundColor, col);
|
||||
|
||||
@ -225,7 +225,7 @@ namespace XNodeEditor {
|
||||
|
||||
Color backgroundColor = new Color32(90, 97, 105, 255);
|
||||
Color tint;
|
||||
if (NodeEditorWindow.nodeTint.TryGetValue(port.node.GetType(), out tint)) backgroundColor *= tint;
|
||||
if (port.node.GetType().TryGetAttributeTint(out tint)) backgroundColor *= tint;
|
||||
Color col = NodeEditorWindow.current.graphEditor.GetPortColor(port);
|
||||
DrawPortHandle(rect, backgroundColor, col);
|
||||
|
||||
|
||||
@ -7,62 +7,55 @@ using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XNodeEditor {
|
||||
/// <summary> Contains reflection-related info </summary>
|
||||
public partial class NodeEditorWindow {
|
||||
/// <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;
|
||||
/// <summary> Custom node widths defined with [NodeWidth(width)] </summary>
|
||||
public static Dictionary<Type, int> nodeWidth { get { return _nodeWidth != null ? _nodeWidth : _nodeWidth = GetNodeWidth(); } }
|
||||
|
||||
[NonSerialized] private static Dictionary<Type, int> _nodeWidth;
|
||||
/// <summary> Contains reflection-related extensions built for xNode </summary>
|
||||
public static class NodeEditorReflection {
|
||||
[NonSerialized] private static Dictionary<Type, Color> nodeTint;
|
||||
[NonSerialized] private static Dictionary<Type, int> nodeWidth;
|
||||
/// <summary> All available node types </summary>
|
||||
public static Type[] nodeTypes { get { return _nodeTypes != null ? _nodeTypes : _nodeTypes = GetNodeTypes(); } }
|
||||
|
||||
[NonSerialized] private static Type[] _nodeTypes = null;
|
||||
|
||||
private Func<bool> isDocked {
|
||||
get {
|
||||
if (_isDocked == null) {
|
||||
/// <summary> Return a delegate used to determine whether window is docked or not. It is faster to cache this delegate than run the reflection required each time. </summary>
|
||||
public static Func<bool> GetIsDockedDelegate(this EditorWindow window) {
|
||||
BindingFlags fullBinding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
|
||||
MethodInfo isDockedMethod = typeof(NodeEditorWindow).GetProperty("docked", fullBinding).GetGetMethod(true);
|
||||
_isDocked = (Func<bool>) Delegate.CreateDelegate(typeof(Func<bool>), this, isDockedMethod);
|
||||
MethodInfo isDockedMethod = typeof(EditorWindow).GetProperty("docked", fullBinding).GetGetMethod(true);
|
||||
return (Func<bool>) Delegate.CreateDelegate(typeof(Func<bool>), window, isDockedMethod);
|
||||
}
|
||||
return _isDocked;
|
||||
}
|
||||
}
|
||||
private Func<bool> _isDocked;
|
||||
|
||||
public static Type[] GetNodeTypes() {
|
||||
//Get all classes deriving from Node via reflection
|
||||
return GetDerivedTypes(typeof(XNode.Node));
|
||||
}
|
||||
|
||||
public static Dictionary<Type, Color> GetNodeTint() {
|
||||
Dictionary<Type, Color> tints = new Dictionary<Type, Color>();
|
||||
for (int i = 0; i < nodeTypes.Length; i++) {
|
||||
var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.Node.NodeTintAttribute), true);
|
||||
if (attribs == null || attribs.Length == 0) continue;
|
||||
XNode.Node.NodeTintAttribute attrib = attribs[0] as XNode.Node.NodeTintAttribute;
|
||||
tints.Add(nodeTypes[i], attrib.color);
|
||||
/// <summary> Custom node tint colors defined with [NodeColor(r, g, b)] </summary>
|
||||
public static bool TryGetAttributeTint(this Type nodeType, out Color tint) {
|
||||
if (nodeTint == null) {
|
||||
CacheAttributes<Color, XNode.Node.NodeTintAttribute>(ref nodeTint, x => x.color);
|
||||
}
|
||||
return tints;
|
||||
return nodeTint.TryGetValue(nodeType, out tint);
|
||||
}
|
||||
|
||||
public static Dictionary<Type, int> GetNodeWidth() {
|
||||
Dictionary<Type, int> widths = new Dictionary<Type, int>();
|
||||
for (int i = 0; i < nodeTypes.Length; i++) {
|
||||
var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.Node.NodeWidthAttribute), true);
|
||||
if (attribs == null || attribs.Length == 0) continue;
|
||||
XNode.Node.NodeWidthAttribute attrib = attribs[0] as XNode.Node.NodeWidthAttribute;
|
||||
widths.Add(nodeTypes[i], attrib.width);
|
||||
/// <summary> Get custom node widths defined with [NodeWidth(width)] </summary>
|
||||
public static bool TryGetAttributeWidth(this Type nodeType, out int width) {
|
||||
if (nodeWidth == null) {
|
||||
CacheAttributes<int, XNode.Node.NodeWidthAttribute>(ref nodeWidth, x => x.width);
|
||||
}
|
||||
return nodeWidth.TryGetValue(nodeType, out width);
|
||||
}
|
||||
|
||||
private static void CacheAttributes<V, A>(ref Dictionary<Type, V> dict, Func<A, V> getter) where A : Attribute {
|
||||
dict = new Dictionary<Type, V>();
|
||||
for (int i = 0; i < nodeTypes.Length; i++) {
|
||||
object[] attribs = nodeTypes[i].GetCustomAttributes(typeof(A), true);
|
||||
if (attribs == null || attribs.Length == 0) continue;
|
||||
A attrib = attribs[0] as A;
|
||||
dict.Add(nodeTypes[i], getter(attrib));
|
||||
}
|
||||
return widths;
|
||||
}
|
||||
|
||||
/// <summary> Get FieldInfo of a field, including those that are private and/or inherited </summary>
|
||||
public static FieldInfo GetFieldInfo(Type type, string fieldName) {
|
||||
public static FieldInfo GetFieldInfo(this Type type, string fieldName) {
|
||||
// If we can't find field in the first run, it's probably a private field in a base class.
|
||||
FieldInfo field = type.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
// Search base classes for private fields only. Public fields are found above
|
||||
@ -71,7 +64,7 @@ namespace XNodeEditor {
|
||||
}
|
||||
|
||||
/// <summary> Get all classes deriving from baseType via reflection </summary>
|
||||
public static Type[] GetDerivedTypes(Type baseType) {
|
||||
public static Type[] GetDerivedTypes(this Type baseType) {
|
||||
List<System.Type> types = new List<System.Type>();
|
||||
System.Reflection.Assembly[] assemblies = System.AppDomain.CurrentDomain.GetAssemblies();
|
||||
foreach (Assembly assembly in assemblies) {
|
||||
@ -82,7 +75,8 @@ namespace XNodeEditor {
|
||||
return types.ToArray();
|
||||
}
|
||||
|
||||
public static void AddCustomContextMenuItems(GenericMenu contextMenu, object obj) {
|
||||
/// <summary> Find methods marked with the [ContextMenu] attribute and add them to the context menu </summary>
|
||||
public static void AddCustomContextMenuItems(this GenericMenu contextMenu, object obj) {
|
||||
KeyValuePair<ContextMenu, MethodInfo>[] items = GetContextMenuMethods(obj);
|
||||
if (items.Length != 0) {
|
||||
contextMenu.AddSeparator("");
|
||||
@ -104,7 +98,7 @@ namespace XNodeEditor {
|
||||
}
|
||||
|
||||
/// <summary> Call OnValidate on target </summary>
|
||||
public static void TriggerOnValidate(UnityEngine.Object target) {
|
||||
public static void TriggerOnValidate(this UnityEngine.Object target) {
|
||||
System.Reflection.MethodInfo onValidate = null;
|
||||
if (target != null) {
|
||||
onValidate = target.GetType().GetMethod("OnValidate", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
@ -36,7 +36,7 @@ namespace XNodeEditor {
|
||||
|
||||
public static bool GetAttrib<T>(Type classType, string fieldName, out T attribOut) where T : Attribute {
|
||||
// If we can't find field in the first run, it's probably a private field in a base class.
|
||||
FieldInfo field = NodeEditorWindow.GetFieldInfo(classType, fieldName);
|
||||
FieldInfo field = classType.GetFieldInfo(fieldName);
|
||||
// This shouldn't happen. Ever.
|
||||
if (field == null) {
|
||||
Debug.LogWarning("Field " + fieldName + " couldnt be found");
|
||||
|
||||
@ -2,6 +2,8 @@ using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace XNodeEditor {
|
||||
[InitializeOnLoad]
|
||||
@ -14,6 +16,14 @@ namespace XNodeEditor {
|
||||
[SerializeField] private NodePortReference[] _references = new NodePortReference[0];
|
||||
[SerializeField] private Rect[] _rects = new Rect[0];
|
||||
|
||||
private Func<bool> isDocked {
|
||||
get {
|
||||
if (_isDocked == null) _isDocked = this.GetIsDockedDelegate();
|
||||
return _isDocked;
|
||||
}
|
||||
}
|
||||
private Func<bool> _isDocked;
|
||||
|
||||
[System.Serializable] private class NodePortReference {
|
||||
[SerializeField] private XNode.Node _node;
|
||||
[SerializeField] private string _name;
|
||||
|
||||
@ -44,8 +44,8 @@ namespace XNodeEditor {
|
||||
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary>
|
||||
public virtual void AddContextMenuItems(GenericMenu menu) {
|
||||
Vector2 pos = NodeEditorWindow.current.WindowToGridPosition(Event.current.mousePosition);
|
||||
for (int i = 0; i < NodeEditorWindow.nodeTypes.Length; i++) {
|
||||
Type type = NodeEditorWindow.nodeTypes[i];
|
||||
for (int i = 0; i < NodeEditorReflection.nodeTypes.Length; i++) {
|
||||
Type type = NodeEditorReflection.nodeTypes[i];
|
||||
|
||||
//Get node context menu path
|
||||
string path = GetNodeMenuName(type);
|
||||
@ -58,8 +58,8 @@ namespace XNodeEditor {
|
||||
menu.AddSeparator("");
|
||||
if (NodeEditorWindow.copyBuffer != null && NodeEditorWindow.copyBuffer.Length > 0) menu.AddItem(new GUIContent("Paste"), false, () => NodeEditorWindow.current.PasteNodes(pos));
|
||||
else menu.AddDisabledItem(new GUIContent("Paste"));
|
||||
menu.AddItem(new GUIContent("Preferences"), false, () => NodeEditorWindow.OpenPreferences());
|
||||
NodeEditorWindow.AddCustomContextMenuItems(menu, target);
|
||||
menu.AddItem(new GUIContent("Preferences"), false, () => NodeEditorReflection.OpenPreferences());
|
||||
menu.AddCustomContextMenuItems(target);
|
||||
}
|
||||
|
||||
public virtual Color GetPortColor(XNode.NodePort port) {
|
||||
|
||||
@ -51,7 +51,7 @@ namespace XNodeEditor {
|
||||
target.name = NodeEditorUtilities.NodeDefaultName(target.GetType());
|
||||
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
|
||||
Close();
|
||||
NodeEditorWindow.TriggerOnValidate(target);
|
||||
target.TriggerOnValidate();
|
||||
}
|
||||
}
|
||||
// Rename asset to input text
|
||||
@ -60,7 +60,7 @@ namespace XNodeEditor {
|
||||
target.name = input;
|
||||
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
|
||||
Close();
|
||||
NodeEditorWindow.TriggerOnValidate(target);
|
||||
target.TriggerOnValidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user