using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using Random = System.Random;
public class UIExportTextBuilder
{
public static string nstr = "\n";
Random random = new Random(Guid.NewGuid().GetHashCode());
public string scripthead =
@"/*-------------------------------------------------------------------------------------
--- 创建人:
--- 描 述:
--- 创建时间: {0}
-------------------------------------------------------------------------------------*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using CaoCao.Runtime;
namespace Game.HotFix
{{
///
/// xx 功能界面
///
public class {1} : {2}
";
public string filePath = UIExportTool.ScriptDir + "/" + UIExportTool.ScriptName;
private static readonly string TagUICtrlDefine = "//UIAutoBuild_CtrlDefine";
private static readonly string TagUICtrlBind = "//UIAutoBuild_CtrlBind";
private static readonly string TagUIEventReg = "//UIAutoBuild_EventReg";
private static readonly string TagUIEventUnReg = "//UIAutoBuild_EventUnReg";
//这是注册控件的方法
public StringBuilder uiElementSB = new StringBuilder();
public StringBuilder onAwake = new StringBuilder();
public StringBuilder onStart = new StringBuilder();
public StringBuilder onEnable = new StringBuilder();
public StringBuilder onDisable = new StringBuilder();
public StringBuilder onShow = new StringBuilder();
//public StringBuilder onDestroy = new StringBuilder();
//移除按钮点击事件
public StringBuilder btnClickRemove = new StringBuilder();
//按钮添加事件
public StringBuilder btnClickAdd = new StringBuilder();
public StringBuilder btnClickFun = new StringBuilder();
//toggle 移除事件
public StringBuilder tglRemove = new StringBuilder();
//toggle 添加事件
public StringBuilder tglAdd = new StringBuilder();
//toggle 方法
public StringBuilder tglfun = new StringBuilder();
//重名检查
public Dictionary nameCheck = new Dictionary();
//全部字符串
public StringBuilder AllStr = new StringBuilder();
public bool hasBtn = false;
public bool hasToggle = false;
private List objs;
private string buildFileName = string.Empty;
private bool isUI = true;
public UIExportTextBuilder(List objs, string fileName)
{
this.objs = objs;
buildFileName = fileName;
scripthead = scripthead.Replace("\r\n", "\n");
if (fileName.Contains("Unit"))
{
isUI = false;
scripthead = string.Format(scripthead, DateTime.Now.ToLongDateString(), fileName, "MonoBehaviour");
}
else
{
isUI = true;
scripthead = string.Format(scripthead, DateTime.Now.ToLongDateString(), fileName, "UIBase");
}
scripthead += "{\n";
//scripthead += "\toverride public string UIFolder\n";
//scripthead += "\t{\n";
//string[] strAry = UIExportTool.ScriptDir.Split('/');
//string floder = strAry[strAry.Length - 1];
//scripthead += "\t\tget { return \"" + floder + "\"; }\n";
//scripthead += "\t}\n\n";
}
///
/// 生成单个大写随机字母
///
private string createBigAbc()
{
//A-Z的 ASCII值为65-90
int num = random.Next(65, 91);
string abc = Convert.ToChar(num).ToString();
return abc;
}
///
/// 生成单个小写随机字母
///
private string createSmallAbc()
{
//a-z的 ASCII值为97-122
int num = random.Next(97, 123);
string abc = Convert.ToChar(num).ToString();
return abc;
}
//检查名字是否重名
public bool CheckNameIsRepeat()
{
bool isrepeat = false;
string oldallPath = "";
for (var i = 0; i < objs.Count; i++)
{
GoInfo info = objs[i];
string goNewName = info.go.name;
GoInfo exsistInfo;
if (nameCheck.TryGetValue(goNewName, out exsistInfo))
{
info.go.name = info.go.name + "_" + createSmallAbc();
goNewName = info.go.name;
oldallPath = info.AllPath;
info.AllPath = UIExportTool.GetAllPath(info.go.transform, info.go.transform.parent);
Debug.LogErrorFormat("路径 {0} 与 路径 {1} 子物体重名 已经换成 {2} ", exsistInfo.AllPath, oldallPath, info.AllPath);
isrepeat = true;
}
nameCheck[goNewName] = info;
}
return isrepeat;
}
public void BuildFileAllStr()
{
try
{
//TODO 选择一种方式是重名还是让其自己修改
// if (CheckNameIsRepeate())
// {
// return "";
// }
if (CheckNameIsRepeat())
{
}
BuildUIElement(uiElementSB);
BuildFunction(onAwake, "Awake");
BuildFunction(onStart, "Start");
BuildFunction(onEnable, "OnEnable");
BuildFunction(onDisable, "OnDisable");
BuildFunction(onShow, "Show");
//BuildFunction(onDestroy, "OnDestroy");
onAwake.AppendLine("\t\t" + TagUICtrlBind);
if(isUI)
onAwake.Append("\t\tbase.Awake();\n");
onAwake.Append("\t\tTransform tf = transform;\n");
//检测是否有按钮
CheckHasBtn(objs);
for (var i = 0; i < objs.Count; i++)
{
GoInfo info = objs[i];
if (info.go.name.Equals("btnClose"))
continue;
onAwake.Append(GetFindStr(info));
//button 注册
if (info.TypeName.Equals("Button"))
{
//驼峰命名方法
string goNewName = FirstLetterToUpper(info.go.name);
string funName = string.Format("On{0}Click", goNewName);
btnClickAdd.Append(string.Format("\t\t{0}.onClick.AddListener({1});\n", info.go.name, funName));
btnClickRemove.Append(string.Format("\t\t{0}.onClick.RemoveAllListeners();\n", info.go.name));
btnClickFun.Append(nstr);
btnClickFun.Append(string.Format("\tprivate void {0}()\n", funName));
btnClickFun.Append("\t{\n");
AddFunctionEnd(btnClickFun);
}
if (info.TypeName.Equals("Toggle"))
{
//驼峰命名方法
string goNewName = FirstLetterToUpper(info.go.name);
string funName = string.Format("On{0}Change", goNewName);
tglAdd.Append(
string.Format("\t\t{0}.onValueChanged.AddListener({1});\n", info.go.name, funName));
tglRemove.Append(string.Format("\t\t{0}.onValueChanged.RemoveAllListeners();\n", info.go.name));
tglfun.Append(nstr);
tglfun.Append(string.Format("\tprivate void {0}(bool _isOn)\n", funName));
tglfun.Append("\t{\n");
AddFunctionEnd(tglfun);
}
}
onAwake.AppendLine("\t\t" + TagUICtrlBind);
AddFunctionEnd(onAwake);
onEnable.AppendLine("\t\t" + TagUIEventReg);
onEnable.Append(btnClickAdd);
onEnable.Append(tglAdd);
onEnable.AppendLine("\t\t" + TagUIEventReg);
AddFunctionEnd(onEnable);
onDisable.AppendLine("\t\t" + TagUIEventUnReg);
onDisable.Append(btnClickRemove);
onDisable.Append(tglRemove);
onDisable.AppendLine("\t\t" + TagUIEventUnReg);
AddFunctionEnd(onDisable);
AddFunctionEnd(onStart);
AddFunctionEnd(onShow);
//AddFunctionEnd(onDestroy);
AllStr.Append(scripthead);
AllStr.Append(uiElementSB);
AllStr.Append(onAwake);
AllStr.Append(onEnable);
AllStr.Append(onDisable);
if (isUI)
{
AllStr.Append(onStart);
AllStr.Append(onShow);
}
//AllStr.Append(onDestroy);
if (hasBtn) // 有按钮才处理
{
AllStr.Append(btnClickFun);
}
if (hasToggle)
{
AllStr.Append(tglfun);
}
AllStr.Append("\n}\n}\n");
}
catch (Exception e)
{
Debug.LogError(e);
}
}
public void BuildUIElement(StringBuilder _sb, bool hasN = true)
{
_sb.AppendLine("\t" + TagUICtrlDefine);
for (var i = 0; i < objs.Count; i++)
{
GoInfo info = objs[i];
if (info.go.name.Equals("btnClose"))
continue;
_sb.Append(GetUIElementStr(info));
}
_sb.AppendLine("\t" + TagUICtrlDefine);
_sb.Append("\n");
}
public void BuildFunction(StringBuilder funSb, string funName, bool hasN = true)
{
funSb.Append(nstr);
string tem = nstr;
if (!hasN)
{
tem = "";
}
//if(funName == "Start")
// funSb.Append("\t// 第一次打开时执行\n");
//if(funName == "Show")
// funSb.Append("\t// 每次显示都执行")
if (funName.Equals("Show"))
{
//if (buildFileName.Contains("Unit"))
if(!isUI)
{
funSb.AppendLine("\t// Show()在 Unit和page脚本中都不起作用. 删除");
funSb.Append(string.Format("\tpublic void {0}(){1}", funName, tem));
funSb.AppendLine("\t{");
}
else
{
funSb.AppendLine("\t// 每次显示都执行, 可定义参数");
funSb.Append(string.Format("\tpublic override void {0}(params object[] _params){1}", funName, tem));
funSb.AppendLine("\t{\n\t\tbase.Show(_params);\n");
}
}
else if(funName.Equals("Awake"))
{
if (isUI)
{
funSb.Append(string.Format("\tpublic override void {0}(){1}", funName, tem));
}
else
{
funSb.Append(string.Format("\tpublic void {0}(){1}", funName, tem));
}
funSb.Append("\t{\n");
}
else
{
funSb.Append(string.Format("\tvoid {0}(){1}", funName, tem));
funSb.Append("\t{\n");
}
}
public void AddFunctionEnd(StringBuilder funSb, bool hasN = false)
{
if (hasN)
funSb.Append(nstr);
funSb.Append("\t}\n");
}
private void CheckHasBtn(List objs)
{
hasBtn = false;
hasToggle = false;
for (var i = 0; i < objs.Count; i++)
{
GoInfo info = objs[i];
if (info.TypeName.Equals("Button"))
{
hasBtn = true;
}
if (info.TypeName.Equals("Toggle"))
{
hasToggle = true;
if (hasBtn)
{
break;
}
}
}
}
private string GetUIElementStr(GoInfo _info)
{
string str = "\tpublic "+ _info.TypeName + " " + _info.go.name + ";\n";
return str;
}
private string GetFindStr(GoInfo info)
{
string luaCom = ".gameObject;";
if (info.TypeName != "GameObject" && !info.TypeName.Equals("Transform"))
{
luaCom = string.Format(".GetComponent<{0}>();", info.TypeName);
}
else if (info.TypeName.Equals("Transform"))
{
luaCom = ";";
}
//把类型注释上
//string notestr = string.Format("\t{0} ", info.TypeName);
string findstr = string.Format("\t\t{0} = tf.Find(\"{1}\"){2}\n", info.go.name, info.AllPath, luaCom);
return /*notestr +*/ findstr;
}
//首字母大写
public static string FirstLetterToUpper(string str)
{
if (str == null)
return null;
if (str.Length > 1)
return char.ToUpper(str[0]) + str.Substring(1);
return str.ToUpper();
}
public void ReplaceFile()
{
byte[] buf = File.ReadAllBytes(filePath);
if (buf.Length == 0)
{
Debug.LogError("文件里没有内容");
return;
}
// 老的脚本
string oldText = Encoding.UTF8.GetString(buf);
oldText = oldText.Replace("\r\n", "\n");
// 新的脚本
BuildFileAllStr();
string newText = AllStr.ToString();
oldText = oldText.Replace("\r\n", "\n");
// 替换 控件定义
ReplaceFileCtrlText(ref oldText, newText, TagUICtrlDefine);
// 替换 控件绑定
ReplaceFileCtrlText(ref oldText, newText, TagUICtrlBind);
// 替换 注册事件
ReplaceFileCtrlText(ref oldText, newText, TagUIEventReg);
// 替换 取消事件
ReplaceFileCtrlText(ref oldText, newText, TagUIEventUnReg);
File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(oldText));
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
public string ReplaceFileCtrlText(ref string _oldText, string _newText, string _tag)
{
string oldStr = CutOutStr(_oldText, _tag, _tag);
string newStr = CutOutStr(_newText, _tag, _tag);
bool isEnmptyOld = string.IsNullOrEmpty(oldStr.Trim());
bool isEnmptyNew = string.IsNullOrEmpty(newStr.Trim());
// 两个都是空的 不需要替换
if (isEnmptyOld && isEnmptyNew)
return _oldText;
// 两个都不为空,直接替换
if (!isEnmptyOld && !isEnmptyNew)
{
_oldText = _oldText.Replace(oldStr, newStr);
return _oldText;
}
// 其中有一个为空
oldStr = string.Format("{0}{1}{2}", _tag, oldStr, _tag);
newStr = string.Format("{0}{1}{2}", _tag, newStr, _tag);
_oldText = _oldText.Replace(oldStr, newStr);
return _oldText;
}
//public void ReplaceFile()
//{
// byte[] buf = File.ReadAllBytes(filePath);
// if (buf.Length == 0)
// {
// Debug.LogError("文件里没有内容");
// return;
// }
// string oldstr = Encoding.UTF8.GetString(buf);
// oldstr = oldstr.Replace("\r\n", "\n");
// BuildFileAllStr();
// AllStr.Clear();
// int firstFun = oldstr.IndexOf("void");
// if (firstFun != -1)
// {
// string head = oldstr.Substring(0, firstFun - 1);
// AllStr.Append(head);
// //截取后面的
// oldstr = oldstr.Substring(firstFun, oldstr.Length - firstFun);
// }
// else
// {
// AllStr.Append(scripthead);
// }
// Dictionary funNode = GetFunNote(oldstr);
// string patt = @"void\s.+\(.*\)\n{(.*\n)*?}";
// // 把按钮事件拆分出来
// Dictionary clickDic =
// MctoDicFunNameKey(Regex.Matches(btnClickFun.ToString(), patt, RegexOptions.Multiline));
// // toggle
// Dictionary tglDic =
// MctoDicFunNameKey(Regex.Matches(tglfun.ToString(), patt, RegexOptions.Multiline));
// Dictionary allMc = MctoDicFunNameKey(Regex.Matches(oldstr, patt, RegexOptions.Multiline));
// bool isChange = false;
// //保证函数只检查一次,不拦截后面的 增对没有的函数
// string matkey = "void {0}()";
// string funStr;
// string newKey;
// //Awake
// newKey = string.Format(matkey, "Awake");
// if (allMc.TryGetValue(newKey, out funStr))
// {
// string oldFunstr = GetOldFunStr(funNode, newKey, funStr);
// //awake不同使用新的
// if (!oldFunstr.Equals(awakesb.ToString()))
// {
// isChange = true;
// AllStr.Append(awakesb);
// }
// else
// {
// AllStr.Append(oldFunstr);
// }
// }
// //start
// newKey = string.Format(matkey, "Start");
// if (allMc.TryGetValue(newKey, out funStr))
// {
// string oldFunstr = GetOldFunStr(funNode, newKey, funStr);
// AllStr.Append(oldFunstr);
// }
// string btnFunPatt = @"\t+btn.+onClick:.+\)\n";
// string tglFunPatt = @"\t+tgl.+onValueChanged:.+\)\n";
// newKey = string.Format(matkey, "OnEnable");
// if (allMc.TryGetValue(newKey, out funStr))
// {
// string oldFunstr = GetOldFunStr(funNode, newKey, funStr);
// //点击事件
// if (StringReplace(ref oldFunstr, btnClickAdd, btnFunPatt))
// isChange = true;
// //toggle 事件
// if (StringReplace(ref oldFunstr, tglAdd, tglFunPatt))
// isChange = true;
// AllStr.Append(oldFunstr);
// }
// newKey = string.Format(matkey, "OnDisable");
// if (allMc.TryGetValue(newKey, out funStr))
// {
// string oldFunstr = GetOldFunStr(funNode, newKey, funStr);
// //点击事件
// if (StringReplace(ref oldFunstr, btnClickRemove, btnFunPatt))
// isChange = true;
// if (StringReplace(ref oldFunstr, tglRemove, tglFunPatt))
// isChange = true;
// AllStr.Append(oldFunstr);
// }
// //newKey = string.Format(matkey, "OnDestroy");
// //if (allMc.TryGetValue(newKey, out funStr))
// //{
// // string oldFunstr = GetOldFunStr(funNode, newKey, funStr);
// // AllStr.Append(oldFunstr);
// //}
// foreach (var funNameAndFun in allMc)
// {
// if (funNameAndFun.Key.Contains("Awake")
// || funNameAndFun.Key.Contains("Start")
// || funNameAndFun.Key.Contains("OnEnable")
// || funNameAndFun.Key.Contains("OnDisable")
// //|| funNameAndFun.Key.Contains("OnDestroy")
// )
// {
// continue;
// }
// string oldFunstr = GetOldFunStr(funNode, funNameAndFun.Key, funNameAndFun.Value);
// //写回按钮老方法
// if (clickDic.ContainsKey(funNameAndFun.Key))
// {
// AllStr.Append(oldFunstr);
// continue;
// }
// //写回老方法
// if (tglDic.ContainsKey(funNameAndFun.Key))
// {
// AllStr.Append(oldFunstr);
// continue;
// }
// // 不是按钮方法的才加
// if (oldFunstr.Contains("Click") || oldFunstr.Contains("ValChange"))
// {
// continue;
// }
// //加最后面的方法
// AllStr.Append(oldFunstr);
// }
// //把以前没有的方法添加进去
// AddNewFun(clickDic, allMc, ref isChange);
// AddNewFun(tglDic, allMc, ref isChange);
// if (isChange)
// {
// File.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(AllStr.ToString()));
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// }
//}
//private static string GetOldFunStr(Dictionary funNode, string newKey, string funStr)
//{
// string node;
// if (!funNode.TryGetValue(newKey, out node))
// {
// node = nstr; //找到注释用注释,没找到使用以前的
// }
// return node + funStr + nstr + nstr;
//}
//private void AddNewFun(Dictionary funDic, Dictionary allMc, ref bool isChange)
//{
// foreach (KeyValuePair kv in funDic)
// {
// //把以前没有的按钮方法加上
// if (!allMc.ContainsKey(kv.Key))
// {
// isChange = true;
// AllStr.Append(nstr);
// AllStr.Append(kv.Value);
// AllStr.Append(nstr);
// AllStr.Append(nstr);
// }
// }
//}
////新不在旧里面加
////旧不在新里面删
/////
/////
/////
///// 以前方法的名称,后面可能还会用到所以这里传的引用进来
/////
/////
///// 改变了返回true 没改变返回false
//public bool StringReplace(ref string oldstr, StringBuilder funStr, string patt)
//{
// Dictionary oldDic = MctoDic(Regex.Matches(oldstr, patt, RegexOptions.Multiline));
// //新没有旧有就减
// Dictionary newDic = MctoDic(Regex.Matches(funStr.ToString(), patt, RegexOptions.Multiline));
// if (oldDic.Count == 0 && newDic.Count == 0)
// {
// return false;
// }
// //string newString = "";
// List adds = new List();
// List removes = new List();
// foreach (var keyValuePair in newDic)
// {
// //旧不包含新
// if (!oldDic.ContainsKey(keyValuePair.Key))
// {
// adds.Add(keyValuePair.Key);
// }
// }
// foreach (var old in oldDic)
// {
// //新不含旧删
// if (!newDic.ContainsKey(old.Key))
// {
// removes.Add(old.Key);
// }
// }
// for (int i = 0; i < removes.Count; i++)
// {
// oldstr = oldstr.Replace(removes[i], "");
// }
// if (adds.Count > 0)
// {
// int endIdex = oldstr.IndexOf("}");
// oldstr = oldstr.Substring(0, endIdex);
// for (int i = 0; i < adds.Count; i++)
// {
// oldstr += adds[i];
// }
// oldstr += "}\n\n";
// }
// return adds.Count > 0 || removes.Count > 0;
//}
//private Dictionary MctoDic(MatchCollection mc)
//{
// Dictionary dic = new Dictionary();
// for (int i = 0; i < mc.Count; i++)
// {
// string old = mc[i].ToString();
// dic[old] = old;
// }
// return dic;
//}
//private Dictionary MctoDicFunNameKey(MatchCollection mc)
//{
// Dictionary dic = new Dictionary();
// for (int i = 0; i < mc.Count; i++)
// {
// string old = mc[i].ToString();
// Match funNameMc = Regex.Match(old, @"void\s.+\(.*\)", RegexOptions.Multiline);
// dic[funNameMc.ToString()] = old;
// }
// return dic;
//}
////是否是一个函数
//public static bool IsMathFunStr(string oldFunstr, string biuldFun)
//{
// string patt = @"void\s.+\(.*\)\n";
// string matchfun = Regex.Match(oldFunstr, patt, RegexOptions.Multiline).ToString();
// return biuldFun.Equals(matchfun);
//}
////获取函数注释
//private Dictionary GetFunNote(string str)
//{
// MatchCollection mc = Regex.Matches(str, @"((---|--).*\n)+void\s.+\(.*\)", RegexOptions.Multiline);
// Dictionary dic = new Dictionary();
// for (int i = 0; i < mc.Count; i++)
// {
// string old = mc[i].ToString();
// //函数名称
// Match funNameMc = Regex.Match(old, @"void\s.+\(.*\)", RegexOptions.Multiline);
// //注释
// Match node = Regex.Match(old, @"((---|--).*\n)+", RegexOptions.Multiline);
// dic[funNameMc.ToString()] = node.ToString();
// }
// return dic;
//}
private string CutOutStr(string _res, string _startTag, string _endTag)
{
if (string.IsNullOrEmpty(_startTag))
{
Debug.LogError("string.IsNullOrEmpty(_startTag)");
return string.Empty;
}
if (string.IsNullOrEmpty(_endTag))
{
Debug.LogError("string.IsNullOrEmpty(_endTag)");
return string.Empty;
}
Regex rg = new Regex("(?<=(" + _startTag + "))[.\\s\\S]*?(?=(" + _endTag + "))"); ;
return rg.Match(_res).Value;
}
}