using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.UI; using TMPro; using BaseGames.UI; using BaseGames.UI.Settings; using BaseGames.UI.MainMenu; using BaseGames.UI.Theme; using BaseGames.Localization; using BaseGames.Editor.Localization; namespace BaseGames.Editor.UI { /// /// UI 通用控件库脚手架。 /// /// 一键生成 / 更新 themed 控件预制件(UIButton / UISelectableRow / UISlider / UIDropdown / /// UISimplePanel / UITabGroup),并提供"向选中节点放置控件"菜单,使策划可拖拽即用。 /// /// 预制件输出目录:Assets/_Game/Prefabs/UI/Controls/(命名前缀 UI_,符合 AssetFolderSpec)。 /// 构建方式复用 Unity/TMP 的 DefaultControls 标准层级,再挂上本项目的封装组件与 UIThemeRole 标记。 /// /// 菜单:BaseGames/UI/控件库/... /// public static class UIControlLibraryScaffold { private const string ControlsDir = "Assets/_Game/Prefabs/UI/Controls"; private const string ThemeDir = "Assets/_Game/Data/UI/Themes"; private const string ThemeName = "UI_Theme_Default"; // 生成期间的默认主题(GenerateAll 开头确保存在;各 Build 方法读取) private static UIThemeSO s_theme; // 预制件文件名 private const string PfButton = "UI_Control_Button"; private const string PfRow = "UI_Control_SelectableRow"; private const string PfSlider = "UI_Control_Slider"; private const string PfDropdown = "UI_Control_Dropdown"; private const string PfPanel = "UI_Control_Panel"; private const string PfTabBar = "UI_Control_TabBar"; // ── 生成 ───────────────────────────────────────────────────────────── [MenuItem("BaseGames/UI/控件库/生成或更新控件预制件")] public static void GenerateAll() { EnsureFolder(ControlsDir); var report = new List(); s_theme = EnsureDefaultTheme(report); BuildButton(report); BuildSelectableRow(report); BuildSlider(report); BuildDropdown(report); BuildPanel(report); BuildTabBar(report); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); var sb = new System.Text.StringBuilder("[UIControlLibrary] 控件预制件已生成/更新:\n"); foreach (var r in report) sb.AppendLine(" • " + r); sb.AppendLine($"目录:{ControlsDir}/(占位配色,可挂 UIThemeApplier + UIThemeSO 统一主题)"); Debug.Log(sb.ToString()); } // ── 放置 ───────────────────────────────────────────────────────────── [MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ Button")] private static void PlaceButton() => Place(PfButton); [MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ SelectableRow")] private static void PlaceRow() => Place(PfRow); [MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ Slider")] private static void PlaceSlider() => Place(PfSlider); [MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ Dropdown")] private static void PlaceDropdown() => Place(PfDropdown); [MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ Panel")] private static void PlacePanel() => Place(PfPanel); [MenuItem("BaseGames/UI/控件库/向选中节点放置 ▸ TabBar")] private static void PlaceTabBar() => Place(PfTabBar); private static void Place(string prefabName) { string path = $"{ControlsDir}/{prefabName}.prefab"; var prefab = AssetDatabase.LoadAssetAtPath(path); if (prefab == null) { EditorUtility.DisplayDialog("控件库", $"未找到预制件:{path}\n请先执行「生成或更新控件预制件」。", "确定"); return; } // 父节点:当前选中的 Transform,否则活动场景中的第一个 Canvas Transform parent = Selection.activeTransform; if (parent == null) { var canvas = Object.FindObjectOfType(); parent = canvas != null ? canvas.transform : null; } var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab, parent); if (instance == null) return; Undo.RegisterCreatedObjectUndo(instance, $"Place {prefabName}"); Selection.activeGameObject = instance; EditorGUIUtility.PingObject(instance); } // ── 默认主题 ───────────────────────────────────────────────────────── private static UIThemeSO EnsureDefaultTheme(List report) { EnsureFolder(ThemeDir); string path = $"{ThemeDir}/{ThemeName}.asset"; var theme = AssetDatabase.LoadAssetAtPath(path); if (theme == null) { theme = ScriptableObject.CreateInstance(); // 字段含默认配色 AssetDatabase.CreateAsset(theme, path); report.Add($"{path}(默认主题,可调色板/字体)"); } return theme; } // ── 各控件构建 ─────────────────────────────────────────────────────── private static void BuildButton(List report) { var go = TMP_DefaultControls.CreateButton(TmpResources()); go.name = PfButton; Size(go, 200, 48); var uiBtn = GetOrAdd(go); if (s_theme != null) AssignRef(uiBtn, "_theme", s_theme); SetEnum(GetOrAdd(go), "_kind", (int)UIThemeRoleKind.Button); var label = go.GetComponentInChildren(); if (label != null) { label.text = "Button"; SetEnum(GetOrAdd(label.gameObject), "_kind", (int)UIThemeRoleKind.Text_Primary); } SaveAsPrefab(go, PfButton, report); } private static void BuildSelectableRow(List report) { var go = NewUI(PfRow, 320, 48); var bg = go.AddComponent(); bg.sprite = Standard(); bg.type = Image.Type.Sliced; bg.color = new Color(1f, 1f, 1f, 0.06f); var btn = go.AddComponent