Files
Convention-Unity-Demo/Assets/Scripts/Framework/EditiorContent/ProjectCreateHelper.cs

155 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Convention;
using UnityEngine;
namespace Demo.Editor
{
public static class ProjectCreateHelper
{
private static void WritePythonStyleFunction(StreamWriter stream, string name, IEnumerable<string> 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))
{
// 绘制工具宏
stream.WriteLine("#define __build_in_pragma #");
stream.WriteLine("#define __build_in_to_text(x) #x");
// 绘制类定义标识符
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in asm.GetTypes())
{
// Functions
if (typeof(ScriptableObject).IsAssignableFrom(type))
{
string typeName = type.Name;
if (typeName.Contains('`'))
{
typeName = typeName[..typeName.LastIndexOf('`')];
}
stream.WriteLine($"#define {typeName}");
}
}
}
// 绘制Mathf
foreach (var method in typeof(Mathf).GetMethods())
{
stream.WriteLine($"#define {method.Name}({string.Join(',', from param in method.GetParameters() select param.Name)})");
}
// 绘制label与goto
stream.Write(@"
/*
控制流标签
*/
");
stream.Write($"#define label(label_name) __build_in_pragma define label_name\n\n");
stream.Write(@"
/*
控制流, 当a>b时跳转到指定的label处
*/
");
stream.Write($"#define goto(a,b,label_name)\n\n");
// 绘制工具
stream.Write(@"
/*
临时设置上下文变量, 在运行完语句后将还原
e.g: LoadSubScript(SplineCore, ""SplineCore.h"") with(r = 1, g = 1, b = 1);
*/
");
stream.Write($"#define with(...)\n\n");
return;
}
string baseTypeName = currentType.BaseType.Name;
if (baseTypeName.Contains('`'))
{
baseTypeName = baseTypeName[..baseTypeName.LastIndexOf('`')];
}
stream.Write($"#include \"{baseTypeName}.helper.h\"\n\n");
}
private static void WriteCPPStyleFunction(StreamWriter stream, string name, IEnumerable<string> paramList, string description)
{
if (name == nameof(ScriptableObject.LoadSubScript))
{
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<ScriptableCallAttribute>(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<ScriptableCallAttribute>(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<ScriptableCallAttribute>(false) != null)
{
// TODO
}
}
}
}
}
}