书接上集,在完成了UI引用字段的自动赋值后,鱼鱼研究出了自动写脚本的编辑器代码。
直接展示
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.Text;
using System.Reflection;
public class UIPanelGenerate : EditorWindow
{
private string path;
private string[] pathDefult=new string[] {"/Scripts/UI/Panel" };
private int index = 0;
public bool isCover;
private string discern = "H";
private string hintInfo;
[MenuItem("Tool/GenerateUIPanel")]
private static void GenerateWindow()
{
UIPanelGenerate uIPanel = EditorWindow.GetWindowWithRect(typeof(UIPanelGenerate), new Rect(0, 0, 500, 500), true, "GenerateUIPanel") as UIPanelGenerate;
uIPanel.Show();
}
private void OnGUI()
{
GUI.Label(new Rect(2, 0, 200, 20),"生成路径");
index= GUI.Toolbar(new Rect(2, 20, 200, 20), index, pathDefult);
path= GUI.TextField(new Rect(2, 40, 450, 20),path);
isCover= GUI.Toggle(new Rect(2, 80, 200, 20), isCover,"是否覆盖");
if(GUI.Button(new Rect(200, 400, 100, 20), "生成Panel"))
{
GeneratePanel();
}
GUI.Label(new Rect(200, 350, 200, 20), hintInfo);
}
private void GeneratePanel()
{
if (Selection.activeGameObject ==null)
{
Debug.Log( "没有选中UI面板");
return;
}
string select = Selection.activeGameObject.name;
Transform targetTranform = Selection.activeTransform;
if (path == null || path == "")
{
path = pathDefult[index];
}
if (File.Exists(Application.dataPath+path + "/" + Selection.activeGameObject.name+".cs")&&!isCover)
{
Debug.LogError("目录下已经存在" + Selection.activeGameObject.name);
return;
}
else
{
// File.Create(Application.dataPath + path + "/" + Selection.activeGameObject.name + ".cs");
FileStream fileStream = new FileStream(Application.dataPath + path + "/" + Selection.activeGameObject.name + ".cs", FileMode.Create,FileAccess.ReadWrite);
fileStream.Dispose();
fileStream.Close();
Debug.Log("开始生成");
}
for(int i=0; i< Selection.gameObjects.Length; i++)
{
select = Selection.gameObjects[i].name;
targetTranform = Selection.gameObjects[i].transform;
StringBuilder data = new StringBuilder();
data.Append("using System.Collections;\n");
data.Append("using System.Collections.Generic;\n");
data.Append("using UnityEngine;\n");
data.Append("using UnityEngine.UI;\n");
data.Append("\n");
data.Append("public class " + select + " :" + "BasePanel\n{\n");
WriteQuoteField(data, targetTranform);
WriteRewriteMethod(data);
data.Append("}");
try
{
using (StreamWriter sw = new StreamWriter(Application.dataPath + path + "/" + Selection.activeGameObject.name + ".cs"))
{
sw.Write(data);
sw.Dispose();
sw.Close();
Debug.Log("生成完成");
AssetDatabase.Refresh();
}
}
catch (Exception e)
{
Debug.LogError("文件路径异常:" + e);
}
}
}
/// <summary>
/// 写入引用类型字段
/// </summary>
/// <param name="builder"></param>
/// <param name="node"></param>
private void WriteQuoteField(StringBuilder builder,Transform node)
{
//命名规则:H_Info_Text 标识符_ui名字_组件类名
string[] t = node.name.Split("_");
if (t[0] == discern)
{
builder.Append("\t" + "private " + t[t.Length - 1] + " " + node.name.TrimStart(new char[]{ 'H', '_' }) + ";\n");
}
for(int i = 0; i < node.childCount; i++)
{
WriteQuoteField(builder, node.GetChild(i));
}
}
private void WriteCustomFiled(StringBuilder builder,string typeName="BasePanel")
{
}
/// <summary>
/// 写入重写方法
/// </summary>
/// <param name="builder"></param>
/// <param name="typeName"></param>
private void WriteRewriteMethod(StringBuilder builder, string typeName = "BasePanel")
{
//Type type =Type.GetType(typeName);
Type type = typeof(BasePanel);
BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public|BindingFlags.Instance|BindingFlags.DeclaredOnly;
MethodInfo[] meths= type.GetMethods(flags);
Debug.Log(meths.Length);
for(int i = 0; i < meths.Length; i++)
{
//如果是可重写的
if (meths[i].IsVirtual && meths[i].ReturnType.Name=="Void")
{
if (meths[i].IsPrivate)
{
builder.Append("\t" + "private override " + meths[i].ReturnType.Name.ToLower() + " "
+ meths[i].Name + "()\n\t{\n\t\t" + "base." + meths[i].Name + "();\n\t}\n");
}
else if(meths[i].IsFamily)
{
builder.Append("\t" + "protected override " + meths[i].ReturnType.Name.ToLower() + " "
+ meths[i].Name + "()\n\t{\n\t\t" + "base." + meths[i].Name + "();\n\t}\n");
}else if (meths[i].IsPublic)
{
builder.Append("\t" + "public override " + meths[i].ReturnType.Name.ToLower() + " "
+ meths[i].Name + "()\n\t{\n\t\t" + "base." + meths[i].Name + "();\n\t}\n");
}
}
}
}
}
要注意的一点是,UI的命名要按照规则来,不然不会正确获取到组件字段。
鱼鱼的UI面板的基类里需要重写的方法里有一个协程,也没有其它返回类型的,所以加了meths[i].ReturnType.Name=="Void"的判断。