using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using TyphoonFormatCSharp; using UnityEditor; using UnityEngine; using Debug = UnityEngine.Debug; namespace TyphoonUI { public class CodeTool { //最大备份数量 public const int MAX_BACK_UP_SIZE = 10; /// /// 导出所有代码 /// [MenuItem("TyphoonUI/代码导出/导出所有", priority = 5000)] public static void ExportAll() { //备份当前代码目录 BackUpAllCodeScripts(); var guids = AssetDatabase.FindAssets("t:prefab", new[] { "Assets" }); var matches = new HashSet(); foreach (var guid in guids) { var path = AssetDatabase.GUIDToAssetPath(guid); var prefab = AssetDatabase.LoadAssetAtPath(path); if (prefab != null) { var objs = GetUIObjectsInChildren(prefab); foreach (var element in objs) { matches.Add(element); } } } var sb = new StringBuilder(); var validate = new HashSet(); foreach (var match in matches) { var current = PrefabUtility.GetCorrespondingObjectFromSource(match.gameObject); var corresponding = PrefabUtility.GetCorrespondingObjectFromOriginalSource(match.gameObject); if (current != null && corresponding != null) { //不属于原始节点,跳过 continue; } validate.Add(match); var sourcePath = AssetDatabase.GetAssetPath(match); sb.AppendLine($"{sourcePath} -> {match.gameObject.GetHierarchyPath()}"); // sb.AppendLine($"[{current}],[{corresponding}]"); } Debug.Log(sb.ToString()); //检查导出节点是否出现问题 foreach (var element in validate) { if (element.HasNullNode()) { Debug.Log($"{element}存在空节点,已自动处理"); var original = PrefabUtility.GetCorrespondingObjectFromOriginalSource(element); original.Apply(); EditorUtility.SetDirty(original); var path = AssetDatabase.GetAssetPath(original); EditorUtility.SetDirty(AssetDatabase.LoadAssetAtPath(path)); AssetDatabase.SaveAssets(); } } //导出所有代码 ExportCode(true, validate.ToArray()); } /// /// 导出代码(多项导出) /// public static List ExportCode(bool refreshProj, params UIObject[] objs) { var arr = new List(); foreach (var view in objs) { arr.Add(new ViewCodeGenerator(view)); view.Apply(); } //分析导出 foreach (var element in arr) { element.Analysis(); //生成成员和初始化方法 element.GenerateMethodInitializeView(); } //生成类型清单 var classFullNames = new HashSet(); foreach (var generator in arr) { classFullNames.Add(generator.GetFullClassName()); } //补充关联view拓展属性 foreach (var element in arr) { element.GenerateViewPropertyField(classFullNames); } var result = new List(); //生成代码 foreach (var element in arr) { var code = element.GenerateCodeSting(); var savePath = element.GetSavePath(); result.Add(savePath); TyphoonUIEditor.CreateDirectoryIfNotExist(Path.GetDirectoryName(savePath)); File.WriteAllText(savePath, code); } Debug.Log($"生成完毕,共:{result.Count}项"); if (result.Count > 0) { AssetDatabase.Refresh(); TyphoonUIEditor.PingObject(result.Last()); FormatCSharp.Format(Paths.ExportCodeFolder, () => { if (refreshProj) { AssetDatabase.Refresh(); } }); } return result; } /// /// 单项导出 /// public static string ExportCode(UIObject obj, bool refreshProj) { obj.Apply(); var codeGenerator = new ViewCodeGenerator(obj); codeGenerator.Analysis(); codeGenerator.GenerateMethodInitializeView(); codeGenerator.GenerateViewPropertyField(new HashSet()); var code = codeGenerator.GenerateCodeSting(); var path = codeGenerator.GetSavePath(); TyphoonUIEditor.CreateDirectoryIfNotExist(Path.GetDirectoryName(path)); Debug.Log($"导出:{path}"); File.WriteAllText(path, code); if (refreshProj) { AssetDatabase.Refresh(); } return path; } /// /// 获取所有子Transform /// public static List GetTransformInChildren(GameObject parent) { List childNodes = new List(); childNodes.Add(parent.transform); // 获取父节点的所有子节点 foreach (Transform child in parent.transform) { // 递归获取子节点的所有子节点 var grandChildNodes = GetTransformInChildren(child.gameObject); childNodes.AddRange(grandChildNodes); } return childNodes; } /// /// 获取所有UIObject /// public static List GetUIObjectsInChildren(GameObject obj) { var nodes = GetTransformInChildren(obj); var hash = new HashSet(); foreach (var node in nodes) { var com = node.GetComponent(); if (com != null) { hash.Add(com); } } return hash.ToList(); } //备份所有代码 public static void BackUpAllCodeScripts() { if (Directory.Exists(Paths.CodeScriptBackUpFolder)) { //删除多余的备份文件夹 var info = new DirectoryInfo(Paths.CodeScriptBackUpFolder); var backups = info.GetDirectories().ToList(); if (backups.Count >= MAX_BACK_UP_SIZE) { var deleteCount = backups.Count - MAX_BACK_UP_SIZE + 1; //删除最早的备份 backups.Sort((a, b) => { return a.CreationTime.CompareTo(b.CreationTime); }); for (int i = 0; i < deleteCount && i < backups.Count; i++) { var element = backups[i]; Directory.Delete(element.FullName, true); } } } var backup = $"{Paths.CodeScriptBackUpFolder}/{DateTime.Now.ToString("yyyyMMdd-HHmmssfff")}"; TyphoonUIEditor.CreateDirectoryIfNotExist(backup); var from = Paths.ExportCodeFolder; if (Directory.Exists(from)) { var info = new DirectoryInfo(from); var files = info.GetFiles("*", SearchOption.AllDirectories); foreach (var element in files) { var fileFrom = element.FullName; var fileTo = element.FullName.Replace(info.FullName, backup); var dir = Path.GetDirectoryName(fileTo); TyphoonUIEditor.CreateDirectoryIfNotExist(dir); File.Copy(fileFrom, fileTo, true); } } Debug.Log($"备份{from}-->{backup}"); } [MenuItem("TyphoonUI/代码导出/查看备份", priority = 5000)] public static void OpenCodeBackFolder() { if (Directory.Exists(Paths.ExportCodeFolder)) { Process.Start($"explorer", $"\"{Path.GetFullPath(Paths.CodeScriptBackUpFolder)}\""); } else { Debug.Log("备份目录为空"); } } } }