using System.Collections.Generic; using UnityEditor; using UnityEngine; using System.IO; using TMPro; using System; using UnityEngine.TextCore.LowLevel; using TMPro.EditorUtilities; using Object = UnityEngine.Object; using System.Reflection; namespace BFEditor.Resource { public class TMPTools { #region GenTMPFontAsset - version 1.4.1 private const int FontSize = 32; private const int Padding = 4; private const GlyphRenderMode GRenderMode = GlyphRenderMode.SDFAA; private const string tmpFontsPath = "Assets/arts/fonts/tmpfonts/"; private const string subFontPath = "/tmpfont"; private const string subTTFPath = "/tmpfont"; private const string AssetCNName = "font_cn_sdf.asset"; private const string AssetDefaultName = "font_sdf.asset"; private const string AssetNumberName = "font_number_sdf.asset"; private const string AssetBattleName = "font_battle_sdf.asset"; private const string AssetThaiName = "font_thai_sdf.asset"; private const string AssetJaName = "font_ja_sdf.asset"; private const string DevStrPath = "Assets/Editor/BFResourceTools/FontTools/cn_3900.txt"; private const string CommonCNWordsPath = "Assets/Editor/BFResourceTools/FontTools/cn_1200.txt"; private const string CommonZHWordsPath = "Assets/Editor/BFResourceTools/FontTools/zh_1200.txt"; private const string commonStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789¥…()—:”“‘《》?、·!【】;’,。+-*/`-=!@#$%^&*()_+[];',.\\~{}|:<>?\" "; private const string defaultFontPath = "Assets/arts/fonts/tmpfonts/default/tmpfont/font_sdf.asset"; private class TTFInfo { public string language; public string fontFolder; public string ttfPath; public int atlasSize; public List wordsPath; public TTFInfo(string language, int atlasSize, List words) { this.language = language; fontFolder = tmpFontsPath + language + subFontPath; ttfPath = tmpFontsPath + language + subTTFPath; this.atlasSize = atlasSize; wordsPath = new List(); if (words != null) { foreach (var word in words) { var tmp = Application.dataPath + "/Developer/lua/app/config/strings/" + word; wordsPath.Add(tmp); } } } public TTFInfo(string language, string fontFolder, string ttfPath, int atlasSize, List wordsPath) { this.language = language; this.fontFolder = fontFolder; this.ttfPath = ttfPath; this.atlasSize = atlasSize; this.wordsPath = wordsPath; } } private static List ttfInfos = new List() { new TTFInfo("en", 512, new List(){"en"}), new TTFInfo("cn", 2048, new List(){"cn"}), // new TTFInfo("fr", 512, new List(){"fr"}), // new TTFInfo("de", 512, new List(){"de"}), // new TTFInfo("it", 512, new List(){"it"}), // new TTFInfo("ms", 512, new List(){"ms"}), // new TTFInfo("pt", 512, new List(){"pt"}), // new TTFInfo("es", 512, new List(){"es"}), // new TTFInfo("tr", 512, new List(){"tr"}), new TTFInfo("id", 512, new List(){"id"}), new TTFInfo("ru", 512, new List(){"ru"}), // new TTFInfo("kr", 512, new List(){"kr"}), new TTFInfo("zh", 2048, new List(){"zh"}), new TTFInfo("th", 512, new List(){"th"}), // new TTFInfo("ja", 512, new List(){"ja"}), new TTFInfo("vi", 512, new List(){"vi"}), }; #if UNITY_EDITOR_OSX private static bool ProgramerOrDesigner = true; #else private static bool ProgramerOrDesigner = false; #endif static public void GenFormalFontAsset(bool isdevelop) { Debug.Log("[bfinfo]生成TMP字体..."); GenAllTMPFontAsset(isdevelop); } static private void GenAllTMPFontAsset(bool isdevelop) { // foreach (var ttfInfo in ttfInfos) // { // var dir = new DirectoryInfo(ttfInfo.ttfPath); // var allFiles = dir.GetFiles("*", SearchOption.AllDirectories); // if (null != allFiles) // { // foreach (var ttfPath in allFiles) // { // var fullName = ttfPath.FullName; // if (fullName.ToLower().EndsWith(".ttf") || fullName.ToLower().EndsWith(".otf")) // { // var path = BF.Utils.GetAssetPathByFullPath(fullName); // var font = AssetDatabase.LoadAssetAtPath(path); // if (!font) // { // Debug.LogError("Can't find font sourcefile !"); // continue; // } // if(fullName.IndexOf("title") != -1) // { // GenTMPFontAsset(font, ttfInfo, AssetNumberName, false, false); // } // else // { // GenTMPFontAsset(font, ttfInfo, AssetDefaultName, false, false); // } // } // } // } // } // var atlasSize = isdevelop ? 4096 : 256; // 常用中文 // var defaultCNFont = AssetDatabase.LoadAssetAtPath("Assets/arts/fonts/tmpfonts/default/tmpfont/font_cn.TTF"); // GenTMPFontAsset(defaultCNFont, new TTFInfo("cn", "Assets/arts/fonts/tmpfonts/default/tmpfont", "Assets/arts/fonts/tmpfonts/default/tmpfont", 256, new List()), AssetCNName, isdevelop); // 常用 var defaultFont = AssetDatabase.LoadAssetAtPath("Assets/arts/fonts/tmpfonts/default/tmpfont/font_default.TTF"); GenTMPFontAsset(defaultFont, new TTFInfo("cn", "Assets/arts/fonts/tmpfonts/default/tmpfont", "Assets/arts/fonts/tmpfonts/default/tmpfont", 2048, new List()), AssetDefaultName, isdevelop); // 数字用 var defaultNumberFont = AssetDatabase.LoadAssetAtPath("Assets/arts/fonts/tmpfonts/default/tmpfont/font_number.TTF"); GenTMPFontAsset(defaultNumberFont, new TTFInfo("cn", "Assets/arts/fonts/tmpfonts/default/tmpfont", "Assets/arts/fonts/tmpfonts/default/tmpfont", 256, new List()), AssetNumberName, isdevelop); // 泰语 var thaiFont = AssetDatabase.LoadAssetAtPath("Assets/arts/fonts/tmpfonts/default/tmpfont/font_thai.ttf"); GenTMPFontAsset(thaiFont, new TTFInfo("cn", "Assets/arts/fonts/tmpfonts/default/tmpfont", "Assets/arts/fonts/tmpfonts/default/tmpfont", 512, new List()), AssetThaiName, isdevelop); // 日语 // var jaFont = AssetDatabase.LoadAssetAtPath("Assets/arts/fonts/tmpfonts/default/tmpfont/font_ja.ttf"); // GenTMPFontAsset(jaFont, new TTFInfo("cn", "Assets/arts/fonts/tmpfonts/default/tmpfont", "Assets/arts/fonts/tmpfonts/default/tmpfont", 512, new List()), AssetJaName, isdevelop); // 战斗用 // var battleFont = AssetDatabase.LoadAssetAtPath("Assets/arts/fonts/tmpfonts/battle/font_battle.ttf"); // GenTMPFontAsset(battleFont, new TTFInfo("cn", "Assets/arts/fonts/tmpfonts/battle", "Assets/arts/fonts/tmpfonts/battle", 1024, new List()), AssetBattleName, isdevelop); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } static private void GetWords(bool isDevelop, bool isDefaultFont, List luaFolderPaths, string language, out string words) { words = string.Empty; //是否开发模式 if (!isDevelop) { var text = LocalizationMenuTools.CatWordsFromLuaConfig(luaFolderPaths); foreach (var w in text) { if (!words.Contains(w.ToString())) words += w; } if(language.CompareTo("cn") != -1) { // 简体常用字 var textAsset = AssetDatabase.LoadAssetAtPath(CommonCNWordsPath); foreach (var w in textAsset.text) { if (!words.Contains(w.ToString())) words += w; } } else if(language.CompareTo("zh") != -1) { // 繁体常用字 var textAsset = AssetDatabase.LoadAssetAtPath(CommonZHWordsPath); foreach (var w in textAsset.text) { if (!words.Contains(w.ToString())) words += w; } } } else { // 常用字母和数字还有符号 foreach (var w in commonStr) { if (!words.Contains(w.ToString())) words += w; } var luaConfigText = LocalizationMenuTools.CatWordsFromLuaConfig(luaFolderPaths); foreach (var w in luaConfigText) { if (!words.Contains(w.ToString())) words += w; } if(isDefaultFont) { // 常用字 var textAsset = AssetDatabase.LoadAssetAtPath(DevStrPath); foreach (var w in textAsset.text) { if (!words.Contains(w.ToString())) words += w; } // 中文配置 var text = LocalizationMenuTools.CatWordsFromLuaConfig(new List(){Application.dataPath + "/Developer/lua/app/config/strings/cn"}); foreach (var w in text) { if (!words.Contains(w.ToString())) words += w; } } } } static private void GetThaiWords(List luaFolderPaths, out uint[] words) { words = new uint[128]; uint begin = 3584; //0E00-0E7F for (uint i = 0; i < 128; i++) { words[i] = begin + i; } } static private void GenTMPFontAsset(Font font, TTFInfo ttfInfo, string assetName, bool isdevelop) { EditorUtility.DisplayProgressBar("生成TMP字体", "正在生成中...", 0f); var assetDirPath = ttfInfo.fontFolder; var assetPath = Path.Combine(assetDirPath, assetName); var texturePath = assetPath.Replace(".asset", "_atlas.asset"); var matPath = assetPath.Replace(".asset", ".mat"); var fontAsset = AssetDatabase.LoadAssetAtPath(assetPath); if (!fontAsset) { if (!Directory.Exists(assetDirPath)) Directory.CreateDirectory(assetDirPath); var targetSize = ttfInfo.atlasSize; fontAsset = TMP_FontAsset.CreateFontAsset(font, FontSize, Padding, GRenderMode, targetSize, targetSize); AssetDatabase.CreateAsset(fontAsset, assetPath); var texture = fontAsset.atlasTextures[0]; texture.name = assetName.Replace(".asset", ".png"); if(File.Exists(texturePath)) { File.Delete(texturePath); } AssetDatabase.CreateAsset(texture, texturePath); fontAsset.atlasTextures[0] = AssetDatabase.LoadAssetAtPath(texturePath); var mat = fontAsset.material; mat.name = assetName.Replace(".asset", ".mat"); if(File.Exists(matPath)) { File.Delete(matPath); } AssetDatabase.CreateAsset(mat, matPath); fontAsset.material = AssetDatabase.LoadAssetAtPath(matPath); fontAsset.material.SetTexture(ShaderUtilities.ID_MainTex, texture); fontAsset.material.SetFloat(ShaderUtilities.ID_TextureWidth, targetSize); fontAsset.material.SetFloat(ShaderUtilities.ID_TextureHeight, targetSize); fontAsset.material.SetFloat(ShaderUtilities.ID_GradientScale, Padding + 1); fontAsset.ReadFontAssetDefinition(); } else { fontAsset.atlasPopulationMode = AtlasPopulationMode.Dynamic; //设置成动态 AddSourceFontRef(assetPath, font); UpdateFontAsset(fontAsset, font, assetDirPath, ttfInfo.atlasSize); fontAsset.ClearFontAssetData(); EditorUtility.SetDirty(fontAsset); } // 泰语使用静态并特殊处理 if (assetName == AssetThaiName) { var luaFolderPaths = new List(); luaFolderPaths.Add(Application.dataPath + "/Developer/lua/app/config/strings/th"); var words = new uint[128];//泰语 GetThaiWords(luaFolderPaths, out words); Debug.Log("泰语字符集:" + words); fontAsset.TryAddCharacters(words); fontAsset.atlasPopulationMode = AtlasPopulationMode.Static; // 修订部分重音位置 _Adjust(fontAsset); } if (null != fontAsset) { // DealWithMetric(fontAsset); var fontssetPath = AssetDatabase.GetAssetPath(fontAsset); AssetDatabase.ImportAsset(fontssetPath); // DeleteSourceFontRef(fontssetPath); fontAsset.fallbackFontAssetTable.Clear(); if(assetName == AssetDefaultName) { var fallbackAsset = AssetDatabase.LoadAssetAtPath(Path.Combine(assetDirPath, AssetThaiName)); if (fallbackAsset != null) { fontAsset.fallbackFontAssetTable.Add(fallbackAsset); } // fallbackAsset = AssetDatabase.LoadAssetAtPath(Path.Combine(assetDirPath, AssetJaName)); // if (fallbackAsset != null) // { // fontAsset.fallbackFontAssetTable.Add(fallbackAsset); // } } } EditorUtility.ClearProgressBar(); } static void DeleteSourceFontRef(string path) { var fontAsset = AssetDatabase.LoadAssetAtPath(path); if (fontAsset != null) { var assetInfo = new SerializedObject(fontAsset); var property = assetInfo.FindProperty("m_SourceFontFileGUID"); property.stringValue = null; var property2 = assetInfo.FindProperty("m_SourceFontFile_EditorRef"); property2.objectReferenceValue = null; var property3 = assetInfo.FindProperty("m_SourceFontFile"); property3.objectReferenceValue = null; assetInfo.ApplyModifiedProperties(); EditorUtility.SetDirty(fontAsset); } } static void AddSourceFontRef(string path, Font font) { var fontAsset = AssetDatabase.LoadAssetAtPath(path); if (fontAsset != null) { string guid; long localID; UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(font, out guid, out localID); var assetInfo = new SerializedObject(fontAsset); var property = assetInfo.FindProperty("m_SourceFontFileGUID"); property.stringValue = guid; var property2 = assetInfo.FindProperty("m_SourceFontFile_EditorRef"); property2.objectReferenceValue = font; var property3 = assetInfo.FindProperty("m_SourceFontFile"); property3.objectReferenceValue = font; assetInfo.ApplyModifiedProperties(); } } static private void UpdateFontAsset(TMP_FontAsset fontAsset, Font font, string assetDirPath, int tarAtlasSize) { var targetSize = tarAtlasSize; var oldFontSize = fontAsset.faceInfo.pointSize; if (oldFontSize != FontSize) { FontEngine.LoadFontFace(font, FontSize); var Type = fontAsset.GetType(); var f = Type.GetProperty("faceInfo"); f.SetValue(fontAsset, FontEngine.GetFaceInfo()); } var altasSize = fontAsset.atlasWidth; var altasPadding = fontAsset.atlasPadding; if (altasSize != targetSize || altasPadding != Padding) { var Type = fontAsset.GetType(); var w = Type.GetProperty("atlasWidth"); w.SetValue(fontAsset, targetSize); var h = Type.GetProperty("atlasHeight"); h.SetValue(fontAsset, targetSize); var p = Type.GetProperty("atlasPadding"); p.SetValue(fontAsset, Padding); fontAsset.material.SetFloat(ShaderUtilities.ID_TextureWidth, targetSize); fontAsset.material.SetFloat(ShaderUtilities.ID_TextureHeight, targetSize); fontAsset.material.SetFloat(ShaderUtilities.ID_GradientScale, Padding + 1); } //keep update Material[] materialPresets = TMP_EditorUtility.FindMaterialReferences(fontAsset); for (int i = 0; i < materialPresets.Length; i++) { Material mat = materialPresets[i]; var path = AssetDatabase.GetAssetPath(mat); if (!path.Contains(assetDirPath)) continue; BF.BFLog.Log("UpdateFontAsset material " + path); mat.SetFloat(ShaderUtilities.ID_TextureWidth, targetSize); mat.SetFloat(ShaderUtilities.ID_TextureHeight, targetSize); mat.SetFloat(ShaderUtilities.ID_GradientScale, Padding + 1); } var renderMode = fontAsset.atlasRenderMode; if (renderMode != GRenderMode) { var Type = fontAsset.GetType(); var r = Type.GetProperty("altasRenderMode"); r.SetValue(fontAsset, GRenderMode); } } /// /// 对于一些特定的字符进行布局调整 /// /// static private void DealWithMetric(TMP_FontAsset fontAsset) { //数字"1" if (fontAsset.characterLookupTable.ContainsKey(0x31)) { var character = fontAsset.characterLookupTable[0x31]; var metrics = character.glyph.metrics; metrics.horizontalBearingX = 4f; metrics.horizontalAdvance = 19f; character.glyph.metrics = metrics; } } #endregion #region TransforFontAssets /// /// 设置所有prefab的FontAssets /// /// /// /// static public void TransforAllFontAsset() { var filter = "Assets/prefabs/ui/"; string[] guids = AssetDatabase.FindAssets("t:prefab", new string[] { }); foreach (string guid in guids) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); if (assetPath.Contains(filter)) { var obj = Object.Instantiate(AssetDatabase.LoadAssetAtPath(assetPath)); TransforFontAsset(obj, assetPath); Object.DestroyImmediate(obj); } } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } static private void TransforFontAsset(GameObject selectObj, string assetPath = "", bool keepHierachy = false) { if (null == selectObj) return; var fakeParent = EditorUtility.GetPrefabParent(selectObj); var parent = PrefabUtility.GetNearestPrefabInstanceRoot(selectObj); parent = parent == null ? selectObj : parent; //处理一层结构 assetPath = string.IsNullOrEmpty(assetPath) ? AssetDatabase.GetAssetPath(fakeParent) : assetPath; var childPath = string.Empty; BF.Utils.GetTransformPath(selectObj.transform, parent.transform, ref childPath); var index = childPath.IndexOf("/"); childPath = childPath.Substring(index + 1, childPath.Length - index - 1); var tmpComs = parent.GetComponentsInChildren(true); if (null != tmpComs) { var replace = false; foreach (var com in tmpComs) { string desPath = string.Empty; string srcPath = AssetDatabase.GetAssetPath(com.font); TMP_FontAsset targetFont; targetFont = AssetDatabase.LoadAssetAtPath(defaultFontPath); if (targetFont && com.font != targetFont) { var matName = com.fontSharedMaterial.name; var matPath = ""; targetFont = AssetDatabase.LoadAssetAtPath(defaultFontPath); matPath = "Assets/arts/fonts/tmpfonts/default/font/" + matName + ".mat"; var targetMat = AssetDatabase.LoadAssetAtPath(matPath); com.font = targetFont; if (targetMat) { com.fontSharedMaterial = targetMat; replace = true; } } } if (replace) { Debug.Log("Font chg, prefab asset name = " + assetPath); PrefabUtility.SaveAsPrefabAsset(parent, assetPath); if (keepHierachy) { //重新替换下 var pParent = parent.transform.parent; var pIndex = parent.transform.GetSiblingIndex(); UnityEngine.Object.DestroyImmediate(parent); var prefab = AssetDatabase.LoadAssetAtPath(assetPath); var obj = PrefabUtility.InstantiatePrefab(prefab) as GameObject; obj.transform.SetParent(pParent, false); obj.transform.SetSiblingIndex(pIndex); var go = obj.transform.Find(childPath); Selection.activeObject = go; } } } } static public void RemoveTMPUISubMesh() { var filter = "Assets/prefabs/ui/"; string[] guids = AssetDatabase.FindAssets("t:prefab", new string[] { }); foreach (string guid in guids) { string assetPath = AssetDatabase.GUIDToAssetPath(guid); if (assetPath.Contains(filter)) { var gameObject = AssetDatabase.LoadAssetAtPath(assetPath); var subMeshUIs = gameObject.GetComponentsInChildren(true); var beChecked = (null != subMeshUIs && subMeshUIs.Length > 0) ? true : false; if (beChecked) { gameObject = Object.Instantiate(gameObject); subMeshUIs = gameObject.GetComponentsInChildren(true); var len = subMeshUIs.Length; for (int i = 0; i < len; i++) { var target = subMeshUIs[i].gameObject; var tarParent = target.transform.parent; if (tarParent && tarParent.GetComponent()) { var childPath = string.Empty; BF.Utils.GetTransformPath(target.transform, gameObject.transform, ref childPath); BF.BFLog.Log("检查到字体图集没有包含!!!!!---------- {0}, 来源{1}", tarParent.GetComponent().text, childPath); tarParent.GetComponent().text = ""; } Object.DestroyImmediate(target); } var parent = PrefabUtility.GetNearestPrefabInstanceRoot(gameObject); parent = parent == null ? gameObject : parent; //处理一层结构 PrefabUtility.SaveAsPrefabAsset(parent, assetPath); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Object.DestroyImmediate(gameObject); } } } } #endregion // 针对泰语处理 static bool overrideAll = true; static float wannayukHeight = 10f; static float aumXPlacementAfter = -35f; static float aumXPlacementBefore = 10f; static void _Adjust(TMP_FontAsset fontAsset) { if (fontAsset == null) { Debug.Log("No FontAsset selected"); return; } var glyphPairAdjustmentRecords = new List(fontAsset.fontFeatureTable.glyphPairAdjustmentRecords); var lookupTable = fontAsset.characterLookupTable; var glyphPairAdjustmentRecordLookupDictionary = (Dictionary) fontAsset.fontFeatureTable .GetType() .GetField("m_GlyphPairAdjustmentRecordLookupDictionary", BindingFlags.NonPublic | BindingFlags.Instance)? .GetValue(fontAsset.fontFeatureTable); int[] saras = new int[7]; int[] wannayuks = new int[4]; //get sara saras[0] = (int) lookupTable[GetUnicodeCharacter("ิ")].glyphIndex; // อิ saras[1] = (int) lookupTable[GetUnicodeCharacter("ี")].glyphIndex; // อี saras[2] = (int) lookupTable[GetUnicodeCharacter("ึ")].glyphIndex; // อึ saras[3] = (int) lookupTable[GetUnicodeCharacter("ื")].glyphIndex; // อื saras[4] = (int) lookupTable[GetUnicodeCharacter("ำ")].glyphIndex; // ำ saras[5] = (int) lookupTable[GetUnicodeCharacter("ั")].glyphIndex; // ั saras[6] = (int) lookupTable[GetUnicodeCharacter("ํ")].glyphIndex; // ํ //get wanna yuk wannayuks[0] = (int) lookupTable[GetUnicodeCharacter("่")].glyphIndex; //เอก wannayuks[1] = (int) lookupTable[GetUnicodeCharacter("้")].glyphIndex; //โท wannayuks[2] = (int) lookupTable[GetUnicodeCharacter("๊")].glyphIndex; //ตรี wannayuks[3] = (int) lookupTable[GetUnicodeCharacter("๋")].glyphIndex; //จัตวา int recordAdd = 0; foreach (var sara in saras) { foreach (var wannayuk in wannayuks) { float xPlacement = sara == saras[4] || sara == saras[6] ? aumXPlacementAfter : 0; TMP_GlyphValueRecord saraPosition = new TMP_GlyphValueRecord(0, 0, 0, 0); TMP_GlyphAdjustmentRecord saraGlyph = new TMP_GlyphAdjustmentRecord((uint) sara, saraPosition); TMP_GlyphValueRecord wannayukPosition = new TMP_GlyphValueRecord(xPlacement, wannayukHeight, 0, 0); TMP_GlyphAdjustmentRecord wannayukGlyph = new TMP_GlyphAdjustmentRecord((uint) wannayuk, wannayukPosition); var saraThenWannayukGlyphPair = new TMP_GlyphPairAdjustmentRecord(saraGlyph, wannayukGlyph); if (sara == saras[4] || sara == saras[6]) { xPlacement = aumXPlacementBefore; wannayukPosition = new TMP_GlyphValueRecord(xPlacement, wannayukHeight, 0, 0); wannayukGlyph = new TMP_GlyphAdjustmentRecord((uint) wannayuk, wannayukPosition); } var wannayukThenSaraGlyphPair = new TMP_GlyphPairAdjustmentRecord(wannayukGlyph, saraGlyph); uint firstPairKey = saraThenWannayukGlyphPair.firstAdjustmentRecord.glyphIndex << 16 | saraThenWannayukGlyphPair.secondAdjustmentRecord.glyphIndex; uint secondPairKey = wannayukThenSaraGlyphPair.firstAdjustmentRecord.glyphIndex << 16 | wannayukThenSaraGlyphPair.secondAdjustmentRecord.glyphIndex; if (overrideAll) { glyphPairAdjustmentRecords.RemoveAll(record => IsGlyphPairEqual(record, saraThenWannayukGlyphPair) || IsGlyphPairEqual(record, wannayukThenSaraGlyphPair)); glyphPairAdjustmentRecords.Add(saraThenWannayukGlyphPair); glyphPairAdjustmentRecords.Add(wannayukThenSaraGlyphPair); if (glyphPairAdjustmentRecordLookupDictionary != null && !glyphPairAdjustmentRecordLookupDictionary.ContainsKey(firstPairKey)) { glyphPairAdjustmentRecordLookupDictionary.Add(firstPairKey, saraThenWannayukGlyphPair); } recordAdd += 2; } else if (glyphPairAdjustmentRecordLookupDictionary != null) { if (!glyphPairAdjustmentRecordLookupDictionary.ContainsKey(firstPairKey)) { glyphPairAdjustmentRecords.Add(saraThenWannayukGlyphPair); recordAdd++; } if (!glyphPairAdjustmentRecordLookupDictionary.ContainsKey(secondPairKey)) { glyphPairAdjustmentRecords.Add(wannayukThenSaraGlyphPair); recordAdd++; } } } } if (recordAdd > 0) { fontAsset.fontFeatureTable.glyphPairAdjustmentRecords = glyphPairAdjustmentRecords; fontAsset.fontFeatureTable.SortGlyphPairAdjustmentRecords(); EditorUtility.SetDirty(fontAsset); AssetDatabase.SaveAssets(); Canvas.ForceUpdateCanvases(); UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); } Debug.Log("Adjust font : " + fontAsset.name + "" + " Height offset : " + wannayukHeight + "" + " Number of adjustment add : " + recordAdd + ""); } static void _Clear(TMP_FontAsset fontAsset) { fontAsset.fontFeatureTable.glyphPairAdjustmentRecords = new List(); EditorUtility.SetDirty(fontAsset); AssetDatabase.SaveAssets(); Canvas.ForceUpdateCanvases(); UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); } static uint GetUnicodeCharacter (string source) { uint unicode; if (source.Length == 1) unicode = source[0]; else if (source.Length == 6) unicode = (uint)TMP_TextUtilities.StringHexToInt(source.Replace("\\u", "")); else unicode = (uint)TMP_TextUtilities.StringHexToInt(source.Replace("\\U", "")); return unicode; } static bool IsGlyphPairEqual(TMP_GlyphPairAdjustmentRecord a, TMP_GlyphPairAdjustmentRecord b) { return a.firstAdjustmentRecord.glyphIndex == b.firstAdjustmentRecord.glyphIndex && a.secondAdjustmentRecord.glyphIndex == b.secondAdjustmentRecord.glyphIndex; } } }