TheInitialProject/Assets/Scripts/Editor/UIExportTool.cs
2024-10-23 16:59:02 +08:00

515 lines
16 KiB
C#

/*
--- 创建人: zjy
--- 描 述: 导出UI控制脚本. UI控件需要安装标准命名
*/
using System;
using System.Collections.Generic;
//using System.Globalization;
//using System.Text.RegularExpressions;
using System.IO;
using System.Text;
using TMPro;
using Unity.Plastic.Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
public class GoInfo
{
public string AllPath;
public string TypeName; //类型名称
public string FullName; //全名
public GameObject go;
}
public class UIExportTool : Editor
{
public static string ScriptName;
public static string ScriptDir;
public static string UIScriptRootPath = UnityEngine.Application.dataPath + "/Scripts/UI"; // UI 脚本生成根目录
public static readonly string UIPrefabRootPath = "Assets/GameAssets/Prefabs/UI"; // UI Prefab根目录
public static readonly string UIPathConfigFile = "Assets/GameAssets/TextAssets/UIMgrPath.json"; // UI Prefab资源路径文件名
/// <summary>
/// 在Project下右键创建
/// </summary>
[MenuItem("Assets/创建UI脚本", false, -99)]
public static void ProCreateLua()
{
string allPath = AssetDatabase.GetAssetPath(Selection.activeGameObject);
//先替换成lua后缀
allPath = allPath.Replace(".prefab", ".cs");
string[] patharr = allPath.Split('/');
if (patharr.Length > 2)
{
//固定路径
ScriptDir = UIScriptRootPath + "/" + patharr[patharr.Length - 2];
ScriptName = patharr[patharr.Length - 1];
}
Debug.Log("开始生成:" + ScriptDir + "/" + ScriptName);
OnCreateBehaviour(Selection.activeGameObject.transform);
}
public static void OnCreateBehaviour(Transform ptf)
{
if (string.IsNullOrEmpty(ScriptName))
{
Debug.LogWarning("OnCreateBehaviour. string.IsNullOrEmpty(ScriptName). 先把设置文件名");
return;
}
List<GoInfo> objs = new List<GoInfo>();
foreach (var tf in ptf.GetComponentsInChildren<Transform>(true))
{
if (tf == ptf)
{
continue;
}
string goname = tf.gameObject.name;
// Debug.Log(allPath);
GoInfo goinfo = new GoInfo();
goinfo.go = tf.gameObject;
goinfo.AllPath = GetAllPath(tf, ptf);
if (ComponentCanGrae(goname, tf, goinfo))
{
objs.Add(goinfo);
}
}
if (objs.Count == 0)
{
Debug.LogError("UI命名不规范|未找到需要导出的控件. 请自行创建");
return;
}
if (!Directory.Exists(ScriptDir))
{
Directory.CreateDirectory(ScriptDir);
}
string filePath = ScriptDir + "/" + ScriptName;
Debug.Log("导出目录 filePath:" + filePath);
if (!File.Exists(filePath))
{
CreateFile(objs);
Debug.Log("导出成功 filePath:" + filePath);
ExportUIPath();
return;
}
//文件存在替换文件
ReplaceFile(objs);
}
/// <summary>
/// 文件不存在的时候创建文件
/// </summary>
/// <param name="objs"></param>
private static void CreateFile(List<GoInfo> objs)
{
// Debug.Log("创建脚本");
UIExportTextBuilder bs = new UIExportTextBuilder(objs, Selection.activeGameObject.name);
bs.BuildFileAllStr();
byte[] buf = Encoding.UTF8.GetBytes(bs.AllStr.ToString());
File.WriteAllBytes(bs.filePath, buf);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log("创建脚本完成. 路径:" + bs.filePath);
}
/// <summary>
/// 文件存在的时候替换文件
/// </summary>
/// <param name="objs"></param>
private static void ReplaceFile(List<GoInfo> objs)
{
//Debug.Log("已有文本");
UIExportTextBuilder bs = new UIExportTextBuilder(objs, ScriptName);
bs.ReplaceFile();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log("已替换旧文件标签内内容. filePath:" + bs.filePath);
}
public static string GetAllPath(Transform tf, Transform ptf)
{
string name = tf.gameObject.name;
Transform temp = tf.parent;
while (temp != null && temp != ptf)
{
name = temp.name + "/" + name;
temp = temp.parent;
}
return name;
}
// TestUI // 界面预制体
// TestUI.lua.txt // 界面脚本
// TestUnit // 界面单元格
// TestUnit.lua.txt // 界面单元格脚本
// TestCtrl // 预制体
// TestCtrl.lua.txt // 预制体控制脚本
//
// UI控件简写
// Text: txtTest // 文本
// Text: txtTest // 文本
// Image: imgTest // 精灵图片
// RawImage: rimgTest // 大图
// Button: btnTest // 按钮
// InputField: iptTest // 输入框
// Transform: tfTest // 坐标变幻
// RectTransform: rtfTest // 坐标变幻
// GameObject: goTest // 对象
// Panel: plTest // 面板,容器
// ScrollView|ScrollRect: svTest // 滑动列表
// SupperScrollView: ssvTest // 超级滑动列表
// Toggle: tglTest // 选择框
// ToggleGroup: tglgTest // 选择组
// Slider: sldTest // 滑动条
// Dropdown: ddTest // 下拉选择框
// UIInputNumChange: numc //数字变化组件
// TextMeshProUGUI: 例如 tmpTest //TMP文本 tmp
// TMP_InputField: 例如 tiptTest //TMP文本输入框 tipt
// TMP_Dropdown: 例如 tddTest //TMP下拉框
// UICurBgLeft: uibglTest //标题居左大
// UICurBgMiddle: uibgmTest //标题居中大
// UICurBgFullScreen: uibgfTest //全屏
// UICurBgSmall: uibgsTest //标题居中小
// UICurBgMiddle: uibgmtTest //弹窗
// UIRoleRawImage: rriTest // 角色模型
// UIItemIconList: iilTest // 道具列表
public static bool ComponentCanGrae(string goname, Transform tf, GoInfo goinfo)
{
if (goname.StartsWith("tf"))
{
TipHasComponent<Transform>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("rtf"))
{
TipHasComponent<RectTransform>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("go"))
{
TipHasComponent<GameObject>(goname, tf, goinfo);
goinfo.TypeName = "GameObject";
return true;
}
if (goname.StartsWith("pl"))
{
TipHasComponent<Image>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("sv"))
{
TipHasComponent<ScrollRect>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("rimg"))
{
TipHasComponent<RawImage>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("img"))
{
TipHasComponent<Image>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("tglg"))
{
TipHasComponent<ToggleGroup>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("tgl"))
{
TipHasComponent<Toggle>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("sld"))
{
TipHasComponent<Slider>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("sclb"))
{
TipHasComponent<Scrollbar>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("txt"))
{
TipHasComponent<Text>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("btn"))
{
TipHasComponent<Button>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("ipt"))
{
TipHasComponent<InputField>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("dd"))
{
TipHasComponent<Dropdown>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("numc"))
{
TipHasComponent<UIInputNumChange>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("tmp"))
{
TipHasComponent<TextMeshProUGUI>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("tipt"))
{
TipHasComponent<TMP_InputField>(goname, tf, goinfo);
return true;
}
if (goname.StartsWith("tdd"))
{
TipHasComponent<TMP_Dropdown>(goname, tf, goinfo);
return true;
}
//if (goname.StartsWith("uibgl"))
//{
// TipHasComponent<UICurBgLeft>(goname, tf, goinfo);
// return true;
//}
//if (goname.StartsWith("uibgm"))
//{
// TipHasComponent<UICurBgMiddle>(goname, tf, goinfo);
// return true;
//}
//if (goname.StartsWith("uibgf"))
//{
// TipHasComponent<UICurBgFullScreen>(goname, tf, goinfo);
// return true;
//}
//if (goname.StartsWith("uibgs"))
//{
// TipHasComponent<UICurBgSmall>(goname, tf, goinfo);
// return true;
//}
//if (goname.StartsWith("uibgmt"))
//{
// TipHasComponent<UICurBgMiddle>(goname, tf, goinfo);
// return true;
//}
//if (goname.StartsWith("rri"))
//{
// TipHasComponent<UIRoleRawImage>(goname, tf, goinfo);
// return true;
//}
//if (goname.StartsWith("iil"))
//{
// TipHasComponent<UIItemIconList>(goname, tf, goinfo);
// return true;
//}
return false;
}
public static void TipHasComponent<T>(string goname, Transform tf, GoInfo goinfo)
{
Type t = typeof(T);
if (tf.GetComponent<T>() == null)
{
Debug.LogErrorFormat("{0} 缺少 {1}", goname, t.Name);
}
goinfo.TypeName = t.Name;
goinfo.FullName = t.FullName;
}
[MenuItem("UI工具/生成UI预制体路径文件")]
public static void ExportUIPath()
{
Debug.Log("生成UI预制体路径 开始");
if (!Directory.Exists(UIPrefabRootPath))
Directory.CreateDirectory(UIPrefabRootPath);
//if (!Directory.Exists(UIMgr.UIPathConfigPath))
// Directory.CreateDirectory(UIMgr.UIPathConfigPath);
LoadScriptableObject();
Debug.Log(string.Format("<color=#{0}>{1}</color>", "00FF00", "生成UI预制体路径 完成"));
}
//private static void LoadScriptableObject()
//{
// var objs = EditorCommonAPI.LoadAllAssetsInAllPath<GameObject>(UIMgr.UIPrefabRootPath);
// if (objs == null)
// {
// Debug.LogError("未找到UI预制体, 根目录:" + UIMgr.UIPrefabRootPath);
// return;
// }
// string assetsFile = UIMgr.UIPathConfigFile;
// //如果文件存在, 直接移除
// AssetDatabase.DeleteAsset(assetsFile);
// AssetDatabase.Refresh();
// Debug.Log("UI预制体总数:" + objs.Count);
// // 找出所有 'UI' | 'Unit' 结尾的prefab
// List<GameObject> uis = new List<GameObject>();
// Dictionary<string, string> mUIToPathDic = new Dictionary<string, string>();
// foreach (var prefab in objs)
// {
// if (prefab.name.EndsWith("UI") || prefab.name.EndsWith("Unit"))
// {
// Debug.Log("" + prefab.name + ". path:" + PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab));
// string aPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab); // 绝对路径
// if (!aPath.EndsWith(".prefab"))
// {
// Debug.LogError("导出UI路径, 对象不是预制体. path:" + aPath);
// continue;
// }
// string rPath = aPath;
// uis.Add(prefab);
// mUIToPathDic.Add(prefab.name, rPath);
// }
// }
// UIMgrPath dataFile = AssetDatabase.LoadAssetAtPath<UIMgrPath>(assetsFile);
// if (dataFile != null)
// {// 有配置文件
// dataFile.mAllUIPath.Clear();
// foreach (var vPair in mUIToPathDic)
// {
// UIMgrPath.UIPath temp1 = new UIMgrPath.UIPath();
// temp1.mUIName = vPair.Key;
// temp1.mUIPath = vPair.Value;
// dataFile.mAllUIPath.Add(temp1);
// }
// }
// else
// {
// dataFile = CreateInstance<UIMgrPath>();// 创建配置文件
// dataFile.mAllUIPath.Clear();
// foreach (var vPair in mUIToPathDic)
// {
// UIMgrPath.UIPath temp1 = new UIMgrPath.UIPath();
// temp1.mUIName = vPair.Key;
// temp1.mUIPath = vPair.Value;
// dataFile.mAllUIPath.Add(temp1);
// }
// AssetDatabase.DeleteAsset(assetsFile);
// AssetDatabase.CreateAsset(dataFile, assetsFile);// 生成资源到指定路径
// }
// Debug.Log("更新了UI路径:assetsPath:" + assetsFile);
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
//}
private static void LoadScriptableObject()
{
var objs = EditorCommonAPI.LoadAllAssetsInAllPath<GameObject>(UIPrefabRootPath);
if (objs == null)
{
Debug.LogError("未找到UI预制体, 根目录:" + UIPrefabRootPath);
return;
}
string assetsFile = Application.dataPath.Replace("/Assets", "/") + UIPathConfigFile;
if (!File.Exists(assetsFile))
{
var sw = File.CreateText(assetsFile);
sw.Close();
}
if (!File.Exists(assetsFile))
{
Debug.LogError("LoadScriptableObject. !File.Exists(assetsFile). assetsFile:" + assetsFile);
return;
}
Debug.Log("UI预制体总数:" + objs.Count);
// 找出所有 'UI' | 'Unit' 结尾的prefab
List<GameObject> uis = new List<GameObject>();
Dictionary<string, string> mUIToPathDic = new Dictionary<string, string>();
foreach (var prefab in objs)
{
if (prefab.name.EndsWith("UI")
|| prefab.name.EndsWith("Page")
|| prefab.name.EndsWith("Unit")
//|| prefab.name.EndsWith("Ctrl")
)
{
Debug.Log("" + prefab.name + ". path:" + PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab));
string aPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefab); // 绝对路径
if (!aPath.EndsWith(".prefab"))
{
Debug.LogError("导出UI路径, 对象不是预制体. path:" + aPath);
continue;
}
string rPath = aPath;
uis.Add(prefab);
mUIToPathDic.Add(prefab.name, rPath);
}
}
string json = CaoCao.LitJson.JsonMapper.ToJson(mUIToPathDic);
File.WriteAllText(assetsFile, JObject.Parse(json).ToString());
Debug.Log("更新了UI路径:assetsPath:" + assetsFile);
}
}