307 lines
10 KiB
C#
307 lines
10 KiB
C#
![]() |
#region Class Documentation
|
|||
|
/************************************************************************************************************
|
|||
|
Class Name: EventInterfaceGenerate.cs
|
|||
|
Type: Editor, Generator, Util, Static
|
|||
|
Definition:
|
|||
|
用法,在目录"Assets/GameScripts/HotFix/GameLogic/Event/Interface/"下分组照示例声明Interface 模块待抛出事件的接口。编译后自动生成接口实现抛出的脚本。
|
|||
|
Example:
|
|||
|
|
|||
|
旧版抛出事件方式: GameEvent.Send(RuntimeId.ToRuntimeId("OnMainPlayerCurrencyChange"),CurrencyType.Gold,oldVal,newVal);
|
|||
|
|
|||
|
新版抛出事件方式 : GameEvent.Get<IActorLogicEvent>().OnMainPlayerCurrencyChange(CurrencyType.Gold,oldVal,newVal);
|
|||
|
|
|||
|
************************************************************************************************************/
|
|||
|
#endregion
|
|||
|
|
|||
|
using HybridCLR.Editor.Settings;
|
|||
|
using System;
|
|||
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Reflection;
|
|||
|
using TEngine;
|
|||
|
using Unity.EditorCoroutines.Editor;
|
|||
|
using UnityEditor;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
[InitializeOnLoad]
|
|||
|
public static class EventInterfaceGenerate
|
|||
|
{
|
|||
|
public static string NameSpace = @"GameLogic";
|
|||
|
|
|||
|
|
|||
|
public const string EventInterfacePath = "Assets/GameScripts/HotFix/GameLogic/Event/Interface/";
|
|||
|
|
|||
|
public static bool BOpenAutoGenerate = false;
|
|||
|
|
|||
|
static EventInterfaceGenerate()
|
|||
|
{
|
|||
|
BOpenAutoGenerate = EditorPrefs.GetBool("EventInterfaceGenerate.BOpenAutoGenerate", true);
|
|||
|
if (BOpenAutoGenerate)
|
|||
|
{
|
|||
|
Generate();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
[MenuItem("TEngine/EventInterface/OpenAutoGenerate", false, 300)]
|
|||
|
public static void OpenAutoGenerate()
|
|||
|
{
|
|||
|
EditorPrefs.SetBool("EventInterfaceGenerate.BOpenAutoGenerate", true);
|
|||
|
Debug.Log("OpenAutoGenerate");
|
|||
|
}
|
|||
|
|
|||
|
[MenuItem("TEngine/EventInterface/CloseAutoGenerate", false, 301)]
|
|||
|
public static void CloseAutoGenerate()
|
|||
|
{
|
|||
|
EditorPrefs.SetBool("EventInterfaceGenerate.BOpenAutoGenerate", false);
|
|||
|
Debug.Log("CloseAutoGenerate");
|
|||
|
}
|
|||
|
|
|||
|
[MenuItem("TEngine/EventInterface/Generate EventInterface", false, 302)]
|
|||
|
public static void Generate()
|
|||
|
{
|
|||
|
if (EventInterfaceGenerateTag.HadGenerate)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
EventInterfaceGenerateTag.HadGenerate = true;
|
|||
|
|
|||
|
// 加载程序集
|
|||
|
Assembly assembly = null;
|
|||
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
|||
|
{
|
|||
|
foreach(var type in asm.GetTypes())
|
|||
|
{
|
|||
|
if (type.Name == "GameApp")
|
|||
|
{
|
|||
|
assembly = asm;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if(assembly == null)
|
|||
|
{
|
|||
|
Debug.LogError("Game App Class Not Found");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// 获取程序集中的所有类型
|
|||
|
Type[] types = assembly.GetTypes();
|
|||
|
|
|||
|
// 遍历每个类型
|
|||
|
foreach (Type type in types)
|
|||
|
{
|
|||
|
// 检查类型是否是接口
|
|||
|
if (!type.IsInterface)
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
var attribute = type.GetCustomAttributes(typeof(EventInterfaceAttribute), false).FirstOrDefault();
|
|||
|
|
|||
|
if (attribute != null)
|
|||
|
{
|
|||
|
EventInterfaceAttribute eventInterfaceAttribute = attribute as EventInterfaceAttribute;
|
|||
|
|
|||
|
GenAutoBindCode(type, eventInterfaceAttribute);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
AssetDatabase.Refresh();
|
|||
|
Debug.Log("Generate EventInterface Complete");
|
|||
|
// EditorUtility.DisplayDialog("提示", "代码生成完毕", "OK");
|
|||
|
|
|||
|
EditorCoroutineUtility.StartCoroutine(EventInterfaceGenerateTag.Reset(), null);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 生成自动绑定代码
|
|||
|
/// </summary>
|
|||
|
private static void GenAutoBindCode(Type interfaceType, EventInterfaceAttribute eventInterfaceAttribute)
|
|||
|
{
|
|||
|
string interfaceName = interfaceType.Name;
|
|||
|
string className = $"{interfaceName}_Gen";
|
|||
|
string codePath = $"{Application.dataPath}/GameScripts/HotFix/GameLogic/Event/Gen/{eventInterfaceAttribute.EventGroup}";
|
|||
|
|
|||
|
if (!Directory.Exists(codePath))
|
|||
|
{
|
|||
|
Directory.CreateDirectory(codePath);
|
|||
|
}
|
|||
|
|
|||
|
using (StreamWriter sw = new StreamWriter($"{codePath}/{className}.cs"))
|
|||
|
{
|
|||
|
sw.WriteLine(
|
|||
|
$"//------------------------------------------------------------------------------\n//\t<auto-generated>\n//\t\tThis code was generated by autoBindTool.\n//\t\tChanges to this file may cause incorrect behavior and will be lost if\n//\t\tthe code is regenerated.\n//\t</auto-generated>\n//------------------------------------------------------------------------------");
|
|||
|
sw.WriteLine("using UnityEngine;");
|
|||
|
sw.WriteLine("using UnityEngine.UI;");
|
|||
|
sw.WriteLine("using TEngine;");
|
|||
|
sw.WriteLine("");
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(NameSpace))
|
|||
|
{
|
|||
|
//命名空间
|
|||
|
sw.WriteLine("namespace " + NameSpace);
|
|||
|
sw.WriteLine("{");
|
|||
|
}
|
|||
|
|
|||
|
#region EventId生成
|
|||
|
|
|||
|
sw.WriteLine($"\tpublic partial class {interfaceName}_Event");
|
|||
|
sw.WriteLine("\t{");
|
|||
|
|
|||
|
// 获取接口中的所有方法
|
|||
|
MethodInfo[] methods = interfaceType.GetMethods();
|
|||
|
|
|||
|
HashSet<string> hadGenerate = new HashSet<string>();
|
|||
|
|
|||
|
//组件字段
|
|||
|
foreach (MethodInfo method in methods)
|
|||
|
{
|
|||
|
if (hadGenerate.Contains(method.Name))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
sw.WriteLine($"\t\tpublic static readonly int {method.Name} = RuntimeId.ToRuntimeId(\"{interfaceName}_Event.{method.Name}\");");
|
|||
|
hadGenerate.Add(method.Name);
|
|||
|
}
|
|||
|
|
|||
|
sw.WriteLine("\t}");
|
|||
|
sw.WriteLine("");
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
|
|||
|
//类名
|
|||
|
sw.WriteLine($"\t[EventInterfaceImp(EEventGroup.{eventInterfaceAttribute.EventGroup})]");
|
|||
|
sw.WriteLine($"\tpublic partial class {className} : {interfaceName}");
|
|||
|
sw.WriteLine("\t{");
|
|||
|
|
|||
|
sw.WriteLine("\t\tprivate EventDispatcher _dispatcher;");
|
|||
|
sw.WriteLine($"\t\tpublic {className}(EventDispatcher dispatcher)");
|
|||
|
sw.WriteLine("\t\t{");
|
|||
|
sw.WriteLine($"\t\t\t_dispatcher = dispatcher;");
|
|||
|
sw.WriteLine("\t\t}");
|
|||
|
sw.WriteLine("");
|
|||
|
|
|||
|
//组件字段
|
|||
|
foreach (MethodInfo methodInfo in methods)
|
|||
|
{
|
|||
|
ParameterInfo[] parameterInfos = methodInfo.GetParameters(); //得到指定方法的参数列表
|
|||
|
if (parameterInfos.Length <= 0)
|
|||
|
{
|
|||
|
sw.WriteLine(
|
|||
|
$" public void {methodInfo.Name}()\n {{\n _dispatcher.Send({interfaceName}_Event.{methodInfo.Name});\n }}");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string paramStr = "";
|
|||
|
string paramStr2 = "";
|
|||
|
for (int i = 0; i < parameterInfos.Length; i++)
|
|||
|
{
|
|||
|
var parameterInfo = parameterInfos[i];
|
|||
|
Type type = parameterInfo.ParameterType;
|
|||
|
string paramName = parameterInfo.Name;
|
|||
|
|
|||
|
if (type.FullName.StartsWith("System.Collections.Generic.List"))
|
|||
|
{
|
|||
|
Debug.Log("123");
|
|||
|
}
|
|||
|
|
|||
|
if (i == parameterInfos.Length - 1)
|
|||
|
{
|
|||
|
paramStr += $"{GetTypeName(parameterInfo)} {paramName}";
|
|||
|
paramStr2 += $"{paramName}";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
paramStr += $"{GetTypeName(parameterInfo)} {paramName},";
|
|||
|
paramStr2 += $"{paramName},";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
sw.WriteLine(
|
|||
|
$" public void {methodInfo.Name}({paramStr})\n {{\n _dispatcher.Send({interfaceName}_Event.{methodInfo.Name},{paramStr2});\n }}");
|
|||
|
}
|
|||
|
|
|||
|
sw.WriteLine("");
|
|||
|
}
|
|||
|
|
|||
|
sw.WriteLine("\t}");
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(NameSpace))
|
|||
|
{
|
|||
|
sw.WriteLine("}");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static string GetTypeName(ParameterInfo parameterInfo)
|
|||
|
{
|
|||
|
if (parameterInfo.ParameterType.IsList() && parameterInfo.ParameterType.IsGenericType)
|
|||
|
{
|
|||
|
string typeName = parameterInfo.ParameterType.FullName.Split('`')[0];
|
|||
|
|
|||
|
return $"{typeName}<{parameterInfo.ParameterType.GenericTypeArguments[0].FullName}>";
|
|||
|
}
|
|||
|
else if (parameterInfo.ParameterType.IsDictionary() && parameterInfo.ParameterType.IsGenericType)
|
|||
|
{
|
|||
|
string typeName = parameterInfo.ParameterType.FullName.Split('`')[0];
|
|||
|
|
|||
|
return $"{typeName}<{parameterInfo.ParameterType.GenericTypeArguments[0].FullName},{parameterInfo.ParameterType.GenericTypeArguments[1].FullName}>";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return parameterInfo.ParameterType.FullName;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 判断类型是否为可操作的列表类型
|
|||
|
/// </summary>
|
|||
|
/// <param name="type"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public static bool IsList(this Type type)
|
|||
|
{
|
|||
|
if (typeof (System.Collections.IList).IsAssignableFrom(type))
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
foreach (var it in type.GetInterfaces())
|
|||
|
{
|
|||
|
if (it.IsGenericType && typeof (IList<>) == it.GetGenericTypeDefinition())
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
public static bool IsDictionary(this Type type)
|
|||
|
{
|
|||
|
if (typeof (System.Collections.IDictionary).IsAssignableFrom(type))
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
foreach (var it in type.GetInterfaces())
|
|||
|
{
|
|||
|
if (it.IsGenericType && typeof (IDictionary) == it.GetGenericTypeDefinition())
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static class EventInterfaceGenerateTag
|
|||
|
{
|
|||
|
public static bool HadGenerate = false;
|
|||
|
|
|||
|
public static IEnumerator Reset()
|
|||
|
{
|
|||
|
yield return new WaitForSeconds(10f);
|
|||
|
HadGenerate = false;
|
|||
|
}
|
|||
|
}
|