Skip to content

Instantly share code, notes, and snippets.

@networm
Created September 9, 2018 17:05
Show Gist options
  • Save networm/76a2856fc393192f4885b4fe8c580d34 to your computer and use it in GitHub Desktop.
Save networm/76a2856fc393192f4885b4fe8c580d34 to your computer and use it in GitHub Desktop.
Convert BMFont txt file to Unity font. XML version: Create UGUI Customize Font – 建立 UGUI 自定義字型 – 阿祥的開發日常 https://tedsieblog.wordpress.com/2016/07/11/create-ugui-customize-font/
using System;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
public class BitmapFontExporter : ScriptableWizard
{
public TextAsset fontFile;
public Texture2D textureFile;
[MenuItem("Tools/BitmapFontExporter/Create")]
private static void CreateFont()
{
ScriptableWizard.DisplayWizard<BitmapFontExporter>("Create Font");
}
private void OnWizardCreate()
{
if (fontFile == null || textureFile == null)
{
return;
}
string path = EditorUtility.SaveFilePanelInProject("Save Font", fontFile.name, "", "");
if (!string.IsNullOrEmpty(path))
{
ResolveFont(path);
}
}
private void ResolveFont(string exportPath)
{
if (!fontFile) throw new UnityException(fontFile.name + "is not a valid font-txt file");
Font font = new Font();
string fontPath = AssetDatabase.GetAssetPath(fontFile);
var sr = new StreamReader(fontPath);
// info
string info = sr.ReadLine();
if (info == null)
{
Debug.LogError(string.Format("Font {0} is not a valid file", fontPath));
return;
}
string face = Regex.Match(info, "face=\"(.*?)\"").Groups[0].Value;
// common
sr.ReadLine();
// page
sr.ReadLine();
// chars
var count = Convert.ToInt32(sr.ReadLine().Substring(12));
CharacterInfo[] charInfos = new CharacterInfo[count];
for (int cnt = 0; cnt < count; cnt++)
{
string node = sr.ReadLine();
var match = Regex.Match(node,
"char id=(-?\\d+)\\s+x=(-?\\d+)\\s+y=(-?\\d+)\\s+width=(-?\\d+)\\s+height=(-?\\d+)\\s+xoffset=(-?\\d+)\\s+yoffset=(-?\\d+)\\s+xadvance=(-?\\d+)\\s+page=(-?\\d+)\\s+chnl=(-?\\d+)");
CharacterInfo charInfo = new CharacterInfo();
charInfo.index = ToInt(match.Groups[1].Value);
// Disable obsolete api warning for compatibility
#pragma warning disable 0618
charInfo.width = ToInt(match.Groups[8].Value);
charInfo.uv = GetUV(match.Groups[2].Value, match.Groups[3].Value, match.Groups[4].Value, match.Groups[5].Value);
charInfo.vert = GetVert(match.Groups[5].Value, match.Groups[7].Value, match.Groups[4].Value, match.Groups[5].Value);
#pragma warning restore 0618
charInfos[cnt] = charInfo;
}
Shader shader = Shader.Find("Unlit/Transparent");
Material material = new Material(shader);
material.mainTexture = textureFile;
AssetDatabase.CreateAsset(material, exportPath + ".mat");
font.material = material;
font.name = face;
font.characterInfo = charInfos;
AssetDatabase.CreateAsset(font, exportPath + ".fontsettings");
}
private Rect GetUV(string x, string y, string width, string height)
{
Rect uv = new Rect();
uv.x = ToFloat(x) / textureFile.width;
uv.y = ToFloat(y) / textureFile.height;
uv.width = ToFloat(width) / textureFile.width;
uv.height = ToFloat(height) / textureFile.height;
uv.y = 1f - uv.y - uv.height;
return uv;
}
private Rect GetVert(string xoffset, string yoffset, string width, string height)
{
Rect uv = new Rect();
uv.x = ToFloat(xoffset);
uv.y = ToFloat(yoffset);
uv.width = ToFloat(width);
uv.height = ToFloat(height);
uv.y = -uv.y;
uv.height = -uv.height;
return uv;
}
private int ToInt(string value)
{
return Convert.ToInt32(value);
}
private float ToFloat(string value)
{
return (float)ToInt(value);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment