#if UNITY_EDITOR using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.Text.RegularExpressions; using System.IO; using Stary.Evo; using System; using System.Linq; using Newtonsoft.Json; using Stary.Evo.Editor; public class UICreateWindow : EditorWindow { #region MenuItem [MenuItem("Assets/Evo/UI工具/CreateUI")] private static void CopyUI() { if (Selection.activeObject == null || !(Selection.activeObject is GameObject)) { Debug.LogError("请选择UI预制体!"); return; } UICreateWindow.OpenWindow().uiPrefab = Selection.activeObject as GameObject; } [MenuItem("Evo/UI管理")] public static UICreateWindow OpenWindow() { var window = GetWindow("UI管理"); if (window == null) { window = CreateWindow("UI管理"); } window.name = "UI管理"; window.Focus(); return window; } #endregion private string _mInput; private Vector2 _scroll; private Vector2 _scroll2; private Vector2 _scroll3; private string _uiViewTemplate = "UIViewTemplate"; private string _uiConfig = "UIConfig"; private string _uiName; public GameObject uiPrefab; private Dictionary _uiNames = new Dictionary(); private Dictionary _uiJsonDatas = new Dictionary(); private bool _isWindow = true; private UILayer _layer = UILayer.NormalLayer; private IEnumerable uiViews; private string[] _domainNames; private int _domainIndex; private UIConfig _uiConfigObj; private void OnEnable() { TryGetPath(ref _uiViewTemplate, _uiViewTemplate, ".txt"); _domainNames = CreatAssetWindow.GetCreatDomainAllName(); ValueChang(); } private void ValueChang() { _uiJsonDatas.Clear(); _uiNames.Clear(); uiViews = ReflectionHelper.GetAllUIViewTypes(_domainNames[_domainIndex]); DomainPathField(); foreach (var uiView in uiViews) { string str = uiView.Name; if (str.Equals("Max")) continue; var jsonData = GetUIJson(str); //if (jsonData == null || string.IsNullOrEmpty(jsonData.path)) continue; var scriptPath = GetUIScript(str, true); _uiNames.AddOrUpdate(str, scriptPath); } } private void OnGUI() { EditorGUILayout.LabelField("通过[Evo/UI管理]可以打开"); _scroll = EditorGUILayout.BeginScrollView(_scroll); { EditorGUILayout.HelpBox("UI基础文件", MessageType.Info); { PathField("UI模板文件.txt", ref _uiViewTemplate, nameof(_uiViewTemplate), ".txt"); DomainPathField(); EditorGUILayout.ObjectField(_uiConfig, _uiConfigObj, typeof(UIConfig), true); } EditorGUILayout.Space(10); EditorGUILayout.BeginHorizontal(); { _scroll2 = EditorGUILayout.BeginScrollView(_scroll2, "box", GUILayout.Width(position.width * 0.4f - 6)); { var tempIndex =EditorGUILayout.Popup("Domain", _domainIndex, _domainNames); if (tempIndex != _domainIndex) { ValueChang(); _domainIndex = tempIndex; } EditorGUILayout.HelpBox("已创建的UI", MessageType.Info); _mInput = EditorGUILayout.TextField(_mInput, EditorStyles.toolbarSearchField, GUILayout.Height(20)); foreach (var uiView in uiViews) { string str = uiView.Name; if (str.Equals("Max")) continue; if (!string.IsNullOrEmpty(_mInput) && !str.Contains(_mInput)) continue; var jsonData = GetUIJson(str); var scriptPath = GetUIScript(str); if (jsonData == null) { jsonData = new UIConfigJson(); } if (string.IsNullOrEmpty(scriptPath)) continue; var defaultColor = GUI.color; if (str.Equals(_uiName)) { GUI.color = Color.yellow; } EditorGUILayout.BeginHorizontal("box"); if (GUILayout.Button("选中")) { uiPrefab = AssetDatabase.LoadAssetAtPath(jsonData.path); } EditorGUILayout.ObjectField(AssetDatabase.LoadAssetAtPath(jsonData.path), typeof(GameObject), true); EditorGUILayout.ObjectField(AssetDatabase.LoadAssetAtPath(scriptPath), typeof(TextAsset), true); EditorGUILayout.EndHorizontal(); GUI.color = defaultColor; } } EditorGUILayout.EndScrollView(); _scroll3 = EditorGUILayout.BeginScrollView(_scroll3, "box", GUILayout.Width(position.width * 0.6f - 6)); { EditorGUILayout.HelpBox("UI操作", MessageType.Info); uiPrefab = EditorGUILayout.ObjectField("UI预制体", uiPrefab, typeof(GameObject), true) as GameObject; if (uiPrefab != null) { _uiName = uiPrefab.name; var uiScriptPath = GetUIScript(_uiName); if (string.IsNullOrEmpty(uiScriptPath)) { var saveUIPath= $"Assets/Domain/{_domainNames[_domainIndex]}/Scripts/UI"; if (GUILayout.Button($"选择创建路径:{saveUIPath}")) { var newPath = EditorUtility.OpenFolderPanel("UI生成路径", saveUIPath, ""); saveUIPath = newPath.Replace(Application.dataPath, "Assets"); } if (uiPrefab != null) { EditorGUILayout.TextField("UI生成路径", $"{saveUIPath}/{_uiName}.cs"); } _isWindow = EditorGUILayout.Toggle("是否为窗口", _isWindow); _layer = (UILayer)EditorGUILayout.EnumPopup("UILayer设置", _layer); var defaultColor = GUI.color; GUI.color = Color.green; if (GUILayout.Button("创建UI")) { // 生成代码 string str = Regex.Replace(File.ReadAllText(_uiViewTemplate), "UIXXXView", _uiName); UIControlData uiControlData = uiPrefab.GetComponent(); if (uiControlData != null) { uiControlData.CopyCodeToClipBoardPrivate(); } str = Regex.Replace(str, "//UIControlData", uiControlData != null ? UnityEngine.GUIUtility.systemCopyBuffer : ""); string newPath = $"{saveUIPath}/{_uiName}.cs"; File.WriteAllText(newPath, str); var jsonData = new UIConfigJson { uiType = _uiName, pathId = $"Prefabs_{uiPrefab.name}", path = AssetDatabase.GetAssetPath(uiPrefab), isWindow = _isWindow, uiLayer = _layer, }; _uiJsonDatas.Add(_uiName, jsonData); _uiNames.Add(_uiName, newPath); SaveJson(); // 生成UIType // var newStr = Regex.Replace(File.ReadAllText(_uiType), "Max,", $"{_uiName},\n\t\tMax,"); // File.Delete(_uiType); // File.WriteAllText(_uiType, newStr); // // Debug.Log("生成成功:" + newPath); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } GUI.color = defaultColor; } else { var jsonData = GetUIJson(_uiName); if (jsonData == null) { jsonData = new UIConfigJson(); jsonData.uiType = _uiName; _uiJsonDatas.AddOrUpdate(_uiName, jsonData); } if (UnityEditor.PrefabUtility.IsPartOfPrefabAsset(uiPrefab)) { // 预制体资源就是自身 jsonData.pathId = $"Prefabs_{uiPrefab.name}"; jsonData.path = UnityEditor.AssetDatabase.GetAssetPath(uiPrefab); } EditorGUILayout.ObjectField("已创建脚本", AssetDatabase.LoadAssetAtPath(uiScriptPath, typeof(TextAsset)), typeof(TextAsset), true); jsonData.isWindow = EditorGUILayout.Toggle("是否为窗口", jsonData.isWindow); jsonData.uiLayer = (UILayer)EditorGUILayout.EnumPopup("UILayer设置", jsonData.uiLayer); var defaultColor = GUI.color; GUI.color = Color.green; if (GUILayout.Button("保存设置")) { SaveJson(); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } GUI.color = defaultColor; GUI.color = Color.red; if (GUILayout.Button("删除UI脚本")) { if (EditorUtility.DisplayDialog("是否确认删除", $"请确认是否删除:\n{uiScriptPath}\n同时会清除Json,UIType中相关数据", "确定", "取消")) { // 清除UIConfig中的指定类型 _uiJsonDatas.Remove(_uiName); _uiNames.Remove(_uiName); SaveJson(); // 删除文件 File.Delete(uiScriptPath); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); _uiNames.Remove(_uiName); } } GUI.color = defaultColor; } } else { _uiName = ""; } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); } private void SaveJson() { List list = new List(); foreach (var name in _uiNames.Keys) { if (_uiJsonDatas.TryGetValue(name, out var data)) { list.Add(data); } } _uiConfigObj.uiConfigJsons.Clear(); _uiConfigObj.uiConfigJsons = list; EditorUtility.SetDirty(_uiConfigObj); AssetDatabase.SaveAssets(); } private void TryGetPath(ref string path, string pathName, string endsWith) { path = PlayerPrefs.GetString(pathName); if (!File.Exists(path)) { string[] ids = AssetDatabase.FindAssets(pathName); if (ids != null) { foreach (var id in ids) { var str = AssetDatabase.GUIDToAssetPath(id); if (str.EndsWith(endsWith)) { path = str; } } } } } private string GetUIScript(string name, bool tryFind = false) { if (_uiNames.TryGetValue(name, out string path)) { return path; } if (!tryFind) { return string.Empty; } // if (GetUIJson(name) == null) return string.Empty; string[] ids = AssetDatabase.FindAssets(name); if (ids != null) { foreach (var id in ids) { var str = AssetDatabase.GUIDToAssetPath(id); if (str.EndsWith(".cs")) { return str; } } } return string.Empty; } private UIConfigJson GetUIJson(string name) { if (_uiJsonDatas.Count == 0) { try { foreach (var item in _uiConfigObj.uiConfigJsons) { _uiJsonDatas.AddOrUpdate(item.uiType, item); } } catch (Exception e) { Debug.LogError(e); } } if (_uiJsonDatas.TryGetValue(name, out var jsonData)) { return jsonData; } return null; } private void DomainPathField() { var path = $"Assets/Domain/{_domainNames[_domainIndex]}/AddressableRes/Config/UIConfig.asset"; if (_uiConfigObj == null) { _uiConfigObj = (UIConfig)AssetDatabase.LoadAssetAtPath(path, typeof(UIConfig)); } if (_uiConfigObj == null) { Debug.LogError($"在{path}中未找到UIConfig"); return; } } private void PathField(string name, ref string path, string pathName, string endsWith) { var obj = EditorGUILayout.ObjectField(name, AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset)), typeof(TextAsset), true); if (obj != null) { var newPath = AssetDatabase.GetAssetPath(obj); if (newPath.EndsWith(endsWith) && !newPath.Equals(path)) { path = newPath; PlayerPrefs.SetString(pathName, path); } } } } #endif static class ReflectionHelper { public static IEnumerable CreateAllInstancesOf() { return typeof(ReflectionHelper).Assembly.GetTypes() //获取当前类库下所有类型 .Where(t => typeof(T).IsAssignableFrom(t)) //获取间接或直接继承t的所有类型 .Where(t => !t.IsAbstract && t.IsClass) //获取非抽象类 排除接口继承 .Select(t => (T)Activator.CreateInstance(t)); //创造实例,并返回结果(项目需求,可删除) } // 新增方法:专门用于查找UIView类型的所有实现类 public static IEnumerable GetAllUIViewTypes(string domainName) { // 查找所有程序集中的UIView类型实现 var uiviewType = typeof(UIView); List result = new List(); // 尝试获取指定名称的程序集 var targetAssembly = AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(assembly => assembly.GetName().Name == $"HotUpdate_{domainName}"); if (targetAssembly == null) { Debug.LogError($"未找到名为HotUpdate_{domainName}的程序集"); return null; } try { result.AddRange(targetAssembly.GetTypes() .Where(t => uiviewType.IsAssignableFrom(t)) .Where(t => !t.IsAbstract && t.IsClass)); } catch (Exception) { // 忽略无法访问的程序集 } // 遍历所有已加载的程序集 // foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) // { // try // { // result.AddRange(assembly.GetTypes() // .Where(t => uiviewType.IsAssignableFrom(t)) // .Where(t => !t.IsAbstract && t.IsClass)); // } // catch (Exception) // { // // 忽略无法访问的程序集 // } // } return result; } }