using UnityEngine; using UnityEditor; using UnityEngine.TextCore; using TMPro; using zbitmapfont; using UnityEngine.TextCore.LowLevel; using System.Drawing; using System.Runtime.InteropServices; using zbitmapfont; namespace zbitmapfont { public static class BitmapFont2TMPro { static void PatchGlyph(RawCharacterInfo character, int textureHeight, int textureWidth, ref Glyph g) { var scaleH = textureWidth / textureHeight > 1 ? textureWidth / textureHeight : 1; var scaleW = textureHeight / textureWidth > 1 ? textureHeight / textureWidth : 1; g.glyphRect = new GlyphRect( character.X * scaleW, (textureHeight - character.Y - character.Height) * scaleH, character.Width * scaleW, character.Height * scaleH ); g.metrics = new GlyphMetrics( character.Width, character.Height, character.Xoffset, -character.Yoffset, character.Xadvance ); } [MenuItem("Assets/zbitmapfont/CreateTMP_FontAsset")] public static void CreateTMP_FontAsset() { foreach (var a in Selection.assetGUIDs) { var p = AssetDatabase.GUIDToAssetPath(a); if (System.IO.Directory.Exists(p)) { string destPath = p; if (!BitmapFontTool.CreateBitmapFont(p, destPath)) { throw new System.Exception("CreateBitmapFont failed: " + p); } p += ".fnt"; } if (!p.EndsWith(".fnt")) { continue; } if (!System.IO.File.Exists(p)) { continue; } Create(p); } } static void Create(string fntFilePath) { var pngPath = System.IO.Path.GetDirectoryName(fntFilePath) + "/" + System.IO.Path.GetFileNameWithoutExtension(fntFilePath) + "_0.png"; Texture2D m_FontAtlasTexture = AssetDatabase.LoadAssetAtPath(pngPath); var assetPath = System.IO.Path.GetDirectoryName(fntFilePath) + "/" + System.IO.Path.GetFileNameWithoutExtension(fntFilePath) + ".asset"; var tex_FileName = System.IO.Path.GetFileNameWithoutExtension(assetPath); //Debug.Log("Creating TextMeshPro font asset!"); var fontAsset = AssetDatabase.LoadAssetAtPath(assetPath); if (fontAsset == null) { fontAsset = ScriptableObject.CreateInstance(); // Create new TextMeshPro Font Asset. AssetDatabase.CreateAsset(fontAsset, assetPath); } // Set version number of font asset //fontAsset.version = "1.1.0"; //Set Font Asset Type //fontAsset.atlasRenderMode = GlyphRenderMode.RASTER; // Reference to the source font file GUID. //fontAsset.m_SourceFontFile_EditorRef = m_DestinationFontFile.sourceFontFile; //fontAsset.m_SourceFontFileGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_DestinationFontFile.sourceFontFile)); // Add FaceInfo to Font Asset //fontAsset.faceInfo = m_FaceInfo; //// Add GlyphInfo[] to Font Asset //fontAsset.glyphTable = m_FontGlyphTable; //// Add CharacterTable[] to font asset. //fontAsset.characterTable = m_FontCharacterTable; //// Sort glyph and character tables. //fontAsset.SortAllTables(); //// Get and Add Kerning Pairs to Font Asset //if (m_IncludeFontFeatures) // fontAsset.fontFeatureTable = GetKerningTable(); // Add Font Atlas as Sub-Asset fontAsset.atlasTextures = new Texture2D[] { m_FontAtlasTexture }; //fontAsset.atlasWidth = m_FontAtlasTexture.width; //fontAsset.atlasHeight = m_FontAtlasTexture.height; //fontAsset.atlasPadding = m_Padding; //AssetDatabase.AddObjectToAsset(m_FontAtlasTexture, fontAsset); // Create new Material and Add it as Sub-Asset Shader default_Shader = Shader.Find("TextMeshPro/Bitmap Custom Atlas"); // m_shaderSelection; Material tmp_material = AssetDatabase.LoadAssetAtPath(assetPath); if (tmp_material == null) { tmp_material = new Material(default_Shader); tmp_material.name = tex_FileName + " Material"; fontAsset.material = tmp_material; AssetDatabase.AddObjectToAsset(tmp_material, fontAsset); } tmp_material.SetTexture(ShaderUtilities.ID_MainTex, m_FontAtlasTexture); fontAsset.GetType().GetProperty("version").SetValue(fontAsset, "1.1.0"); fontAsset.GetType().GetProperty("atlasRenderMode").SetValue(fontAsset, (int)GlyphRenderMode.RASTER); //fontAsset.GetType().GetProperty("faceInfo").SetValue(fontAsset, m_DestinationFontFile.faceInfo); fontAsset.GetType().GetProperty("atlasWidth").SetValue(fontAsset, m_FontAtlasTexture.width); fontAsset.GetType().GetProperty("atlasHeight").SetValue(fontAsset, m_FontAtlasTexture.height); fontAsset.GetType().GetProperty("atlasPadding").SetValue(fontAsset, 1); //fontAsset.GetType().GetField("m_SourceFontFile_EditorRef", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(fontAsset, m_DestinationFontFile.sourceFontFile); //fontAsset.GetType().GetField("m_SourceFontFileGUID", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(fontAsset, AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_DestinationFontFile.sourceFontFile))); var fontFile = fontAsset; var fnt = FntParse.GetFntParse(System.IO.File.ReadAllText(fntFilePath)); fontFile.characterTable.Clear(); //fontFile.characterLookupTable.Clear(); fontFile.glyphTable.Clear(); //fontFile.glyphLookupTable.Clear(); for (uint j = 0; j < fnt.charInfos.Length; j++) { var c = fnt.charInfos[j]; var a = new TMP_Character(); a.unicode = (uint)c.index; a.glyphIndex = j; a.textAsset = fontFile; var glyph = new Glyph(); PatchGlyph(fnt.rawCharInfos[j], fnt.textureHeight, fnt.textureWidth, ref glyph); glyph.index = j; glyph.atlasIndex = 0; a.glyph = glyph; fontFile.characterTable.Add(a); //fontFile.characterLookupTable.Add(a.unicode, a); fontFile.glyphTable.Add(glyph); //fontFile.glyphLookupTable.Add(j, glyph); } fontAsset.GetType().GetMethod("SortAllTables", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(fontAsset, null); var maxHeight = 0; for (int j = 0; j < fnt.charInfos.Length; j++) { maxHeight = Mathf.Max(maxHeight, Mathf.Abs(fnt.charInfos[j].minY - fnt.charInfos[j].maxY)); } var newFaceInfo = fontFile.faceInfo; //newFaceInfo.baseline = fnt.lineBaseHeight; //newFaceInfo.lineHeight = fnt.lineHeight; //newFaceInfo.ascentLine = fnt.lineHeight; newFaceInfo.baseline = 0; newFaceInfo.lineHeight = maxHeight; newFaceInfo.ascentLine = 0; newFaceInfo.pointSize = fnt.fontSize; newFaceInfo.descentLine = -maxHeight; var fontType = typeof(TMP_FontAsset); var faceInfoProperty = fontType.GetProperty("faceInfo"); faceInfoProperty.SetValue(fontFile, newFaceInfo); AssetDatabase.Refresh(); AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); AssetDatabase.SaveAssets(); } } }