using System.IO;
using System.Linq;
using System.Text;
using Luneraria.UI;
using UnityEditor;
using UnityEngine;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.TextCore.Text;
using UnityEngine.UIElements;
namespace Luneraria.EditorTools
{
///
/// Builds Settings/LuneUi.asset (U3): static SDF font atlases from the variable fonts of the
/// reference (assets/fonts, OFL). Unity's text engine has no weight axis; FreeType loads the
/// named instances through the face index (named instance << 16): Cantarell Regular (3) and
/// Bold (4), Cinzel Bold (2). The atlases hold every character the HUD texts use, so the player
/// never needs the font files.
/// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneUiAssetsBuilder.Build -logFile -
///
public static class LuneUiAssetsBuilder
{
public const string AssetPath = "Assets/Luneraria/Settings/LuneUi.asset";
const string Fonts = "Assets/Luneraria/UI/Fonts/";
public static void Build()
{
var assets = AssetDatabase.LoadAssetAtPath(AssetPath);
if (assets == null)
{
assets = ScriptableObject.CreateInstance();
AssetDatabase.CreateAsset(assets, AssetPath);
}
assets.Text = Font("Cantarell-VF.otf", 3, "Cantarell-Regular");
assets.TextBold = Font("Cantarell-VF.otf", 4, "Cantarell-Bold");
assets.Display = Font("Cinzel-VF.ttf", 2, "Cinzel-Bold");
assets.Theme = AssetDatabase.LoadAssetAtPath("Assets/Luneraria/UI/LuneRuntimeTheme.tss");
EditorUtility.SetDirty(assets);
AssetDatabase.SaveAssets();
Debug.Log("LUNE_UI built " + AssetPath);
if (Application.isBatchMode)
EditorApplication.Exit(0);
}
/// Printable ASCII, Latin-1 and the punctuation and symbols of the HUD texts.
public static string Characters()
{
var text = new StringBuilder();
for (char c = (char)32; c < 127; c++)
text.Append(c);
for (char c = (char)160; c <= 255; c++)
text.Append(c);
text.Append("–—‘’‚“”„•…‰‹›€→←↑↓−×★≈≤≥∞·ŒœŠšŽžŸ");
return new string(text.ToString().Distinct().ToArray());
}
static FontAsset Font(string file, int namedInstance, string name)
{
string path = Fonts + name + ".asset";
if (AssetDatabase.LoadAssetAtPath(path) != null)
AssetDatabase.DeleteAsset(path);
string source = Path.GetFullPath(Fonts + file);
FontAsset font = FontAsset.CreateFontAsset(source, namedInstance << 16, 64, 8, GlyphRenderMode.SDFAA, 1024, 1024);
if (font == null)
throw new System.InvalidOperationException("Font asset failed: " + file + " instance " + namedInstance);
font.name = name;
AssetDatabase.CreateAsset(font, path);
if (!font.TryAddCharacters(Characters(), out string missing))
Debug.LogWarning("LUNE_UI " + name + " misses: " + missing);
for (int index = 0; index < font.atlasTextures.Length; index++)
{
Texture2D atlas = font.atlasTextures[index];
if (atlas == null)
continue;
atlas.name = name + " Atlas " + index;
AssetDatabase.AddObjectToAsset(atlas, font);
}
font.material.name = name + " Material";
AssetDatabase.AddObjectToAsset(font.material, font);
font.atlasPopulationMode = AtlasPopulationMode.Static;
// A static atlas needs no source at runtime: keep no machine path and never clear it in builds.
var serialized = new SerializedObject(font);
serialized.FindProperty("m_SourceFontFilePath").stringValue = Fonts + file;
serialized.FindProperty("m_ClearDynamicDataOnBuild").boolValue = false;
serialized.ApplyModifiedPropertiesWithoutUndo();
EditorUtility.SetDirty(font);
AssetDatabase.SaveAssets();
Debug.Log(string.Format("LUNE_UI font {0}: {1} / {2}, {3} glyphs, {4} atlas(es)", name, font.faceInfo.familyName, font.faceInfo.styleName, font.glyphTable.Count, font.atlasTextures.Length));
return font;
}
}
}