com.alicizax.unity.editor.e.../Editor/ToolBarExtension/New/LocalizationToolbarDropdown.cs

162 lines
5.1 KiB
C#
Raw Normal View History

2026-04-07 19:50:38 +08:00
#if UNITY_6000_3_OR_NEWER
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AlicizaX.Localization.Editor;
using AlicizaX.Localization.Runtime;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEditor.Toolbars;
using UnityEngine;
namespace AlicizaX.Editor.Extension
{
[InitializeOnLoad]
public static class LocalizationToolbarDropdown
{
private const string ElementPath = "AlicizaX/Localization";
private const string Tooltip = "Switch editor localization preview language";
private static readonly Texture2D SettingsIcon;
private static string s_LastKnownLanguage;
static LocalizationToolbarDropdown()
{
SettingsIcon = GetIcon("Settings");
s_LastKnownLanguage = GetSelectedLanguage();
EditorApplication.update += RefreshWhenLanguageChanges;
}
[MainToolbarElement(ElementPath, defaultDockPosition = MainToolbarDockPosition.Right, defaultDockIndex = 0)]
public static MainToolbarElement CreateElement()
{
return new MainToolbarDropdown(
new MainToolbarContent(GetToolbarLabel(), SettingsIcon, Tooltip),
ShowDropdownMenu);
}
private static void RefreshWhenLanguageChanges()
{
var selectedLanguage = GetSelectedLanguage();
if (selectedLanguage == s_LastKnownLanguage)
{
return;
}
s_LastKnownLanguage = selectedLanguage;
MainToolbar.Refresh(ElementPath);
}
private static void ShowDropdownMenu(Rect dropdownRect)
{
var selectedLanguage = GetSelectedLanguage();
var menu = new GenericMenu();
var languageNames = GetLanguageTypeNames();
if (languageNames.Count == 0)
{
menu.AddDisabledItem(new GUIContent("No language options"));
menu.DropDown(dropdownRect);
return;
}
foreach (var languageName in languageNames)
{
var capturedLanguageName = languageName;
menu.AddItem(
new GUIContent(capturedLanguageName),
string.Equals(selectedLanguage, capturedLanguageName, StringComparison.Ordinal),
() => SetSelectedLanguage(capturedLanguageName));
}
menu.DropDown(dropdownRect);
}
private static void SetSelectedLanguage(string languageName)
{
EditorPrefs.SetString(LocalizationComponent.PrefsKey, languageName);
s_LastKnownLanguage = languageName;
InvokeOnValidateInScene();
MainToolbar.Refresh(ElementPath);
}
private static IReadOnlyList<string> GetLanguageTypeNames()
{
return LocalizationConfiguration.Instance != null
? LocalizationConfiguration.Instance.LanguageTypeNames
: Array.Empty<string>();
}
private static string GetSelectedLanguage()
{
return EditorPrefs.GetString(LocalizationComponent.PrefsKey, "None");
}
private static string GetToolbarLabel()
{
return GetSelectedLanguage();
}
private static void InvokeOnValidateInScene()
{
var targetType = FindType("UnityEngine.UI.UXTextMeshPro");
if (targetType == null)
{
Debug.LogWarning("Could not find type UnityEngine.UI.UXTextMeshPro.");
return;
}
var onValidateMethod = targetType.GetMethod(
"OnValidate",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (onValidateMethod == null)
{
Debug.LogWarning($"Could not find OnValidate on {targetType.Name}.");
return;
}
var components = GameObject.FindObjectsOfType(targetType)
.OfType<Component>()
.ToList();
if (components.Count == 0)
{
return;
}
var sceneToMarkDirty = EditorSceneManager.GetActiveScene();
foreach (var component in components)
{
Undo.RecordObject(component, "Invoke OnValidate");
onValidateMethod.Invoke(component, null);
EditorUtility.SetDirty(component);
}
EditorSceneManager.MarkSceneDirty(sceneToMarkDirty);
}
private static Type FindType(string fullName)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var type = assembly.GetType(fullName);
if (type != null)
{
return type;
}
}
return null;
}
private static Texture2D GetIcon(string iconName)
{
return EditorGUIUtility.IconContent(iconName).image as Texture2D;
}
}
}
#endif