| New file |
| | |
| | | using UnityEngine; |
| | | using UnityEditor; |
| | | using System.Collections.Generic; |
| | | |
| | | /// <summary> |
| | | /// TextLanguageAdapter 自定义编辑器 |
| | | /// 提供可视化的多语言排版配置界面 |
| | | /// </summary> |
| | | [CustomEditor(typeof(TextLanguageAdapter), true)] |
| | | [CanEditMultipleObjects] |
| | | public class TextLanguageAdapterEditor : Editor |
| | | { |
| | | private Dictionary<string, bool> m_FoldoutStates = new Dictionary<string, bool>(); |
| | | private Dictionary<string, string> m_LanguageShowDict; |
| | | private static readonly string[] m_PresetLanguageIds = { TextLanguageAdapter.DefaultLangId, "zh", "ft", "en"}; |
| | | private static readonly string[] m_PresetLanguageNames = { "默认", "简体", "繁体", "English" }; |
| | | private string m_CopySourceLanguageId = ""; |
| | | |
| | | protected virtual void OnEnable() |
| | | { |
| | | InitLanguageShowDict(); |
| | | if (target is TextLanguageAdapter adapter) |
| | | { |
| | | // 确保 default 配置存在 |
| | | if (!adapter.HasConfig(TextLanguageAdapter.DefaultLangId)) |
| | | { |
| | | adapter.ReadCurrentToConfig(TextLanguageAdapter.DefaultLangId); |
| | | EditorUtility.SetDirty(adapter); |
| | | } |
| | | |
| | | foreach (var langId in adapter.GetConfiguredLanguages()) |
| | | { |
| | | m_FoldoutStates.TryAdd(langId, false); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public override void OnInspectorGUI() |
| | | { |
| | | TextLanguageAdapter adapter = target as TextLanguageAdapter; |
| | | |
| | | DrawBasicInfo(adapter); |
| | | EditorGUILayout.Space(); |
| | | DrawLanguageConfigs(adapter); |
| | | |
| | | if (GUI.changed) |
| | | { |
| | | EditorUtility.SetDirty(target); |
| | | } |
| | | } |
| | | |
| | | private void InitLanguageShowDict() |
| | | { |
| | | if (m_LanguageShowDict != null) return; |
| | | |
| | | m_LanguageShowDict = new Dictionary<string, string>(); |
| | | for (int i = 0; i < m_PresetLanguageIds.Length; i++) |
| | | { |
| | | m_LanguageShowDict[m_PresetLanguageIds[i]] = m_PresetLanguageNames[i]; |
| | | } |
| | | } |
| | | |
| | | private string GetLanguageDisplayName(string languageId) |
| | | { |
| | | if (m_LanguageShowDict != null && m_LanguageShowDict.TryGetValue(languageId, out string name)) |
| | | { |
| | | return name; |
| | | } |
| | | return TextLanguageAdapter.GetLanguageShowName(languageId); |
| | | } |
| | | |
| | | private void DrawBasicInfo(TextLanguageAdapter adapter) |
| | | { |
| | | EditorGUILayout.BeginVertical(EditorStyles.helpBox); |
| | | EditorGUILayout.LabelField("基本信息", EditorStyles.boldLabel); |
| | | |
| | | EditorGUI.BeginDisabledGroup(true); |
| | | // 使用新开放的 TargetTextComponent 属性,彻底消除反射 |
| | | EditorGUILayout.ObjectField("目标组件", adapter.LanguageConfigs.keys.Count > 0 ? adapter.TargetTextComponent : null, typeof(Component), true); |
| | | EditorGUILayout.EnumPopup("组件类型", adapter.TargetTextType); |
| | | EditorGUI.EndDisabledGroup(); |
| | | |
| | | if (GUILayout.Button("刷新组件检测", GUILayout.Width(120))) |
| | | { |
| | | adapter.Editor_ForceRefreshDetection(); |
| | | } |
| | | |
| | | EditorGUILayout.EndVertical(); |
| | | } |
| | | |
| | | private void DrawLanguageConfigs(TextLanguageAdapter adapter) |
| | | { |
| | | EditorGUILayout.BeginVertical(EditorStyles.helpBox); |
| | | EditorGUILayout.LabelField($"语言排版配置 (必须包含 {TextLanguageAdapter.DefaultLangId} 默认配置)", EditorStyles.boldLabel); |
| | | |
| | | List<string> configuredLanguages = adapter.GetConfiguredLanguages(); |
| | | foreach (var langId in configuredLanguages) |
| | | { |
| | | DrawLanguageConfigItem(adapter, langId); |
| | | } |
| | | |
| | | EditorGUILayout.Space(); |
| | | DrawAddLanguageConfig(adapter); |
| | | EditorGUILayout.EndVertical(); |
| | | } |
| | | |
| | | private void DrawLanguageConfigItem(TextLanguageAdapter adapter, string languageId) |
| | | { |
| | | m_FoldoutStates.TryAdd(languageId, false); |
| | | |
| | | string displayName = GetLanguageDisplayName(languageId); |
| | | string foldoutLabel = string.IsNullOrEmpty(displayName) ? languageId : $"{languageId} ({displayName})"; |
| | | |
| | | EditorGUI.indentLevel++; |
| | | |
| | | // 高亮默认配置 |
| | | if (languageId == TextLanguageAdapter.DefaultLangId) |
| | | { |
| | | GUI.backgroundColor = new Color(1f, 0.9f, 0.7f); |
| | | } |
| | | |
| | | m_FoldoutStates[languageId] = EditorGUILayout.Foldout(m_FoldoutStates[languageId], foldoutLabel, true); |
| | | GUI.backgroundColor = Color.white; |
| | | |
| | | if (m_FoldoutStates[languageId]) |
| | | { |
| | | EditorGUI.indentLevel++; |
| | | LanguageConfigItem config = adapter.LanguageConfigs.Get(languageId); |
| | | if (config != null) |
| | | { |
| | | DrawConfigItem(config); |
| | | EditorGUILayout.Space(); |
| | | DrawConfigItemActions(adapter, languageId); |
| | | } |
| | | EditorGUI.indentLevel--; |
| | | } |
| | | |
| | | EditorGUI.indentLevel--; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 绘制 RectTransform 和指定的文本适配属性 |
| | | /// </summary> |
| | | private void DrawConfigItem(LanguageConfigItem config) |
| | | { |
| | | // 1. RectTransform 配置 |
| | | EditorGUILayout.LabelField("RectTransform 配置", EditorStyles.miniBoldLabel); |
| | | EditorGUI.BeginChangeCheck(); |
| | | |
| | | config.anchoredPosition = EditorGUILayout.Vector2Field("Anchored Position", config.anchoredPosition); |
| | | config.sizeDelta = EditorGUILayout.Vector2Field("Size Delta", config.sizeDelta); |
| | | config.anchorMin = EditorGUILayout.Vector2Field("Anchor Min", config.anchorMin); |
| | | config.anchorMax = EditorGUILayout.Vector2Field("Anchor Max", config.anchorMax); |
| | | config.pivot = EditorGUILayout.Vector2Field("Pivot", config.pivot); |
| | | config.localScale = EditorGUILayout.Vector3Field("Local Scale", config.localScale); |
| | | config.localRotation = EditorGUILayout.Vector3Field("Local Rotation", config.localRotation); |
| | | EditorGUILayout.Space(); |
| | | |
| | | // 2. 文本排版与适配配置 |
| | | EditorGUILayout.LabelField("文本排版与适配配置", EditorStyles.miniBoldLabel); |
| | | config.font = (Font)EditorGUILayout.ObjectField("Font", config.font, typeof(Font), false); |
| | | config.fontStyle = (FontStyle)EditorGUILayout.EnumPopup("Font Style", config.fontStyle); |
| | | config.fontSize = EditorGUILayout.IntField("Font Size", config.fontSize); |
| | | config.lineSpacing = EditorGUILayout.FloatField("Line Spacing", config.lineSpacing); |
| | | config.alignment = (TextAnchor)EditorGUILayout.EnumPopup("Alignment", config.alignment); |
| | | config.alignByGeometry = EditorGUILayout.Toggle("Align By Geometry", config.alignByGeometry); |
| | | config.horizontalOverflow = (HorizontalWrapMode)EditorGUILayout.EnumPopup("Horizontal Overflow", config.horizontalOverflow); |
| | | config.verticalOverflow = (VerticalWrapMode)EditorGUILayout.EnumPopup("Vertical Overflow", config.verticalOverflow); |
| | | config.resizeTextForBestFit = EditorGUILayout.Toggle("Best Fit", config.resizeTextForBestFit); |
| | | |
| | | if (config.resizeTextForBestFit) |
| | | { |
| | | EditorGUI.indentLevel++; |
| | | config.resizeTextMinSize = EditorGUILayout.IntField("Min Size", config.resizeTextMinSize); |
| | | config.resizeTextMaxSize = EditorGUILayout.IntField("Max Size", config.resizeTextMaxSize); |
| | | EditorGUI.indentLevel--; |
| | | } |
| | | |
| | | if (EditorGUI.EndChangeCheck()) |
| | | { |
| | | EditorUtility.SetDirty(target); |
| | | } |
| | | } |
| | | |
| | | private void DrawConfigItemActions(TextLanguageAdapter adapter, string languageId) |
| | | { |
| | | EditorGUILayout.BeginHorizontal(); |
| | | GUILayout.Space(EditorGUI.indentLevel * 15f); // 补偿 GUILayout 忽略 indentLevel 的问题 |
| | | |
| | | if (GUILayout.Button("从当前读取", GUILayout.Width(80))) |
| | | { |
| | | Undo.RecordObject(adapter, "Read Current Config"); |
| | | adapter.ReadCurrentToConfig(languageId); |
| | | } |
| | | |
| | | if (GUILayout.Button("应用", GUILayout.Width(60))) |
| | | { |
| | | Undo.RecordObject(adapter, "Apply Config"); |
| | | adapter.ApplyConfig(languageId); |
| | | } |
| | | |
| | | bool isDefault = languageId == TextLanguageAdapter.DefaultLangId; |
| | | |
| | | if (!isDefault) |
| | | { |
| | | if (GUILayout.Button("复制到默认", GUILayout.Width(80))) |
| | | { |
| | | Undo.RecordObject(adapter, "Copy to Default"); |
| | | adapter.SetConfig(TextLanguageAdapter.DefaultLangId, adapter.LanguageConfigs.Get(languageId)?.Clone()); |
| | | } |
| | | } |
| | | |
| | | // Default 不可删除 |
| | | GUI.enabled = !isDefault; |
| | | if (GUILayout.Button("删除", GUILayout.Width(50))) |
| | | { |
| | | Undo.RecordObject(adapter, "Remove Config"); |
| | | adapter.RemoveConfig(languageId); |
| | | m_FoldoutStates.Remove(languageId); |
| | | } |
| | | GUI.enabled = true; |
| | | |
| | | EditorGUILayout.EndHorizontal(); |
| | | } |
| | | |
| | | private void DrawAddLanguageConfig(TextLanguageAdapter adapter) |
| | | { |
| | | // === 添加预设语言 === |
| | | EditorGUILayout.BeginHorizontal(); |
| | | GUILayout.Space(15f); |
| | | EditorGUILayout.LabelField("添加预设语言:", GUILayout.Width(100)); |
| | | |
| | | // Inspector 面板的可用总宽度 (减去右侧滚动条的大致宽度) |
| | | float viewWidth = EditorGUIUtility.currentViewWidth - 30f; |
| | | float currentWidth = 115f; // 起始宽度:15(Space) + 100(LabelWidth) |
| | | float buttonWidth = 64f; // 按钮宽度 60 + 默认边距大约 4 |
| | | |
| | | for (int i = 0; i < m_PresetLanguageIds.Length; i++) |
| | | { |
| | | string langId = m_PresetLanguageIds[i]; |
| | | if (!adapter.HasConfig(langId)) |
| | | { |
| | | // 检测当前行是否放得下下一个按钮 |
| | | if (currentWidth + buttonWidth > viewWidth) |
| | | { |
| | | // 放不下,结束当前行,开启新的一行 |
| | | EditorGUILayout.EndHorizontal(); |
| | | EditorGUILayout.BeginHorizontal(); |
| | | |
| | | // 新行为了美观,缩进对齐上面的按钮 |
| | | GUILayout.Space(115f); |
| | | currentWidth = 115f; |
| | | } |
| | | |
| | | if (GUILayout.Button(m_PresetLanguageNames[i], GUILayout.Width(60))) |
| | | { |
| | | CreateNewLanguageConfig(adapter, langId); |
| | | } |
| | | |
| | | // 累加当前行的宽度 |
| | | currentWidth += buttonWidth; |
| | | } |
| | | } |
| | | EditorGUILayout.EndHorizontal(); |
| | | |
| | | EditorGUILayout.Space(2f); |
| | | |
| | | // === 添加自定义语言 === |
| | | EditorGUILayout.BeginHorizontal(); |
| | | GUILayout.Space(15f); |
| | | EditorGUILayout.LabelField("自定义语言ID:", GUILayout.Width(100)); |
| | | m_CopySourceLanguageId = EditorGUILayout.TextField(m_CopySourceLanguageId, GUILayout.Width(80)); |
| | | |
| | | if (GUILayout.Button("添加", GUILayout.Width(50))) |
| | | { |
| | | string newLangId = m_CopySourceLanguageId.Trim(); |
| | | if (!string.IsNullOrEmpty(newLangId) && !adapter.HasConfig(newLangId)) |
| | | { |
| | | CreateNewLanguageConfig(adapter, newLangId); |
| | | m_CopySourceLanguageId = ""; |
| | | GUI.FocusControl(null); |
| | | } |
| | | } |
| | | EditorGUILayout.EndHorizontal(); |
| | | } |
| | | |
| | | /// <summary> 辅助方法:封装新建语言配置的复用逻辑 </summary> |
| | | private void CreateNewLanguageConfig(TextLanguageAdapter adapter, string langId) |
| | | { |
| | | Undo.RecordObject(adapter, "Add Language Config"); |
| | | LanguageConfigItem newConfig = adapter.HasConfig(TextLanguageAdapter.DefaultLangId) |
| | | ? adapter.LanguageConfigs.Get(TextLanguageAdapter.DefaultLangId).Clone() |
| | | : new LanguageConfigItem(); |
| | | |
| | | adapter.SetConfig(langId, newConfig); |
| | | m_FoldoutStates[langId] = true; // 自动展开新添加的项 |
| | | } |
| | | } |