using System; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.TextCore.LowLevel; using UnityEngine.TextCore.Text; using UnityEngine.UIElements; namespace Ironspore.Editor { public static class LocalizationBuilder { public const string CatalogPath = "Assets/Game/Localization/LocalizationCatalog.asset"; const string FontPath = "Assets/ThirdParty/Adobe/NotoSansSC/NotoSansSC-VF.ttf"; const string FontAssetPath = "Assets/Game/UI/Fonts/GameFont.asset"; [MenuItem("Ironspore/Configure Localization")] public static string Configure() { if (EditorApplication.isPlaying) throw new InvalidOperationException("Stop play mode before configuring localization."); Directory.CreateDirectory("Assets/Game/UI/Fonts"); AssetDatabase.Refresh(); var importer = AssetImporter.GetAtPath(FontPath) as TrueTypeFontImporter; if (!importer) throw new FileNotFoundException("Archived OFL font has not imported.", FontPath); importer.fontTextureCase = FontTextureCase.Dynamic; importer.fontSize = 40; importer.includeFontData = true; importer.SaveAndReimport(); var font = AssetDatabase.LoadAssetAtPath(FontPath); var catalog = AssetDatabase.LoadAssetAtPath(CatalogPath); if (!catalog) { catalog = ScriptableObject.CreateInstance(); AssetDatabase.CreateAsset(catalog, CatalogPath); } catalog.locales = new[] { new GameLocale { code = "zh-Hans", nativeName = "简体中文", table = AssetDatabase.LoadAssetAtPath("Assets/Game/Localization/Tables/zh-Hans.json") }, new GameLocale { code = "en", nativeName = "English", table = AssetDatabase.LoadAssetAtPath("Assets/Game/Localization/Tables/en.json") } }; var uiFont = AssetDatabase.LoadAssetAtPath(FontAssetPath); if (!uiFont) { uiFont = FontAsset.CreateFontAsset(font, 64, 7, GlyphRenderMode.SDFAA, 2048, 2048, AtlasPopulationMode.Dynamic, true); uiFont.name = "GameFont"; AssetDatabase.CreateAsset(uiFont, FontAssetPath); uiFont.material.name = "GameFont Material"; AssetDatabase.AddObjectToAsset(uiFont.material, uiFont); } uiFont.isMultiAtlasTexturesEnabled = true; var characters = new HashSet(Enumerable.Range(32, 95).Select(x => (char)x)); foreach (var locale in catalog.locales) { foreach (char c in locale.nativeName) characters.Add(c); foreach (var entry in GameLocalization.ReadTable(locale.table)) foreach (char c in entry.Value) if (!char.IsControl(c)) characters.Add(c); } string absent; uiFont.TryAddCharacters(new string(characters.OrderBy(x => x).ToArray()), out absent); if (!string.IsNullOrEmpty(absent)) throw new InvalidOperationException("Font is missing required glyphs: " + absent); foreach (var atlas in uiFont.atlasTextures) { if (!atlas || AssetDatabase.Contains(atlas)) continue; atlas.name = "GameFont Atlas"; AssetDatabase.AddObjectToAsset(atlas, uiFont); } EditorUtility.SetDirty(uiFont); catalog.worldFont = font; catalog.uiFont = uiFont; EditorUtility.SetDirty(catalog); var textSettings = AssetDatabase.LoadAssetAtPath("Assets/Game/UI/Fonts/GameTextSettings.asset"); if (!textSettings) { textSettings = ScriptableObject.CreateInstance(); AssetDatabase.CreateAsset(textSettings, "Assets/Game/UI/Fonts/GameTextSettings.asset"); } textSettings.fallbackFontAssets = new List { uiFont }; textSettings.clearDynamicDataOnBuild = false; EditorUtility.SetDirty(textSettings); var panel = AssetDatabase.LoadAssetAtPath("Assets/Game/UI/GamePanelSettings.asset"); panel.textSettings = textSettings; EditorUtility.SetDirty(panel); string previousScene = EditorSceneManager.GetActiveScene().path; foreach (string name in new[] { "Bootstrap", "MechTestRange", "WarzonePrototype" }) { var scene = EditorSceneManager.OpenScene("Assets/Scenes/" + name + ".unity"); var session = UnityEngine.Object.FindAnyObjectByType(); session.localization = catalog; EditorUtility.SetDirty(session); EditorSceneManager.MarkSceneDirty(scene); EditorSceneManager.SaveScene(scene); } AssetDatabase.SaveAssets(); EditorSceneManager.OpenScene(string.IsNullOrEmpty(previousScene) ? "Assets/Scenes/Bootstrap.unity" : previousScene); return "Configured two locales, " + characters.Count + " glyphs, UI Toolkit and TextMesh fonts, and all three scenes."; } } }