Das G3-HUD ist abgenommen; der Meilenstein U3 ist damit fertig. - Prüfung (Port von verify_g3, Teile A–H plus I): 718 Prüfungen ohne Fehler. Teil I prüft die Feld-Darstellung um das HUD (U3-Zugabe aus dem Motivvergleich): Aufstellungsflächen, Grotteneingang, ruhender Boss, Namensschilder, Eigentümer-Ring, Ancient-Balken. - Feld um das HUD: Namensschilder für Helden (mit Stufe), Angriffs- champions und den eingesetzten Boss („für Blau“), Eigentümer-Ring, Ancient-Balken bei Schaden, ruhende Schlundkrone auf dem Podest, eigener Grotteneingang, Aufstellungsflächen als eigene Objekte. - Schriften korrigiert: Die Referenz deklariert Cantarell 560/700–760 und Cinzel 700, wendet die Gewichte aber nie an (variation_opentype mit dem String-Schlüssel „wght“ wird von Godot ignoriert). G3 zeigt Regular 400, der Port ebenso — Cinzel-Regular statt Bold, keine Kontur zur Aufdickung. Laufweite aus spacing_glyph umgerechnet; dunkler Saum als Schatten statt TextCore-Kontur. - Werkzeuge: HudViewsTests (14 G3-Motive), HudPlaytest (Spieltest über die echte Oberfläche per Befehlsdateien), ui_ms_per_frame im LuneBenchmark. Layout folgt den echten Panelhöhen, Kamera startet wie Godot _ready auf der eigenen Lane. - Tests: EditMode 23/23, PlayMode 13/13, Kerntests 402/402, Verify 718/0. Fingerabdrücke der Bot-Partien unverändert (DCE95C96556F3A1A, 7B8E43AEFC0D60C5). - Bilder: 14 Motive bei 1920×1080, Auflösungen 1152×720 bis 2560×1440, Prüf-Schlüsselbilder, Spieltest-Screenshots. - Leistung (macOS-Player mit HUD, 116 Einheiten): 169 fps Übersicht, 218 fps Mid nah; HUD-Skripte 0,090 bzw. 0,078 ms je Bild. - Dokumentation: U3-UI (U3D, Schriftbefund), PORT-QA (U3), PORT-STATUS (U3 fertig, U4 nächster Schritt), KNOWN-BEHAVIOR-DIFFERENCES. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
95 lines
4.7 KiB
C#
95 lines
4.7 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// 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 a
|
|
/// named instance through the face index (named instance << 16), index 0 is the default
|
|
/// instance. The HUD uses Cantarell Regular (3) and Cinzel in its default instance (Regular
|
|
/// 400), the weights G3 really shows (see LuneFace); Cantarell Bold (4) stays for the U3A probe.
|
|
/// The atlases hold every character the HUD texts use, so the player never needs the font
|
|
/// files. Existing atlases are kept (no churn); delete one to rebuild it.
|
|
/// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneUiAssetsBuilder.Build -logFile -
|
|
/// </summary>
|
|
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<LuneUiAssets>(AssetPath);
|
|
if (assets == null)
|
|
{
|
|
assets = ScriptableObject.CreateInstance<LuneUiAssets>();
|
|
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", 0, "Cinzel-Regular");
|
|
assets.Theme = AssetDatabase.LoadAssetAtPath<ThemeStyleSheet>("Assets/Luneraria/UI/LuneRuntimeTheme.tss");
|
|
EditorUtility.SetDirty(assets);
|
|
AssetDatabase.SaveAssets();
|
|
Debug.Log("LUNE_UI built " + AssetPath);
|
|
if (Application.isBatchMode)
|
|
EditorApplication.Exit(0);
|
|
}
|
|
|
|
/// <summary>Printable ASCII, Latin-1 and the punctuation and symbols of the HUD texts.</summary>
|
|
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";
|
|
FontAsset existing = AssetDatabase.LoadAssetAtPath<FontAsset>(path);
|
|
if (existing != null)
|
|
return existing;
|
|
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;
|
|
}
|
|
}
|
|
}
|