using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using Convention; using Unity.VisualScripting; using UnityEngine; namespace Demo.Editor { public static class ProjectCreateHelper { private static void WritePythonStyleFunction(StreamWriter stream, string name, IEnumerable paramList, string description) { stream.Write($"def {name}({string.Join(',', paramList)}):\n"); stream.Write($"'''\n{description}\n'''\n...\n\n"); } private static void WriteCPPClassBase(StreamWriter stream, Type currentType) { if (currentType == typeof(ScriptableObject)) return; string typeName = currentType.Name; if (typeName.Contains('`')) { typeName = typeName[..typeName.LastIndexOf('`')]; } string baseTypeName = currentType.BaseType.Name; if (baseTypeName.Contains('`')) { baseTypeName = baseTypeName[..baseTypeName.LastIndexOf('`')]; } stream.Write($"#include \"{baseTypeName}.helper.h\"\n\n#define {typeName}\n\n"); stream.Write(@"/* 临时设置上下文变量, 在运行完语句后将还原 e.g: LoadSubScript(SplineCore, ""SplineCore.h"") with(r = 1, g = 1, b = 1); */"); stream.Write($"#define with(...)\n\n"); } private static void WriteCPPStyleFunction(StreamWriter stream, string name, IEnumerable paramList, string description) { if (name == nameof(ScriptableObject.LoadSubScript)) { stream.WriteLine("#define __build_in_pragma #"); stream.WriteLine("#define __build_in_to_text(x) #x"); stream.Write("/*\n" + description + "\n*/\n"); stream.Write($"#define {name}({string.Join(',', paramList)}) __build_in_pragma include {paramList.ToArray()[1]}\n\n"); //stream.Write($"#define {name}({string.Join(',', paramList)})\n\n"); } else { stream.Write("/*\n" + description + "\n*/\n"); stream.Write($"#define {name}({string.Join(',', paramList)}) \n\n"); } } public static void CreateHelperFiles(string dir, ProjectDefaultFileStyle style = ProjectDefaultFileStyle.CPP) { var toolDir = new ToolFile(dir); if (toolDir.IsDir() == false) { throw new InvalidOperationException("Not a directory"); } toolDir.MustExistsPath(); foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var type in asm.GetTypes()) { // Functions if (typeof(ScriptableObject).IsAssignableFrom(type)) { var scriptCalls = (from info in type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) where info is MethodInfo where info.GetCustomAttribute(false) != null select info as MethodInfo).ToList(); var typeName = type.Name; if (typeName.Contains('`')) { typeName = typeName[..typeName.LastIndexOf('`')]; } string fileHeader = $"{typeName}.helper" + style switch { ProjectDefaultFileStyle.PY => ",py", _ => ".h" }; using var fs = File.AppendText((toolDir | fileHeader).GetFullPath()); switch (style) { case ProjectDefaultFileStyle.CPP: WriteCPPClassBase(fs, type); break; case ProjectDefaultFileStyle.PY: break; } foreach (var methodInfo in scriptCalls) { var data = methodInfo.GetCustomAttribute(false); switch (style) { case ProjectDefaultFileStyle.PY: WritePythonStyleFunction(fs, methodInfo.Name, from param in methodInfo.GetParameters() select param.Name, data.Description); break; default: WriteCPPStyleFunction(fs, methodInfo.Name, from param in methodInfo.GetParameters() select param.Name, data.Description); break; } } } // Enums if (typeof(Enum).IsAssignableFrom(type)&& type.GetCustomAttribute(false) != null) { // TODO } } } } } }