champions-of-luneraria/Assets/Luneraria/UI/Editor/LuneUiAssetsBuilder.cs
Martin Stickelbroeck 4dee9b18d2 U3A HUD-Grundlagen: UI Toolkit, Sichtmodell, menschlicher Sitz
Beginn des Ports des G3-HUD (Referenz luneraria/g3, 1b540f2).

- Entscheidung UI Toolkit statt uGUI nach kurzer Bewertung und einer Probe:
  Panel rendert im Batchmodus in eine 1920x1080-Textur (Skalierung wie Godot
  canvas_items/expand, 1600x960), gefaste Verlaufsplatten, alle 50 Symbole,
  Schriften aus den variablen Fonts der Referenz.
- Sichtmodell portiert (LuneHudModel, LuneLaneThreat, LuneStats) mit den
  Privatsphäre-Regeln der Referenz: Gold, Entwurf, Rückgängig und neue
  Buchungen nur für den eigenen Sitz; Lanes, Gebäude, Boss und Wellen aus
  öffentlichem Zustand.
- Menschlicher Sitz in LuneMatchRunner/LuneMatchDriver: Bots planen die
  übrigen fünf Sitze, die Planung wartet auf Bereit; Tempo 1x/2x/4x und Pause
  nur im Kampf. Bot-Partien unverändert.
- Theme-Grundlagen: Farben und Zahlenformate, Platten (forged_style.gd),
  Vektorsymbole (lune_glyphs.gd) mit Painter2D, statische SDF-Atlanten aus
  den benannten Instanzen von Cantarell und Cinzel (OFL).
- Tests: EditMode 23/23 (12 neue: gleiches öffentliches Bild für alle Sitze,
  fremde Entwürfe privat, private Boss-Lane-Wahl, Lane-Bedrohung, Bosszustände,
  nächste Welle, Bereit-Sperre, Formate, menschlicher Sitz); PlayMode 3/3,
  Fingerabdrücke der Bot-Partien unverändert (DCE95C96556F3A1A, 7B8E43AEFC0D60C5).
- Dokumentation: U3-UI (Bewertung, U3A), U5-VISUAL (Vorgaben des
  Projektinhabers: stilisierter Realismus für die ganze Welt, erst in U5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:57:45 +02:00

92 lines
4.5 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 the
/// named instances through the face index (named instance &lt;&lt; 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 -
/// </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", 2, "Cinzel-Bold");
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";
if (AssetDatabase.LoadAssetAtPath<FontAsset>(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;
}
}
}