Files
plugin-library/Assets/06.UIFarme/Editor/UICreateWindow.cs
2025-09-24 17:16:12 +08:00

480 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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("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管理/OpenWindow")]
public static UICreateWindow OpenWindow()
{
var window = GetWindow<UICreateWindow>("UI管理");
if (window == null)
{
window = CreateWindow<UICreateWindow>("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;
private string _saveUIPath;
public GameObject uiPrefab;
private Dictionary<string, string> _uiNames = new Dictionary<string, string>();
private Dictionary<string, UIConfigJson> _uiJsonDatas = new Dictionary<string, UIConfigJson>();
private bool _isWindow = true;
private UILayer _layer = UILayer.NormalLayer;
private IEnumerable<Type> 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]);
_saveUIPath = EditorPrefs.GetString(nameof(_saveUIPath));
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<GameObject>(jsonData.path);
}
EditorGUILayout.ObjectField(AssetDatabase.LoadAssetAtPath<GameObject>(jsonData.path),
typeof(GameObject), true);
EditorGUILayout.ObjectField(AssetDatabase.LoadAssetAtPath<TextAsset>(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))
{
if (string.IsNullOrEmpty(_saveUIPath))
{
_saveUIPath = $"Assets/Domain/{_domainNames[_domainIndex]}/HotUpdate/UI";
}
if (GUILayout.Button($"选择创建路径:{_saveUIPath}"))
{
var newPath = EditorUtility.OpenFolderPanel("UI生成路径", _saveUIPath, "");
_saveUIPath = newPath.Replace(Application.dataPath, "Assets");
EditorPrefs.SetString(nameof(_saveUIPath), _saveUIPath);
}
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<UIControlData>();
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同时会清除JsonUIType中相关数据", "确定", "取消"))
{
// 清除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<UIConfigJson> list = new List<UIConfigJson>();
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<T> CreateAllInstancesOf<T>()
{
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<Type> GetAllUIViewTypes(string domainName)
{
// 查找所有程序集中的UIView类型实现
var uiviewType = typeof(UIView);
List<Type> result = new List<Type>();
// 尝试获取指定名称的程序集
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;
}
}