利用编辑器实现UIPanel脚本的自动创建和写入字段,重写方法

书接上集,在完成了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"的判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值