using System.Collections.Generic; using System.Text; using AlicizaX.Editor; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; using UnityEditorInternal; namespace AlicizaX.Localization.Editor { internal class LocalizationSettingsProvider : UnityEditor.SettingsProvider { private SerializedObject _serializedObject; private SerializedProperty _languageTypes; private ReorderableList _languageList; private SerializedProperty _genLangaugeTypePath; private SerializedProperty generateScriptCodeFirstConfig; private List popConfig = new List(); public LocalizationSettingsProvider() : base("Project/Localization Settings", SettingsScope.Project) { } public override void OnActivate(string searchContext, VisualElement rootElement) { InitGUI(); } private void InitGUI() { var setting = LocalizationConfiguration.Instance; _serializedObject?.Dispose(); _serializedObject = new SerializedObject(setting); _languageTypes = _serializedObject.FindProperty("LanguageTypes"); _genLangaugeTypePath = _serializedObject.FindProperty("_genLangaugeTypePath"); generateScriptCodeFirstConfig = _serializedObject.FindProperty("generateScriptCodeFirstConfig"); // 自定义 ReorderableList _languageList = new ReorderableList(_serializedObject, _languageTypes, draggable: false, displayHeader: true, displayAddButton: true, displayRemoveButton: true); _languageList.drawHeaderCallback = rect => { EditorGUI.LabelField(rect, "Language Types"); }; _languageList.drawElementCallback = (rect, index, isActive, isFocused) => { var element = _languageTypes.GetArrayElementAtIndex(index); rect.y += 2; if (index < 2) // 前两个(中文、英文)禁止修改 { EditorGUI.BeginDisabledGroup(true); EditorGUI.TextField( new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element.stringValue); EditorGUI.EndDisabledGroup(); } else { element.stringValue = EditorGUI.TextField( new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element.stringValue); } }; // 禁止删除前两个 _languageList.onCanRemoveCallback = list => { return list.index >= 2; // 只有索引 >=2 的项才能删除 }; popConfig.Clear(); if (setting.LanguageTypeNames.Count > 0) { foreach (var lang in setting.LanguageTypeNames) { string name = lang.Or("Unknown"); popConfig.Add(name); } } } public override void OnGUI(string searchContext) { if (_serializedObject == null || !_serializedObject.targetObject) { InitGUI(); } _serializedObject.Update(); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_genLangaugeTypePath); EditorDrawing.DrawStringSelectPopup(new GUIContent("Gen Lang"), new GUIContent("None"), popConfig.ToArray(), generateScriptCodeFirstConfig.stringValue, (e) => { generateScriptCodeFirstConfig.stringValue = e; _serializedObject.ApplyModifiedProperties(); LocalizationConfiguration.Save(); }); if (GUILayout.Button("Generate Language Types")) { RegenerateLanguageTypes(); } _languageList.DoLayoutList(); if (EditorGUI.EndChangeCheck()) { _serializedObject.ApplyModifiedProperties(); LocalizationConfiguration.Save(); } } private void RegenerateLanguageTypes() { StringBuilder sb = new StringBuilder(); sb.AppendLine("using System.Collections.Generic;"); sb.AppendLine(""); sb.AppendLine("/// "); sb.AppendLine("/// AutoGenerate"); sb.AppendLine("/// "); sb.AppendLine("public static class LanguageTypes"); sb.AppendLine("{"); sb.AppendLine("\tpublic static readonly IReadOnlyList Types = new List"); sb.AppendLine("\t{"); for (int i = 0; i < LocalizationConfiguration.Instance.LanguageTypeNames.Count; i++) { sb.AppendLine($"\t\t\"{LocalizationConfiguration.Instance.LanguageTypeNames[i]}\","); } sb.AppendLine("\t};"); sb.AppendLine(""); sb.AppendLine("\tpublic static string IndexToString(int index)"); sb.AppendLine("\t{"); sb.AppendLine("\t\tif (index < 0 || index >= Types.Count) return \"Unknown\";"); sb.AppendLine("\t\treturn Types[index];"); sb.AppendLine("\t}"); sb.AppendLine(""); sb.AppendLine("\tpublic static int StringToIndex(string s)"); sb.AppendLine("\t{"); sb.AppendLine("\t\tint index = -1;"); sb.AppendLine("\t\tfor (int i = 0; i < Types.Count; i++)"); sb.AppendLine("\t\t{"); sb.AppendLine("\t\t\tif (Types[i] == s)"); sb.AppendLine("\t\t\t{"); sb.AppendLine("\t\t\t\tindex = i;"); sb.AppendLine("\t\t\t\tbreak;"); sb.AppendLine("\t\t\t}"); sb.AppendLine("\t\t}"); sb.AppendLine(""); sb.AppendLine("\t\treturn index;"); sb.AppendLine("\t}"); sb.AppendLine(""); sb.AppendLine("}"); System.IO.File.WriteAllText(_genLangaugeTypePath.stringValue, sb.ToString()); AssetDatabase.Refresh(); } public override void OnDeactivate() { base.OnDeactivate(); LocalizationConfiguration.Save(); } static LocalizationSettingsProvider s_provider; [SettingsProvider] public static SettingsProvider CreateMyCustomSettingsProvider() { if (s_provider == null) { s_provider = new LocalizationSettingsProvider(); } return s_provider; } } }