using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEngine; using XNode; namespace XNodeEditor { /// Contains reflection-related info public partial class NodeEditorWindow { /// Custom node editors defined with [CustomNodeInspector] [NonSerialized] private static Dictionary customNodeEditor; /// Custom node tint colors defined with [NodeColor(r, g, b)] public static Dictionary nodeTint { get { return _nodeTint != null ? _nodeTint : _nodeTint = GetNodeTint(); } } [NonSerialized] private static Dictionary _nodeTint; /// All available node types 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)]; } public static Type[] GetNodeTypes() { //Get all classes deriving from Node via reflection return GetDerivedTypes(typeof(Node)); } public static void CacheCustomNodeEditors() { customNodeEditor = new Dictionary(); 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 GetNodeTint() { Dictionary tints = new Dictionary(); for (int i = 0; i < nodeTypes.Length; i++) { var attribs = nodeTypes[i].GetCustomAttributes(typeof(Node.NodeTint), true); if (attribs == null || attribs.Length == 0) continue; Node.NodeTint attrib = attribs[0] as Node.NodeTint; tints.Add(nodeTypes[i], attrib.color); } return tints; } public static Type[] GetDerivedTypes(Type baseType) { //Get all classes deriving from baseType via reflection Assembly assembly = Assembly.GetAssembly(baseType); return assembly.GetTypes().Where(t => !t.IsAbstract && baseType.IsAssignableFrom(t) ).ToArray(); } public static object ObjectFromType(Type type) { return Activator.CreateInstance(type); } public static object ObjectFromFieldName(object obj, string fieldName) { Type type = obj.GetType(); FieldInfo fieldInfo = type.GetField(fieldName); return fieldInfo.GetValue(obj); } public static KeyValuePair[] GetContextMenuMethods(object obj) { Type type = obj.GetType(); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); List> kvp = new List>(); for (int i = 0; i < methods.Length; i++) { ContextMenu[] attribs = methods[i].GetCustomAttributes(typeof(ContextMenu), true).Select(x => x as ContextMenu).ToArray(); if (attribs == null || attribs.Length == 0) continue; if (methods[i].GetParameters().Length != 0) { Debug.LogWarning("Method " + methods[i].DeclaringType.Name + "." + methods[i].Name + " has parameters and cannot be used for context menu commands."); continue; } if (methods[i].IsStatic) { Debug.LogWarning("Method " + methods[i].DeclaringType.Name + "." + methods[i].Name + " is static and cannot be used for context menu commands."); continue; } for (int k = 0; k < attribs.Length; k++) { kvp.Add(new KeyValuePair(attribs[k], methods[i])); } } //Sort menu items kvp.Sort((x, y) => x.Key.priority.CompareTo(y.Key.priority)); return kvp.ToArray(); } } }