korchoon
3/30/2020 - 5:11 AM

Unity Editor Window script to generate fonts. See: http://gamedev.stackexchange.com/a/91936/16587

Unity Editor Window script to generate fonts. See: http://gamedev.stackexchange.com/a/91936/16587

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System;
using System.Reflection;

// This Unity Editor window was created for this GD.SE question: http://gamedev.stackexchange.com/a/91936/16587
// The XML->Font is from the question asker, Almo
// By MLM
//
// Access the editor window by going to `Window -> Generate Custom Font`:
public class GenerateCustomFontWindow : EditorWindow
{

	string fontName = "freespin_big";

	// Add menu named "My Window" to the Window menu
	[MenuItem ("Window/Generate Custom Font")]
	static void CreateWindow () {
		// Get existing open window or if none, make a new one:
		GenerateCustomFontWindow fontWindow = EditorWindow.GetWindow<GenerateCustomFontWindow>("Gen. Custom Font");
	}
	
	void OnGUI()
	{
		this.fontName = EditorGUILayout.TextField("Font Name:", this.fontName);

		if(GUILayout.Button("Create Font"))
		{
			this.CreatFont(fontName);
		}
	}
	
	void CreatFont(string fontName) {
		TextAsset xml = Resources.Load<TextAsset>(fontName);
		Texture2D image = Resources.Load<Texture2D>(fontName);

		if(xml != null && image != null)
		{
			Font font = Resources.Load<Font>(fontName + ".fontsettings");
			if (font == null)
			{
				font = new Font();
				AssetDatabase.CreateAsset(font, "Assets/Resources/" + fontName + ".fontsettings");
			}
			
			Material mat = Resources.Load<Material>(fontName + ".mat");
			if (mat == null)
			{
				mat = new Material(Shader.Find("Unlit/Transparent"));
				mat.SetTexture("_MainTex", image);
				AssetDatabase.CreateAsset(mat, "Assets/Resources/" + fontName + ".mat");
			}
			font.material = mat;
			
			this.ImportFont(xml, font, new Vector2(image.width, image.height));
			AssetDatabase.SaveAssets();
		}
		else
		{
			Debug.LogError("Could not find XML data/image for font name: " + this.fontName + " - XML: " + (xml == null ? "null" : xml.ToString()) + " - image: " + (image == null ? "null" : image.ToString()));
		}
	}
	
	
	public void SetAsciiStartOffset(Font font, int asciiStartOffset)
	{
		Editor editor = Editor.CreateEditor(font);
		
		SerializedProperty startOffsetProperty = editor.serializedObject.FindProperty("m_AsciiStartOffset");
		startOffsetProperty.intValue = asciiStartOffset;
		
		editor.serializedObject.ApplyModifiedProperties();
		
	}
	
	
	public void ImportFont(TextAsset XMLAsset, Font font, Vector2 size)
	{
		int asciiOffset = 1000;
		XmlDocument xmlDoc = new XmlDocument();
		xmlDoc.LoadXml(XMLAsset.text);
		XmlNode spriteNode = xmlDoc.SelectSingleNode("font").FirstChild;
		
		XmlNode frameNode = spriteNode.FirstChild;
		
		List<CharacterInfo> infoList = new List<CharacterInfo>();
		while (frameNode != null)
		{
			int width = System.Convert.ToInt32(frameNode.Attributes["w"].Value);
			int height = System.Convert.ToInt32(frameNode.Attributes["h"].Value);
			int x = System.Convert.ToInt32(frameNode.Attributes["x"].Value);
			int y = (int)size.y - height - System.Convert.ToInt32(frameNode.Attributes["y"].Value);
			string character = frameNode.Attributes["name"].Value;
			if (!string.IsNullOrEmpty(character))
			{
				byte[] asciiBytes = System.Text.Encoding.ASCII.GetBytes(character);
				if (asciiBytes[0] < asciiOffset)
				{
					asciiOffset = asciiBytes[0];
				}
			}
			
			CharacterInfo info = new CharacterInfo();
			
			info.uv.x = x / size.x;
			info.uv.y = y / size.y;
			info.uv.width = width / size.x;
			info.uv.height = height / size.y;
			info.vert.x = 0;
			info.vert.y = 0;
			info.vert.width = width;
			info.vert.height = -height;
			info.width = width;
			info.index = infoList.Count;
			
			infoList.Add(info);
			frameNode = frameNode.NextSibling;
		}

		this.SetAsciiStartOffset(font, asciiOffset);
		font.characterInfo = infoList.ToArray();
	}
}