2025-09-23 12:04:39 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using AlicizaX.Editor;
|
|
|
|
|
|
using Sirenix.OdinInspector;
|
|
|
|
|
|
using UnityEditor.IMGUI.Controls;
|
|
|
|
|
|
using UnityEditor;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace AlicizaX.Localization.Editor
|
|
|
|
|
|
{
|
|
|
|
|
|
public class LocalizationTableWindow : EditorWindow
|
|
|
|
|
|
{
|
|
|
|
|
|
private List<GameLocaizationTable> allTables = new List<GameLocaizationTable>(); // 存储所有找到的GameLocaizationTable
|
|
|
|
|
|
private string[] tableDisplayNames; // 用于下拉框显示的名称数组
|
|
|
|
|
|
private int selectedTableIndex = 0; // 当前选中的索引
|
|
|
|
|
|
private string selectString = string.Empty;
|
|
|
|
|
|
private GameLocaizationTable currentTable; // 当前选中的GameLocaizationTable
|
|
|
|
|
|
|
2025-09-25 11:11:19 +08:00
|
|
|
|
|
|
|
|
|
|
// 原本是 const,现在改成可调的字段
|
|
|
|
|
|
[SerializeField] private float languagesWidth = 200f;
|
2025-10-14 19:38:28 +08:00
|
|
|
|
[SerializeField] private float tableSheetWidth = 300f;
|
2025-09-25 11:11:19 +08:00
|
|
|
|
|
|
|
|
|
|
private const float SplitterWidth = 3f; // 拖拽条的宽度
|
|
|
|
|
|
private bool isResizingLeft, isResizingMiddle;
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-23 12:04:39 +08:00
|
|
|
|
private float Spacing => EditorGUIUtility.standardVerticalSpacing * 2;
|
|
|
|
|
|
|
|
|
|
|
|
private GUIStyle miniLabelButton => new GUIStyle(EditorStyles.miniButton)
|
|
|
|
|
|
{
|
|
|
|
|
|
font = EditorStyles.miniBoldLabel.font,
|
|
|
|
|
|
fontSize = EditorStyles.miniBoldLabel.fontSize
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
public class WindowSelection
|
|
|
|
|
|
{
|
|
|
|
|
|
public TreeViewItem TreeViewItem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public sealed class LanguageSelect : WindowSelection
|
|
|
|
|
|
{
|
|
|
|
|
|
public TempLanguageData Language;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public sealed class SectionSelect : WindowSelection
|
|
|
|
|
|
{
|
|
|
|
|
|
public SheetSectionTreeView Section;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public sealed class ItemSelect : WindowSelection
|
|
|
|
|
|
{
|
|
|
|
|
|
public SheetItemTreeView Item;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private LocalizationWindowData windowData;
|
|
|
|
|
|
|
|
|
|
|
|
private SearchField searchField;
|
|
|
|
|
|
private string searchString;
|
|
|
|
|
|
private Vector2 scrollPosition;
|
|
|
|
|
|
|
|
|
|
|
|
[SerializeField] private TreeViewState languagesTreeViewState;
|
|
|
|
|
|
private LanguagesTreeView languagesTreeView;
|
|
|
|
|
|
|
|
|
|
|
|
[SerializeField] private TreeViewState tableSheetTreeViewState;
|
|
|
|
|
|
private TableSheetTreeView tableSheetTreeView;
|
|
|
|
|
|
|
|
|
|
|
|
private WindowSelection selection = null;
|
|
|
|
|
|
private bool globalExpanded = false;
|
|
|
|
|
|
|
|
|
|
|
|
private void CreateGUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
searchField = new SearchField();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
|
|
{
|
|
|
|
|
|
SaveSelection();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnEnable()
|
|
|
|
|
|
{
|
|
|
|
|
|
RefreshTableList();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnDisable()
|
|
|
|
|
|
{
|
|
|
|
|
|
SaveSelection();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshTableList()
|
|
|
|
|
|
{
|
|
|
|
|
|
allTables.Clear();
|
|
|
|
|
|
string[] guids = AssetDatabase.FindAssets("t:GameLocaizationTable");
|
|
|
|
|
|
foreach (string guid in guids)
|
|
|
|
|
|
{
|
|
|
|
|
|
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
|
|
|
|
|
GameLocaizationTable table = AssetDatabase.LoadAssetAtPath<GameLocaizationTable>(assetPath);
|
|
|
|
|
|
if (table != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
allTables.Add(table);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tableDisplayNames = new string[allTables.Count];
|
|
|
|
|
|
for (int i = 0; i < allTables.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
tableDisplayNames[i] = allTables[i].name;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (allTables.Count > 0 && selectedTableIndex >= allTables.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
selectedTableIndex = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var selectIndex = selectedTableIndex;
|
|
|
|
|
|
var lastSelect = EditorPrefs.GetString("LastSelectedGameLocaizationTable", string.Empty);
|
|
|
|
|
|
if (!string.IsNullOrEmpty(lastSelect))
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < allTables.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var path = AssetDatabase.GetAssetPath(allTables[i]);
|
|
|
|
|
|
if (path.Equals(lastSelect))
|
|
|
|
|
|
{
|
|
|
|
|
|
selectIndex = i;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (selectIndex <= tableDisplayNames.Length - 1 && selectIndex >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
selectString = tableDisplayNames[selectIndex];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UpdateCurrentTable();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateCurrentTable()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (allTables.Count > 0 && selectedTableIndex >= 0 && selectedTableIndex < allTables.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentTable = allTables[selectedTableIndex];
|
|
|
|
|
|
SaveSelection();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
currentTable = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
InitializeTreeView();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void SaveSelection()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (currentTable != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
string path = AssetDatabase.GetAssetPath(currentTable);
|
|
|
|
|
|
EditorPrefs.SetString("LastSelectedGameLocaizationTable", path);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void InitializeTreeView()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!currentTable) return;
|
|
|
|
|
|
|
|
|
|
|
|
LocalizationWindowUtility.BuildWindowData(currentTable, out windowData);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var section in windowData.TableSheet)
|
|
|
|
|
|
{
|
|
|
|
|
|
section.IsExpanded = globalExpanded;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
languagesTreeViewState = new TreeViewState();
|
|
|
|
|
|
languagesTreeView = new(languagesTreeViewState, windowData, currentTable)
|
|
|
|
|
|
{
|
|
|
|
|
|
OnLanguageSelect = (s) => selection = s
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tableSheetTreeViewState = new TreeViewState();
|
|
|
|
|
|
tableSheetTreeView = new(tableSheetTreeViewState, windowData)
|
|
|
|
|
|
{
|
|
|
|
|
|
OnTableSheetSelect = (s) => selection = s
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnGUI()
|
|
|
|
|
|
{
|
2025-09-25 11:11:19 +08:00
|
|
|
|
// 顶部工具栏
|
2025-09-23 12:04:39 +08:00
|
|
|
|
Rect toolbarRect = new(0, 0, position.width, 20f);
|
|
|
|
|
|
GUI.Box(toolbarRect, GUIContent.none, EditorStyles.toolbar);
|
|
|
|
|
|
|
|
|
|
|
|
float buttonWidth = 100f;
|
|
|
|
|
|
float spacing = 5f;
|
|
|
|
|
|
|
|
|
|
|
|
Rect leftTitle = new(toolbarRect.xMin, 0, 40, 20f);
|
|
|
|
|
|
Rect leftPop = new(leftTitle.xMin + 40, 0, 200, 20f);
|
|
|
|
|
|
Rect saveBtn = new(toolbarRect.xMax - buttonWidth - spacing, 0, buttonWidth, 20f);
|
|
|
|
|
|
Rect genBtn = new(saveBtn.xMin - buttonWidth - spacing, 0, buttonWidth, 20f);
|
|
|
|
|
|
Rect importBtn = new(genBtn.xMin - buttonWidth - spacing, 0, buttonWidth, 20f);
|
|
|
|
|
|
Rect exportBtn = new(importBtn.xMin - buttonWidth - spacing, 0, buttonWidth, 20f);
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUI.LabelField(leftTitle, "Table", EditorStyles.boldLabel);
|
|
|
|
|
|
EditorDrawing.DrawStringSelectPopup(leftPop, tableDisplayNames, selectString, (e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
selectString = e;
|
|
|
|
|
|
selectedTableIndex = allTables.FindIndex(table => table.name == e);
|
|
|
|
|
|
UpdateCurrentTable();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (currentTable == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (GUI.Button(exportBtn, "Export CSV", EditorStyles.toolbarButton))
|
|
|
|
|
|
{
|
|
|
|
|
|
string path = EditorUtility.SaveFilePanel("Export CSV", "", "Localization", "csv");
|
|
|
|
|
|
LocalizationExporter.ExportLocalizationToCSV(windowData, path);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (GUI.Button(importBtn, "Import CSV", EditorStyles.toolbarButton))
|
|
|
|
|
|
{
|
|
|
|
|
|
string path = EditorUtility.OpenFilePanel("Export CSV", "", "csv");
|
|
|
|
|
|
LocalizationExporter.ImportLocalizationFromCSV(windowData, path);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (GUI.Button(genBtn, "Gen Code", EditorStyles.toolbarButton))
|
|
|
|
|
|
{
|
|
|
|
|
|
LocalizationWindowUtility.GenerateCode(currentTable);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (GUI.Button(saveBtn, "Save Asset", EditorStyles.toolbarButton))
|
|
|
|
|
|
{
|
|
|
|
|
|
BuildLocalizationTable();
|
|
|
|
|
|
EditorUtility.SetDirty(currentTable);
|
|
|
|
|
|
AssetDatabase.SaveAssets();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-25 11:11:19 +08:00
|
|
|
|
// ---------------- 这里开始是 SplitView ----------------
|
|
|
|
|
|
Rect fullRect = new Rect(0, 20f, position.width, position.height - 20f);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
|
2025-09-25 11:11:19 +08:00
|
|
|
|
// 左侧 Languages
|
|
|
|
|
|
Rect languagesRect = new Rect(fullRect.x, fullRect.y, languagesWidth, fullRect.height);
|
|
|
|
|
|
languagesTreeView?.OnGUI(languagesRect);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
|
2025-09-25 11:11:19 +08:00
|
|
|
|
// 左侧拖拽条
|
|
|
|
|
|
Rect leftSplitter = new Rect(languagesRect.xMax, fullRect.y, SplitterWidth, fullRect.height);
|
|
|
|
|
|
EditorGUIUtility.AddCursorRect(leftSplitter, MouseCursor.ResizeHorizontal);
|
|
|
|
|
|
HandleResize(ref languagesWidth, leftSplitter, ref isResizingLeft);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
|
2025-09-25 11:11:19 +08:00
|
|
|
|
// 中间 TableSheet
|
|
|
|
|
|
Rect tableSheetRect = new Rect(leftSplitter.xMax, fullRect.y, tableSheetWidth, fullRect.height);
|
|
|
|
|
|
tableSheetTreeView?.OnGUI(tableSheetRect);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
|
2025-09-25 11:11:19 +08:00
|
|
|
|
// 中间拖拽条
|
|
|
|
|
|
Rect midSplitter = new Rect(tableSheetRect.xMax, fullRect.y, SplitterWidth, fullRect.height);
|
|
|
|
|
|
EditorGUIUtility.AddCursorRect(midSplitter, MouseCursor.ResizeHorizontal);
|
|
|
|
|
|
HandleResize(ref tableSheetWidth, midSplitter, ref isResizingMiddle);
|
|
|
|
|
|
|
|
|
|
|
|
// 右侧 Inspector(剩余空间)
|
|
|
|
|
|
float inspectorWidth = fullRect.width - (languagesWidth + tableSheetWidth + SplitterWidth * 2);
|
|
|
|
|
|
Rect inspectorRect = new Rect(midSplitter.xMax, fullRect.y, inspectorWidth, fullRect.height);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
|
|
|
|
|
|
if (selection != null)
|
|
|
|
|
|
{
|
2025-09-25 11:11:19 +08:00
|
|
|
|
GUILayout.BeginArea(inspectorRect);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
{
|
2025-09-25 11:11:19 +08:00
|
|
|
|
if (selection is LanguageSelect lang) OnDrawLanguageInspector(lang);
|
|
|
|
|
|
else if (selection is SectionSelect sec) OnDrawSectionInspector(sec);
|
|
|
|
|
|
else if (selection is ItemSelect item) OnDrawSectionItemInspector(item);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
}
|
2025-09-25 11:11:19 +08:00
|
|
|
|
GUILayout.EndArea();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void HandleResize(ref float targetWidth, Rect splitterRect, ref bool isResizing)
|
|
|
|
|
|
{
|
|
|
|
|
|
Event e = Event.current;
|
|
|
|
|
|
|
|
|
|
|
|
switch (e.type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case EventType.MouseDown:
|
|
|
|
|
|
if (splitterRect.Contains(e.mousePosition))
|
|
|
|
|
|
{
|
|
|
|
|
|
isResizing = true;
|
|
|
|
|
|
e.Use();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case EventType.MouseDrag:
|
|
|
|
|
|
if (isResizing)
|
|
|
|
|
|
{
|
|
|
|
|
|
targetWidth += e.delta.x;
|
|
|
|
|
|
targetWidth = Mathf.Max(100f, targetWidth); // 设置最小宽度
|
|
|
|
|
|
e.Use();
|
|
|
|
|
|
Repaint();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case EventType.MouseUp:
|
|
|
|
|
|
if (isResizing)
|
|
|
|
|
|
{
|
|
|
|
|
|
isResizing = false;
|
|
|
|
|
|
e.Use();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
2025-09-23 12:04:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnDrawSectionInspector(SectionSelect section)
|
|
|
|
|
|
{
|
|
|
|
|
|
// section name change
|
|
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
|
|
{
|
|
|
|
|
|
section.Section.Name = EditorGUILayout.TextField("Name", section.Section.Name);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
|
|
|
|
{
|
|
|
|
|
|
section.TreeViewItem.displayName = section.Section.Name;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using (new EditorGUI.DisabledGroupScope(true))
|
|
|
|
|
|
{
|
|
|
|
|
|
int childerCount = section.TreeViewItem.children?.Count ?? 0;
|
|
|
|
|
|
EditorGUILayout.IntField(new GUIContent("Keys"), childerCount);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.Space(2);
|
|
|
|
|
|
EditorDrawing.Separator();
|
|
|
|
|
|
EditorGUILayout.Space(1);
|
|
|
|
|
|
|
|
|
|
|
|
using (new EditorGUI.DisabledGroupScope(true))
|
|
|
|
|
|
{
|
|
|
|
|
|
EditorGUILayout.LabelField("Id: " + section.Section.Id, EditorStyles.miniBoldLabel);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-14 19:38:28 +08:00
|
|
|
|
private void OnDrawSectionItemInspector(ItemSelect itemSelect)
|
2025-09-23 12:04:39 +08:00
|
|
|
|
{
|
2025-10-14 19:38:28 +08:00
|
|
|
|
var item = itemSelect.Item;
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.LabelField("Editing Key Across Languages", EditorStyles.boldLabel);
|
|
|
|
|
|
|
|
|
|
|
|
// 显示 Key 和 ID(只读)
|
|
|
|
|
|
using (new EditorGUI.DisabledGroupScope(true))
|
2025-09-23 12:04:39 +08:00
|
|
|
|
{
|
2025-10-14 19:38:28 +08:00
|
|
|
|
EditorGUILayout.TextField("Key", item.Key);
|
|
|
|
|
|
EditorGUILayout.LabelField("Id: " + item.Id);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-14 19:38:28 +08:00
|
|
|
|
EditorGUILayout.Space(4);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
EditorDrawing.Separator();
|
2025-10-14 19:38:28 +08:00
|
|
|
|
EditorGUILayout.Space(4);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
|
2025-10-14 19:38:28 +08:00
|
|
|
|
// 遍历所有语言
|
|
|
|
|
|
foreach (var lang in windowData.Languages)
|
2025-09-23 12:04:39 +08:00
|
|
|
|
{
|
2025-10-14 19:38:28 +08:00
|
|
|
|
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);
|
2025-09-23 12:04:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-14 19:38:28 +08:00
|
|
|
|
|
2025-09-23 12:04:39 +08:00
|
|
|
|
private void OnDrawLanguageInspector(LanguageSelect selection)
|
|
|
|
|
|
{
|
|
|
|
|
|
var language = selection.Language;
|
|
|
|
|
|
var entry = language.Entry;
|
|
|
|
|
|
var treeView = selection.TreeViewItem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using (new EditorGUI.DisabledGroupScope(entry.Asset == null))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Draw search field
|
|
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
|
|
|
|
|
|
|
|
GUIContent expandText = new GUIContent("Expand");
|
|
|
|
|
|
float expandWidth = miniLabelButton.CalcSize(expandText).x;
|
|
|
|
|
|
|
|
|
|
|
|
var searchRect = EditorGUILayout.GetControlRect();
|
|
|
|
|
|
searchRect.xMax -= (expandWidth + 2f);
|
|
|
|
|
|
searchString = searchField.OnGUI(searchRect, searchString);
|
|
|
|
|
|
|
|
|
|
|
|
Rect expandRect = new Rect(searchRect.xMax + 2f, searchRect.y, expandWidth, searchRect.height);
|
|
|
|
|
|
expandRect.y -= 1f;
|
|
|
|
|
|
|
|
|
|
|
|
using (new EditorDrawing.BackgroundColorScope("#F7E987"))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (GUI.Button(expandRect, expandText, miniLabelButton))
|
|
|
|
|
|
{
|
|
|
|
|
|
globalExpanded = !globalExpanded;
|
|
|
|
|
|
foreach (var section in language.TableSheet)
|
|
|
|
|
|
{
|
|
|
|
|
|
section.Reference.IsExpanded = globalExpanded;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (entry.Asset != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Draw localization data
|
|
|
|
|
|
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var section in GetSearchResult(language, searchString))
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawLocalizationKey(section);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
EditorGUILayout.EndScrollView();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
EditorGUILayout.HelpBox("To begin editing localization data, you must first assign a localization asset.", MessageType.Warning);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void DrawLocalizationKey(TempSheetSection section)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (section.Items == null || section.Items.Count == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
using (new EditorDrawing.BorderBoxScope(false))
|
|
|
|
|
|
{
|
|
|
|
|
|
string sectionName = section.Name.Replace(" ", "");
|
|
|
|
|
|
section.Reference.IsExpanded = EditorGUILayout.Foldout(section.Reference.IsExpanded, new GUIContent(sectionName), true, EditorDrawing.Styles.miniBoldLabelFoldout);
|
|
|
|
|
|
|
|
|
|
|
|
// Show section keys when expanded
|
|
|
|
|
|
if (section.Reference.IsExpanded)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var item in section.Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
string keyName = item.Key.Replace(" ", "");
|
|
|
|
|
|
string key = sectionName + "." + keyName;
|
|
|
|
|
|
|
|
|
|
|
|
if (IsMultiline(item.Value))
|
|
|
|
|
|
key += " (Multiline)";
|
|
|
|
|
|
|
|
|
|
|
|
using (new EditorGUILayout.VerticalScope(GUI.skin.box))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Display the expandable toggle
|
|
|
|
|
|
using (new EditorGUILayout.HorizontalScope(GUI.skin.box))
|
|
|
|
|
|
{
|
|
|
|
|
|
item.IsExpanded = EditorGUILayout.Foldout(item.IsExpanded, new GUIContent(key), true, EditorDrawing.Styles.miniBoldLabelFoldout);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (item.IsExpanded)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Show TextArea when expanded
|
|
|
|
|
|
float height = (EditorGUIUtility.standardVerticalSpacing + EditorGUIUtility.singleLineHeight) * 3;
|
|
|
|
|
|
height += EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
|
|
|
|
|
|
|
|
item.Scroll = EditorGUILayout.BeginScrollView(item.Scroll, GUILayout.Height(height));
|
|
|
|
|
|
item.Value = EditorGUILayout.TextArea(item.Value, GUILayout.ExpandHeight(true));
|
|
|
|
|
|
EditorGUILayout.EndScrollView();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Show TextField when collapsed
|
|
|
|
|
|
item.Value = EditorGUILayout.TextField(item.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.Space(1f);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private IEnumerable<TempSheetSection> GetSearchResult(TempLanguageData languageData, string search)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!string.IsNullOrEmpty(search))
|
|
|
|
|
|
{
|
|
|
|
|
|
List<TempSheetSection> searchResult = new();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var section in languageData.TableSheet)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<TempSheetItem> sectionItems = new();
|
|
|
|
|
|
string sectionName = section.Name.Replace(" ", "");
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in section.Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
string keyName = item.Key.Replace(" ", "");
|
|
|
|
|
|
string key = sectionName + "." + keyName;
|
|
|
|
|
|
|
|
|
|
|
|
if (key.Contains(search))
|
|
|
|
|
|
sectionItems.Add(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
searchResult.Add(new TempSheetSection()
|
|
|
|
|
|
{
|
|
|
|
|
|
Items = sectionItems,
|
|
|
|
|
|
Reference = section.Reference
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return searchResult;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return languageData.TableSheet;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool IsMultiline(string text)
|
|
|
|
|
|
{
|
|
|
|
|
|
return text.Contains("\n") || text.Contains("\r");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void BuildLocalizationTable()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. build table sheet
|
|
|
|
|
|
currentTable.TableSheet = new();
|
|
|
|
|
|
foreach (var section in windowData.TableSheet)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameLocaizationTable.TableData tableData = new GameLocaizationTable.TableData(section.Name, section.Id);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in section.Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameLocaizationTable.SheetItem sheetItem = new GameLocaizationTable.SheetItem(item.Key, item.Id, item.isGen);
|
|
|
|
|
|
tableData.SectionSheet.Add(sheetItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currentTable.TableSheet.Add(tableData);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. build table sheet for each language
|
|
|
|
|
|
IList<LocalizationLanguage> languages = new List<LocalizationLanguage>();
|
|
|
|
|
|
foreach (var language in windowData.Languages)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (language.Entry.Asset == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
LocalizationLanguage asset = language.Entry.Asset;
|
|
|
|
|
|
IList<LocalizationLanguage.LocalizationString> strings = new List<LocalizationLanguage.LocalizationString>();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var section in language.TableSheet)
|
|
|
|
|
|
{
|
|
|
|
|
|
string sectionKey = section.Name.Replace(" ", "");
|
|
|
|
|
|
foreach (var item in section.Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
string itemKey = item.Key.Replace(" ", "");
|
|
|
|
|
|
string key = sectionKey + "." + itemKey;
|
|
|
|
|
|
|
|
|
|
|
|
strings.Add(new()
|
|
|
|
|
|
{
|
|
|
|
|
|
SectionId = section.Id,
|
|
|
|
|
|
EntryId = item.Id,
|
|
|
|
|
|
Key = key,
|
|
|
|
|
|
Value = item.Value
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
asset.LanguageName = language.Entry.LanguageName;
|
|
|
|
|
|
asset.Strings = new(strings);
|
|
|
|
|
|
|
|
|
|
|
|
languages.Add(asset);
|
|
|
|
|
|
EditorUtility.SetDirty(asset);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currentTable.Languages = new(languages);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|