From 6284f33de637faead772ec4abee34da191b61759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <1464576565@qq.com> Date: Tue, 14 Oct 2025 19:38:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=9A=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LocalizationTableWindow.cs | 91 ++++++++++--------- .../TreeView/TableSheetTreeView.cs | 76 +++++++++++++++- 2 files changed, 123 insertions(+), 44 deletions(-) diff --git a/Editor/Localization/LocalizationTableWindow/LocalizationTableWindow.cs b/Editor/Localization/LocalizationTableWindow/LocalizationTableWindow.cs index 4cce690..845f67e 100644 --- a/Editor/Localization/LocalizationTableWindow/LocalizationTableWindow.cs +++ b/Editor/Localization/LocalizationTableWindow/LocalizationTableWindow.cs @@ -18,12 +18,10 @@ namespace AlicizaX.Localization.Editor private string selectString = string.Empty; private GameLocaizationTable currentTable; // 当前选中的GameLocaizationTable - private const float k_LanguagesWidth = 200f; - private const float k_TableSheetWidth = 200f; // 原本是 const,现在改成可调的字段 [SerializeField] private float languagesWidth = 200f; - [SerializeField] private float tableSheetWidth = 200f; + [SerializeField] private float tableSheetWidth = 300f; private const float SplitterWidth = 3f; // 拖拽条的宽度 private bool isResizingLeft, isResizingMiddle; @@ -344,58 +342,69 @@ namespace AlicizaX.Localization.Editor } } - private void OnDrawSectionItemInspector(ItemSelect item) + private void OnDrawSectionItemInspector(ItemSelect itemSelect) { - // item key change - EditorGUI.BeginChangeCheck(); - { - item.Item.Key = EditorGUILayout.TextField("Key", item.Item.Key); - } - if (EditorGUI.EndChangeCheck()) - { - item.TreeViewItem.displayName = item.Item.Key; - } + var item = itemSelect.Item; - EditorGUILayout.Space(2); - EditorDrawing.Separator(); - EditorGUILayout.Space(1); + EditorGUILayout.LabelField("Editing Key Across Languages", EditorStyles.boldLabel); + // 显示 Key 和 ID(只读) using (new EditorGUI.DisabledGroupScope(true)) { - string parentName = item.Item.Parent.Name; - string parentText = item.Item.Parent.Id + $" ({parentName})"; - EditorGUILayout.LabelField("Parent Id: " + parentText, EditorStyles.miniBoldLabel); - EditorGUILayout.LabelField("Id: " + item.Item.Id, EditorStyles.miniBoldLabel); + EditorGUILayout.TextField("Key", item.Key); + EditorGUILayout.LabelField("Id: " + item.Id); + } + + EditorGUILayout.Space(4); + EditorDrawing.Separator(); + EditorGUILayout.Space(4); + + // 遍历所有语言 + foreach (var lang in windowData.Languages) + { + if (lang.Entry.Asset == null) + continue; + + var languageName = lang.Entry.LanguageName; + TempSheetItem targetItem = null; + + // 在语言的 TableSheet 里找到对应的 Item + foreach (var section in lang.TableSheet) + { + targetItem = section.Items.Find(i => i.Id == item.Id); + if (targetItem != null) + break; + } + + if (targetItem == null) + { + EditorGUILayout.HelpBox($"Language [{languageName}] does not contain this key.", MessageType.Info); + continue; + } + + // 绘制语言名标题 + EditorGUILayout.LabelField(languageName, EditorStyles.miniBoldLabel); + + // 多行文本框 + EditorGUI.BeginChangeCheck(); + targetItem.Value = EditorGUILayout.TextArea(targetItem.Value, GUILayout.MinHeight(40)); + if (EditorGUI.EndChangeCheck()) + { + // 标记已修改 + EditorUtility.SetDirty(lang.Entry.Asset); + } + + EditorGUILayout.Space(6); } } + private void OnDrawLanguageInspector(LanguageSelect selection) { var language = selection.Language; var entry = language.Entry; var treeView = selection.TreeViewItem; - // using (new EditorDrawing.BorderBoxScope(false)) - // { - // // language name change - // Rect nameRect = EditorGUILayout.GetControlRect(); - // - // Rect renameAssetRect = nameRect; - // renameAssetRect.xMin = nameRect.xMax + 2f; - // renameAssetRect.width = EditorGUIUtility.singleLineHeight; - // - // using (new EditorGUI.DisabledGroupScope(entry.Asset == null)) - // { - // GUIContent editIcon = EditorGUIUtility.IconContent("editicon.sml", "Rename"); - // if (GUI.Button(renameAssetRect, editIcon, EditorStyles.iconButton)) - // { - // string assetPath = AssetDatabase.GetAssetPath(entry.Asset); - // string newName = "(Language) " + entry.LanguageName; - // AssetDatabase.RenameAsset(assetPath, newName); - // } - // } - // - // } using (new EditorGUI.DisabledGroupScope(entry.Asset == null)) { diff --git a/Editor/Localization/LocalizationTableWindow/TreeView/TableSheetTreeView.cs b/Editor/Localization/LocalizationTableWindow/TreeView/TableSheetTreeView.cs index 4eec34b..7605891 100644 --- a/Editor/Localization/LocalizationTableWindow/TreeView/TableSheetTreeView.cs +++ b/Editor/Localization/LocalizationTableWindow/TreeView/TableSheetTreeView.cs @@ -118,6 +118,39 @@ namespace AlicizaX.Localization.Editor PopUpContextMenu(); } + // --- 新增:Ctrl/Cmd + D 快捷键处理(在 TreeView 获得焦点且选中 entry 时新增 entry) --- + Event e = Event.current; + if (e.type == EventType.KeyDown && (e.control || e.command) && e.keyCode == KeyCode.D) + { + if (HasFocus()) + { + var sel = GetSelection(); + if (sel != null && sel.Count > 0) + { + var selectedItem = FindItem(sel[0], rootItem); + if (selectedItem is LstrEntryTreeViewItem entry) + { + var parentSection = selectedItem.parent as LstrSectionTreeViewItem; + if (parentSection != null) + { + OnAddNewSectionEntry(parentSection.Section.Id); + Reload(); + SelectLastChildOfSectionAfterReload(parentSection); // 选中新加的条目 + e.Use(); + } + } + else if (selectedItem is LstrSectionTreeViewItem section) + { + OnAddNewSectionEntry(section.Section.Id); + Reload(); + SelectLastChildOfSectionAfterReload(section); + e.Use(); + } + } + } + } + // --- 结束新增 --- + HandleCommandEvent(Event.current); base.OnGUI(rect); } @@ -134,6 +167,7 @@ namespace AlicizaX.Localization.Editor OnAddNewSectionEntry(section.Section.Id); ContextSelectedID = -1; Reload(); + SelectLastChildOfSectionAfterReload(section); }); menu.AddItem(new GUIContent("Delete"), false, () => @@ -145,16 +179,34 @@ namespace AlicizaX.Localization.Editor } else if (selectedItem is LstrEntryTreeViewItem item) { - LstrSectionTreeViewItem parentSection = (LstrSectionTreeViewItem)item.parent; + LstrSectionTreeViewItem parentSection = item.parent as LstrSectionTreeViewItem; + + // 新增:对 entry 的右键也显示 Add Entry(在同一个 section 下新增) + menu.AddItem(new GUIContent("Add Entry"), false, () => + { + if (parentSection != null) + OnAddNewSectionEntry(parentSection.Section.Id); + + ContextSelectedID = -1; + Reload(); + + if (parentSection != null) + SelectLastChildOfSectionAfterReload(parentSection); + }); + menu.AddItem(new GUIContent("Delete"), false, () => { - DeleteLstrEntry(parentSection.Section, item.Item); + if (parentSection != null) + DeleteLstrEntry(parentSection.Section, item.Item); + ContextSelectedID = -1; Reload(); }); menu.AddItem(new GUIContent("Copy"), false, () => { - CopyEntryToBiliboard(parentSection.Section, item.Item); + if (parentSection != null) + CopyEntryToBiliboard(parentSection.Section, item.Item); + ContextSelectedID = -1; Reload(); }); @@ -163,6 +215,24 @@ namespace AlicizaX.Localization.Editor menu.ShowAsContext(); } + private void SelectLastChildOfSectionAfterReload(LstrSectionTreeViewItem originalSection) + { + if (rootItem == null || rootItem.children == null) return; + + // 找到 reload 后仍然绑定到同一 section object 的节点 + var newSectionNode = rootItem.children + .OfType() + .FirstOrDefault(s => s.Section != null && originalSection.Section != null && s.Section.Id == originalSection.Section.Id); + + if (newSectionNode != null && newSectionNode.children != null && newSectionNode.children.Count > 0) + { + var newEntryNode = newSectionNode.children.Last(); + SetSelection(new int[] { newEntryNode.id }); + FrameItem(newEntryNode.id); + } + } + + private void OnAddNewSection() { windowData.AddSection(k_NewSection);