1
0
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:
Thor Brigsted 2019-07-24 10:04:05 +02:00
parent 93fa101af8
commit 891ecebc3f
8 changed files with 59 additions and 55 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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) {

View File

@ -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();
}
}
}