using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.UI; using TMPro; using BaseGames.UI; using BaseGames.UI.Theme; using BaseGames.Core.Events; using BaseGames.Localization; using BaseGames.Editor.Localization; namespace BaseGames.Editor.UI { /// /// 图鉴脚手架:生成 UI_BestiaryCell + UI_BestiaryPanel 预制件 + 空 UI_BestiaryDatabase 表 + BESTIARY_* 中英文案。 /// 面板据 BestiaryDatabaseSO 列出全部敌人,经 IBestiaryService 读已发现态(已发现亮/未发现 ??? + 剪影 + 锁), /// 订阅 EVT_BestiaryUpdated 实时刷新;点击格子在右侧详情区展示。 /// /// 数据:策划在 UI_BestiaryDatabase 增删条目(enemyId 须与 EnemyBase._enemyId 一致),或用「同步图鉴条目」工具自动补。 /// 菜单:BaseGames/UI/控件库/生成图鉴(预制件 + 空表) /// public static class UIBestiaryScaffold { private const string PrefabDir = "Assets/_Game/Prefabs/UI"; private const string ControlsDir = "Assets/_Game/Prefabs/UI/Controls"; private const string ConfigDir = "Assets/_Game/Data/UI"; private const string ThemePath = "Assets/_Game/Data/UI/Themes/UI_Theme_Default.asset"; private const string PanelName = "UI_BestiaryPanel"; private const string CellName = "UI_BestiaryCell"; private const string DbName = "UI_BestiaryDatabase"; [MenuItem("BaseGames/UI/控件库/生成图鉴(预制件 + 空表)")] public static void GeneratePrefab() { EnsureFolder(PrefabDir); EnsureFolder(ControlsDir); EnsureFolder(ConfigDir); var report = new List(); var theme = AssetDatabase.LoadAssetAtPath(ThemePath); var db = EnsureDatabase(report); SeedLocalization(report); var cell = BuildCellPrefab(theme, report); BuildPanelPrefab(theme, db, cell, report); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); var sb = new System.Text.StringBuilder("[UIBestiary] 图鉴已生成:\n"); foreach (var r in report) sb.AppendLine(" • " + r); sb.AppendLine("策划在 UI_BestiaryDatabase 填敌人条目(enemyId 同 EnemyBase._enemyId);重跑「Scaffold Inventory Hub」收编为图鉴 Tab。"); Debug.Log(sb.ToString()); } private static BestiaryDatabaseSO EnsureDatabase(List report) { string path = $"{ConfigDir}/{DbName}.asset"; var db = AssetDatabase.LoadAssetAtPath(path); if (db == null) { db = ScriptableObject.CreateInstance(); AssetDatabase.CreateAsset(db, path); report.Add($"{path}(空表,待策划/同步工具填充)"); } return db; } private static void SeedLocalization(List report) { var zh = new Dictionary { { "MENU_BESTIARY", "图鉴" }, { "BESTIARY_TITLE", "图鉴" }, { "BESTIARY_LOCKED", "???" }, { "BESTIARY_LOCKED_DESC", "尚未发现该敌人。" }, { "BESTIARY_HP", "生命" }, { "BESTIARY_KILLS", "击杀" }, }; var en = new Dictionary { { "MENU_BESTIARY", "Bestiary" }, { "BESTIARY_TITLE", "Bestiary" }, { "BESTIARY_LOCKED", "???" }, { "BESTIARY_LOCKED_DESC", "Not yet discovered." }, { "BESTIARY_HP", "HP" }, { "BESTIARY_KILLS", "Kills" }, }; int added = MergeWriteUI(Language.ChineseSimplified, zh) + MergeWriteUI(Language.English, en); report.Add($"本地化新增 {added} 条(已存在不覆盖)。"); } private static int MergeWriteUI(Language lang, Dictionary kv) { var dict = LocalizationFileIO.Read(lang, LocalizationTable.UI); int added = 0; foreach (var p in kv) if (!dict.ContainsKey(p.Key)) { dict[p.Key] = p.Value; added++; } if (added > 0) LocalizationFileIO.Write(lang, LocalizationTable.UI, dict); return added; } // ── 单元格预制件 ───────────────────────────────────────────────────── private static BestiaryCellView BuildCellPrefab(UIThemeSO theme, List report) { var root = new GameObject(CellName, typeof(RectTransform), typeof(CanvasGroup)); ((RectTransform)root.transform).sizeDelta = new Vector2(170f, 130f); var view = root.AddComponent(); var bg = root.AddComponent(); bg.sprite = Std(); bg.type = Image.Type.Sliced; bg.color = new Color(1f, 1f, 1f, 0.05f); var btn = root.AddComponent