using Cryville.Common.Font; using Cryville.Culture; using System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using TMPro; using UnityEngine; using UnityEngine.TextCore.LowLevel; using UnityEngine.TextCore.Text; namespace Cryville.Common.Unity.UI { [RequireComponent(typeof(TextMeshProUGUI))] public class TMPAutoFont : MonoBehaviour { public static Shader DefaultShader; public static FontMatcher FontMatcher; public static int MaxFallbackCount = 4; static FontAsset _font; TextMeshProUGUI _text; [SerializeField] Shader m_shader; void Awake() { if (FontMatcher == null) return; _text = GetComponent(); if (_font == null) { foreach (var typeface in FontMatcher.MatchLanguage(new LanguageId(CultureInfo.CurrentCulture.Name), true)) { try { var ifont = CreateFontAsset(typeface.File.FullName, typeface.IndexInFile); if (m_shader) ifont.material.shader = m_shader; else if (DefaultShader) ifont.material.shader = DefaultShader; if (_font == null) { _font = ifont; Shared.Logger.Log(1, "UI", "Using main font: {0}", typeface.FullName); if (MaxFallbackCount <= 0) break; } else { _font.fallbackFontAssetTable ??= new List(); _font.fallbackFontAssetTable.Add(ifont); Shared.Logger.Log(1, "UI", "Using fallback font #{0}: {1}", _font.fallbackFontAssetTable.Count, typeface.FullName); if (_font.fallbackFontAssetTable.Count >= MaxFallbackCount) break; } } catch (Exception) { } } } _text.font = _font; } static MethodInfo _methodCreateFontAsset; static readonly object[] _paramsCreateFontAsset = new object[] { null, null, 90, 9, GlyphRenderMode.SDFAA, 1024, 1024, Type.Missing, Type.Missing }; static FontAsset CreateFontAsset(string path, int index) { if (_methodCreateFontAsset == null) { _methodCreateFontAsset = typeof(FontAsset).GetMethod( "CreateFontAsset", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(string), typeof(int), typeof(int), typeof(int), typeof(GlyphRenderMode), typeof(int), typeof(int), typeof(AtlasPopulationMode), typeof(bool) }, null ); } _paramsCreateFontAsset[0] = path; _paramsCreateFontAsset[1] = index; return (FontAsset)_methodCreateFontAsset.Invoke(null, _paramsCreateFontAsset); } } }