diff options
author | chai <chaifix@163.com> | 2022-06-28 09:40:37 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2022-06-28 09:40:37 +0800 |
commit | 49b25e755b70ec412feaaf0b898d6f7e09d2bea6 (patch) | |
tree | 3c5f4260f30d1c2d7196db93153700d7ddec3157 /Other/NodeEditorExamples/Assets/xNode-examples/Scripts/Editor/NodeEditorUtilities.cs | |
parent | c92269331692feca2c276649f6c4ee8911f1f859 (diff) |
+node example
Diffstat (limited to 'Other/NodeEditorExamples/Assets/xNode-examples/Scripts/Editor/NodeEditorUtilities.cs')
-rw-r--r-- | Other/NodeEditorExamples/Assets/xNode-examples/Scripts/Editor/NodeEditorUtilities.cs | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/Other/NodeEditorExamples/Assets/xNode-examples/Scripts/Editor/NodeEditorUtilities.cs b/Other/NodeEditorExamples/Assets/xNode-examples/Scripts/Editor/NodeEditorUtilities.cs new file mode 100644 index 00000000..a6ede849 --- /dev/null +++ b/Other/NodeEditorExamples/Assets/xNode-examples/Scripts/Editor/NodeEditorUtilities.cs @@ -0,0 +1,266 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using UnityEditor; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace XNodeEditor { + /// <summary> A set of editor-only utilities and extensions for xNode </summary> + public static class NodeEditorUtilities { + + /// <summary>C#'s Script Icon [The one MonoBhevaiour Scripts have].</summary> + private static Texture2D scriptIcon = (EditorGUIUtility.IconContent("cs Script Icon").image as Texture2D); + + /// Saves Attribute from Type+Field for faster lookup. Resets on recompiles. + private static Dictionary<Type, Dictionary<string, Dictionary<Type, Attribute>>> typeAttributes = new Dictionary<Type, Dictionary<string, Dictionary<Type, Attribute>>>(); + + /// Saves ordered PropertyAttribute from Type+Field for faster lookup. Resets on recompiles. + private static Dictionary<Type, Dictionary<string, List<PropertyAttribute>>> typeOrderedPropertyAttributes = new Dictionary<Type, Dictionary<string, List<PropertyAttribute>>>(); + + public static bool GetAttrib<T>(Type classType, out T attribOut) where T : Attribute { + object[] attribs = classType.GetCustomAttributes(typeof(T), false); + return GetAttrib(attribs, out attribOut); + } + + public static bool GetAttrib<T>(object[] attribs, out T attribOut) where T : Attribute { + for (int i = 0; i < attribs.Length; i++) { + if (attribs[i] is T) { + attribOut = attribs[i] as T; + return true; + } + } + attribOut = null; + return false; + } + + 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 = classType.GetFieldInfo(fieldName); + // This shouldn't happen. Ever. + if (field == null) { + Debug.LogWarning("Field " + fieldName + " couldnt be found"); + attribOut = null; + return false; + } + object[] attribs = field.GetCustomAttributes(typeof(T), true); + return GetAttrib(attribs, out attribOut); + } + + public static bool HasAttrib<T>(object[] attribs) where T : Attribute { + for (int i = 0; i < attribs.Length; i++) { + if (attribs[i].GetType() == typeof(T)) { + return true; + } + } + return false; + } + + public static bool GetCachedAttrib<T>(Type classType, string fieldName, out T attribOut) where T : Attribute { + Dictionary<string, Dictionary<Type, Attribute>> typeFields; + if (!typeAttributes.TryGetValue(classType, out typeFields)) { + typeFields = new Dictionary<string, Dictionary<Type, Attribute>>(); + typeAttributes.Add(classType, typeFields); + } + + Dictionary<Type, Attribute> typeTypes; + if (!typeFields.TryGetValue(fieldName, out typeTypes)) { + typeTypes = new Dictionary<Type, Attribute>(); + typeFields.Add(fieldName, typeTypes); + } + + Attribute attr; + if (!typeTypes.TryGetValue(typeof(T), out attr)) { + if (GetAttrib<T>(classType, fieldName, out attribOut)) { + typeTypes.Add(typeof(T), attribOut); + return true; + } else typeTypes.Add(typeof(T), null); + } + + if (attr == null) { + attribOut = null; + return false; + } + + attribOut = attr as T; + return true; + } + + public static List<PropertyAttribute> GetCachedPropertyAttribs(Type classType, string fieldName) { + Dictionary<string, List<PropertyAttribute>> typeFields; + if (!typeOrderedPropertyAttributes.TryGetValue(classType, out typeFields)) { + typeFields = new Dictionary<string, List<PropertyAttribute>>(); + typeOrderedPropertyAttributes.Add(classType, typeFields); + } + + List<PropertyAttribute> typeAttributes; + if (!typeFields.TryGetValue(fieldName, out typeAttributes)) { + FieldInfo field = classType.GetFieldInfo(fieldName); + object[] attribs = field.GetCustomAttributes(typeof(PropertyAttribute), true); + typeAttributes = attribs.Cast<PropertyAttribute>().Reverse().ToList(); //Unity draws them in reverse + typeFields.Add(fieldName, typeAttributes); + } + + return typeAttributes; + } + + public static bool IsMac() { +#if UNITY_2017_1_OR_NEWER + return SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX; +#else + return SystemInfo.operatingSystem.StartsWith("Mac"); +#endif + } + + /// <summary> Returns true if this can be casted to <see cref="Type"/></summary> + public static bool IsCastableTo(this Type from, Type to) { + if (to.IsAssignableFrom(from)) return true; + var methods = from.GetMethods(BindingFlags.Public | BindingFlags.Static) + .Where( + m => m.ReturnType == to && + (m.Name == "op_Implicit" || + m.Name == "op_Explicit") + ); + return methods.Count() > 0; + } + + /// <summary> Return a prettiefied type name. </summary> + public static string PrettyName(this Type type) { + if (type == null) return "null"; + if (type == typeof(System.Object)) return "object"; + if (type == typeof(float)) return "float"; + else if (type == typeof(int)) return "int"; + else if (type == typeof(long)) return "long"; + else if (type == typeof(double)) return "double"; + else if (type == typeof(string)) return "string"; + else if (type == typeof(bool)) return "bool"; + else if (type.IsGenericType) { + string s = ""; + Type genericType = type.GetGenericTypeDefinition(); + if (genericType == typeof(List<>)) s = "List"; + else s = type.GetGenericTypeDefinition().ToString(); + + Type[] types = type.GetGenericArguments(); + string[] stypes = new string[types.Length]; + for (int i = 0; i < types.Length; i++) { + stypes[i] = types[i].PrettyName(); + } + return s + "<" + string.Join(", ", stypes) + ">"; + } else if (type.IsArray) { + string rank = ""; + for (int i = 1; i < type.GetArrayRank(); i++) { + rank += ","; + } + Type elementType = type.GetElementType(); + if (!elementType.IsArray) return elementType.PrettyName() + "[" + rank + "]"; + else { + string s = elementType.PrettyName(); + int i = s.IndexOf('['); + return s.Substring(0, i) + "[" + rank + "]" + s.Substring(i); + } + } else return type.ToString(); + } + + /// <summary> Returns the default name for the node type. </summary> + public static string NodeDefaultName(Type type) { + string typeName = type.Name; + // Automatically remove redundant 'Node' postfix + if (typeName.EndsWith("Node")) typeName = typeName.Substring(0, typeName.LastIndexOf("Node")); + typeName = UnityEditor.ObjectNames.NicifyVariableName(typeName); + return typeName; + } + + /// <summary> Returns the default creation path for the node type. </summary> + public static string NodeDefaultPath(Type type) { + string typePath = type.ToString().Replace('.', '/'); + // Automatically remove redundant 'Node' postfix + if (typePath.EndsWith("Node")) typePath = typePath.Substring(0, typePath.LastIndexOf("Node")); + typePath = UnityEditor.ObjectNames.NicifyVariableName(typePath); + return typePath; + } + + /// <summary>Creates a new C# Class.</summary> + [MenuItem("Assets/Create/xNode/Node C# Script", false, 89)] + private static void CreateNode() { + string[] guids = AssetDatabase.FindAssets("xNode_NodeTemplate.cs"); + if (guids.Length == 0) { + Debug.LogWarning("xNode_NodeTemplate.cs.txt not found in asset database"); + return; + } + string path = AssetDatabase.GUIDToAssetPath(guids[0]); + CreateFromTemplate( + "NewNode.cs", + path + ); + } + + /// <summary>Creates a new C# Class.</summary> + [MenuItem("Assets/Create/xNode/NodeGraph C# Script", false, 89)] + private static void CreateGraph() { + string[] guids = AssetDatabase.FindAssets("xNode_NodeGraphTemplate.cs"); + if (guids.Length == 0) { + Debug.LogWarning("xNode_NodeGraphTemplate.cs.txt not found in asset database"); + return; + } + string path = AssetDatabase.GUIDToAssetPath(guids[0]); + CreateFromTemplate( + "NewNodeGraph.cs", + path + ); + } + + public static void CreateFromTemplate(string initialName, string templatePath) { + ProjectWindowUtil.StartNameEditingIfProjectWindowExists( + 0, + ScriptableObject.CreateInstance<DoCreateCodeFile>(), + initialName, + scriptIcon, + templatePath + ); + } + + /// Inherits from EndNameAction, must override EndNameAction.Action + public class DoCreateCodeFile : UnityEditor.ProjectWindowCallback.EndNameEditAction { + public override void Action(int instanceId, string pathName, string resourceFile) { + Object o = CreateScript(pathName, resourceFile); + ProjectWindowUtil.ShowCreatedAsset(o); + } + } + + /// <summary>Creates Script from Template's path.</summary> + internal static UnityEngine.Object CreateScript(string pathName, string templatePath) { + string className = Path.GetFileNameWithoutExtension(pathName).Replace(" ", string.Empty); + string templateText = string.Empty; + + UTF8Encoding encoding = new UTF8Encoding(true, false); + + if (File.Exists(templatePath)) { + /// Read procedures. + StreamReader reader = new StreamReader(templatePath); + templateText = reader.ReadToEnd(); + reader.Close(); + + templateText = templateText.Replace("#SCRIPTNAME#", className); + templateText = templateText.Replace("#NOTRIM#", string.Empty); + /// You can replace as many tags you make on your templates, just repeat Replace function + /// e.g.: + /// templateText = templateText.Replace("#NEWTAG#", "MyText"); + + /// Write procedures. + + StreamWriter writer = new StreamWriter(Path.GetFullPath(pathName), false, encoding); + writer.Write(templateText); + writer.Close(); + + AssetDatabase.ImportAsset(pathName); + return AssetDatabase.LoadAssetAtPath(pathName, typeof(Object)); + } else { + Debug.LogError(string.Format("The template file was not found: {0}", templatePath)); + return null; + } + } + } +} |