// TO DO: CLASS NAME has to include the type of the input parameters if it is a method to allow overloading public static string GenerateFile(MemberInfo memberInfo, out string filename) { List <KeyValuePair <string, Type> > input = new List <KeyValuePair <string, Type> >(); List <KeyValuePair <string, Type> > output = new List <KeyValuePair <string, Type> >(); StringBuilder builder = new StringBuilder(); builder.Append("//////////////////////////////////////\n"); builder.Append("//// FILE GENERATED AUTOMATICALLY ////\n"); builder.Append("//////////////////////////////////////\n"); builder.Append("\n"); builder.Append("using System;\n"); builder.Append("using Ashkatchap.AIBrain.Nodes;\n"); builder.Append("\n"); builder.Append("namespace Ashkatchap.AIBrain.GeneratedNodes {\n"); builder.Append(" [Serializable]\n"); builder.Append(" [CreateNode(\"Actuator/"+ memberInfo.DeclaringType.FullName.Replace('.', '/') + "/" + TypeFinder.GetDisplayName(memberInfo, false, false) + "\")]\n"); filename = "GN_" + (memberInfo.DeclaringType.FullName + "_" + memberInfo.Name).Replace('.', '_'); if (memberInfo.MemberType == MemberTypes.Method) { string methodSignature = string.Join("__", ((MethodInfo)memberInfo).GetParameters().Select(p => p.ParameterType.FullName.Replace('.', '_')).ToArray()); filename += "_" + GetHashString(methodSignature); } filename = filename.Replace("&", "_Out_"); builder.Append(" public class "+ filename + " : Node {\n"); filename += ".cs"; bool useReference = memberInfo.MemberType == MemberTypes.Method && !((MethodInfo)memberInfo).IsStatic; useReference |= memberInfo.MemberType == MemberTypes.Field && !((FieldInfo)memberInfo).IsStatic; useReference |= memberInfo.MemberType == MemberTypes.Property && !( (((PropertyInfo)memberInfo).GetGetMethod(false) != null && ((PropertyInfo)memberInfo).GetGetMethod(false).IsStatic) || (((PropertyInfo)memberInfo).GetSetMethod(false) != null && ((PropertyInfo)memberInfo).GetSetMethod(false).IsStatic) ); if (useReference) { builder.Append(" [HideInNormalInspector] [UnityEngine.SerializeField] public Input_"+ TemplateIO.GetIOName(memberInfo.DeclaringType) + " refObject;\n"); if (memberInfo.DeclaringType.IsValueType) { builder.Append(" [HideInNormalInspector] [UnityEngine.SerializeField] public Output_"+ TemplateIO.GetIOName(memberInfo.DeclaringType) + " newRefObject;\n"); } } bool isSpecialSetMethod = memberInfo.MemberType == MemberTypes.Method && (memberInfo as MethodInfo).IsSpecialName && memberInfo.Name.StartsWith("set_"); ParameterInfo[] parameters = null; bool methodHasReturn = false; bool canWrite = memberInfo.MemberType == MemberTypes.Field && !((FieldInfo)memberInfo).IsInitOnly && !((FieldInfo)memberInfo).IsLiteral; canWrite |= memberInfo.MemberType == MemberTypes.Property && (memberInfo as PropertyInfo).CanWrite; canWrite |= isSpecialSetMethod; canWrite &= !memberInfo.DeclaringType.IsValueType; bool canRead = memberInfo.MemberType == MemberTypes.Field || (memberInfo.MemberType == MemberTypes.Property && (memberInfo as PropertyInfo).CanRead); Type fieldPropertyType = memberInfo.MemberType == MemberTypes.Field ? (memberInfo as FieldInfo).FieldType : memberInfo.MemberType == MemberTypes.Property ? (memberInfo as PropertyInfo).PropertyType : null; if (memberInfo.MemberType == MemberTypes.Method) { var method = memberInfo as MethodInfo; parameters = method.GetParameters(); for (int i = 0; i < parameters.Length; i++) { if (parameters[i].IsOut) { builder.Append(" [HideInNormalInspector] [UnityEngine.SerializeField] public Output_"+ TemplateIO.GetIOName(parameters[i].ParameterType) + " " + parameters[i].Name + ";\n"); output.Add(new KeyValuePair <string, Type>(parameters[i].Name, parameters[i].ParameterType)); } else { builder.Append(" [HideInNormalInspector] [UnityEngine.SerializeField] public Input_"+ TemplateIO.GetIOName(parameters[i].ParameterType) + " " + parameters[i].Name + ";\n"); input.Add(new KeyValuePair <string, Type>(parameters[i].Name, parameters[i].ParameterType)); } } methodHasReturn = method.ReturnType != typeof(void); if (methodHasReturn) { builder.Append("\n"); builder.Append(" [HideInNormalInspector] [UnityEngine.SerializeField] public Output_"+ TemplateIO.GetIOName(method.ReturnType) + " returnVar;\n"); output.Add(new KeyValuePair <string, Type>("returnVar", method.ReturnType)); } if (isSpecialSetMethod) { fieldPropertyType = parameters[0].ParameterType; } } else { if (canRead) { builder.Append(" [HideInNormalInspector] [UnityEngine.SerializeField] public Output_"+ TemplateIO.GetIOName(fieldPropertyType) + " getter;\n"); output.Add(new KeyValuePair <string, Type>("getter", fieldPropertyType)); } } if (canWrite) { builder.Append(" [HideInNormalInspector] [UnityEngine.SerializeField] public Input_"+ TemplateIO.GetIOName(fieldPropertyType) + " setter;\n"); input.Add(new KeyValuePair <string, Type>("setter", fieldPropertyType)); } builder.Append("\n"); builder.Append("\n"); builder.Append("#if UNITY_EDITOR\n"); builder.Append(" public override void Init() {\n"); var nodeName = memberInfo.Name; if (memberInfo.MemberType == MemberTypes.Method && ((MethodInfo)memberInfo).IsSpecialName) { var name = memberInfo.Name; if (name.StartsWith("get_")) { nodeName = name.Substring("get_".Length); } else if (name.StartsWith("op_")) { nodeName = OperatorFromName[name]; } } builder.Append(" SetName(\""+ nodeName + "\");\n"); if (useReference) { builder.Append(" refObject = "+ CreateIOConstructorParam(memberInfo.DeclaringType, "Input") + ";\n"); if (memberInfo.DeclaringType.IsValueType) { builder.Append(" newRefObject = "+ CreateIOConstructorParam(memberInfo.DeclaringType, "Output") + ";\n"); } } foreach (var i in input) { builder.Append(" "+ i.Key + " = " + CreateIOConstructorParam(i.Value, "Input") + ";\n"); } foreach (var i in output) { builder.Append(" "+ i.Key + " = " + CreateIOConstructorParam(i.Value, "Output") + ";\n"); } builder.Append(" }\n"); builder.Append("#endif\n"); builder.Append("\n"); builder.Append(" public override NodeTreeOutput Tick(out ExecutionResult executionResult, ExecutionResult childResult) {\n"); if (memberInfo.MemberType == MemberTypes.Method && !isSpecialSetMethod) { builder.Append(" Calculate();\n"); } else if (canWrite) { if (useReference) { builder.Append(" (("+ memberInfo.DeclaringType.FullName + ") refObject.GetValue())."); } else { builder.Append(memberInfo.DeclaringType.FullName + "."); } if (isSpecialSetMethod) { builder.Append(memberInfo.Name.Substring("set_".Length)); } else { builder.Append(memberInfo.Name); } builder.Append(" = setter.GetValue();\n"); } builder.Append(" executionResult = ExecutionResult.Success;\n"); builder.Append(" return null;\n"); builder.Append(" }\n"); builder.Append("\n"); builder.Append(" public override void Calculate() {"); if (canRead) { builder.Append("\n"); builder.Append(" getter.value = ("); if (useReference) { builder.Append("((" + memberInfo.DeclaringType.FullName + ") refObject.GetValue())."); } else { builder.Append(memberInfo.DeclaringType.FullName + "."); } builder.Append(memberInfo.Name + ");\n"); } else if (!isSpecialSetMethod) { builder.Append("\n"); builder.Append(" "); WriteMethodAction(memberInfo, parameters, builder, methodHasReturn, useReference); } builder.Append(" }\n"); builder.Append("\n"); builder.Append("#if UNITY_EDITOR\n"); builder.Append(" protected override void Draw() {\n"); if (useReference) { builder.Append(" refObject.DisplayLayout(\"Reference\");\n"); if (memberInfo.DeclaringType.IsValueType) { builder.Append(" newRefObject.DisplayLayout(\"Reference\");\n"); } } if (memberInfo.MemberType == MemberTypes.Method) { for (int i = 0; i < parameters.Length; i++) { if (!parameters[i].IsOut) { builder.Append(" "+ parameters[i].Name + ".DisplayLayout(\"" + parameters[i].Name + "\");\n"); } } for (int i = 0; i < parameters.Length; i++) { if (parameters[i].IsOut) { builder.Append(" "+ parameters[i].Name + ".DisplayLayout(\"" + parameters[i].Name + "\");\n"); } } if (methodHasReturn) { builder.Append(" returnVar.DisplayLayout(\"Return\");\n"); } } else { builder.Append(" UnityEngine.GUILayout.BeginHorizontal();\n"); if (canWrite) { builder.Append(" setter.DisplayLayout(\"set "+ memberInfo.Name + "\");\n"); } if (canRead) { builder.Append(" getter.DisplayLayout(\"get "+ memberInfo.Name + "\");\n"); } builder.Append(" UnityEngine.GUILayout.EndHorizontal();\n"); } builder.Append(" }\n"); builder.Append("#endif\n"); builder.Append(" }\n"); builder.Append("}\n"); return(builder.ToString()); }
/// <param name="ioType">Input or Output</param> static string CreateIOConstructorParam(Type type, string ioType) { return(type.IsValueType || type.IsAbstract || type.GetConstructors().Count(c => c.GetParameters().Length == 0) == 0 ? "CreateIO<" + ioType + "_" + TemplateIO.GetIOName(type) + ">()" : "Create" + ioType + "<" + ioType + "_" + TemplateIO.GetIOName(type) + ", " + type.FullName + ">(new " + type.FullName + "())"); }
// Do something similar for structs and enums like Vector3 void OnGUI() { var toggleStyle = EditorStyles.toggle; toggleStyle.richText = true; var buttonStyle = GUI.skin.button; buttonStyle.richText = true; buttonStyle.alignment = TextAnchor.MiddleLeft; if (CheckStep("Step 1: Select Nodes to create", 1)) { string searchLower = search.ToLower(); int matches = TypeFinder.Types.Where(t => search == "" || t.FullName.ToLower().Contains(searchLower)).Count(); search = EditorGUILayout.TextField("Search (Matches: " + matches + ")", search); searchLower = search.ToLower(); scroll = GUILayout.BeginScrollView(scroll, false, true); foreach (var type in TypeFinder.Types) { if (search == "" || type.FullName.ToLower().Contains(searchLower)) { if (GUILayoutCull.Button(position, scroll, type.FullName, buttonStyle)) { clickedType = clickedType == type ? null : type; if (clickedType == type) { currentTypeMethods = TypeFinder.GetMethods(type); currentTypePropertiesAndFields = TypeFinder.GetPropertiesAndFields(type); } } if (clickedType == type) { GUILayout.Label("Struct/class", EditorStyles.boldLabel); bool inside = WantedStructs.Contains(type); if (inside != GUILayout.Toggle(inside, type.Name, toggleStyle)) { if (inside) { WantedStructs.Remove(type); } else { WantedStructs.Add(type); } } /* * GUILayout.Label("Constructors", EditorStyles.boldLabel); * // TO DO */ GUILayout.Label("Methods", EditorStyles.boldLabel); foreach (var elem in currentTypeMethods) { inside = WantedMembers.Contains(elem); if (inside != GUILayout.Toggle(inside, TypeFinder.GetDisplayName(elem, true, true), toggleStyle)) { if (inside) { WantedMembers.Remove(elem); } else { WantedMembers.Add(elem); } } } GUILayout.Label("Properties and Fields", EditorStyles.boldLabel); foreach (var elem in currentTypePropertiesAndFields) { inside = WantedMembers.Contains(elem); if (inside != GUILayout.Toggle(inside, TypeFinder.GetDisplayName(elem, true, true), toggleStyle)) { if (inside) { WantedMembers.Remove(elem); } else { WantedMembers.Add(elem); } } } } } } GUILayout.EndScrollView(); } EditorGUILayout.EndToggleGroup(); if (CheckStep("Step 2: Generate files", 2)) { scroll = GUILayout.BeginScrollView(scroll, false, true); GUILayout.Label("Structs", EditorStyles.boldLabel); foreach (var elem in WantedStructs) { if (!GUILayout.Toggle(true, elem.FullName + " - " + elem.FullName, toggleStyle)) { WantedStructs.Remove(elem); break; } } GUILayout.Label("Methods, Properties and Fields", EditorStyles.boldLabel); foreach (var elem in WantedMembers) { if (!GUILayout.Toggle(true, elem.DeclaringType.FullName + " - " + TypeFinder.GetDisplayName(elem, true, true), toggleStyle)) { WantedMembers.Remove(elem); break; } } GUILayout.EndScrollView(); if (GUILayout.Button("Generate Files")) { var fullPath = GetFullPath(); foreach (var elem in WantedMembers) { string filename; string textFile = TemplateNode.GenerateFile(elem, out filename); WriteFile(fullPath, "Nodes", filename, textFile); } foreach (var elem in WantedStructs) { string filename; string textFile = TemplateIO.GenerateFileInput(elem, out filename); WriteFile(fullPath, "IO", filename, textFile); textFile = TemplateIO.GenerateFileOutput(elem, out filename); WriteFile(fullPath, "IO", filename, textFile); textFile = TemplateIO.GenerateValueFile(elem, out filename); WriteFile(fullPath, "Values", filename, textFile); } AssetDatabase.Refresh(); } } EditorGUILayout.EndToggleGroup(); }