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>
133 lines
6.6 KiB
C#
133 lines
6.6 KiB
C#
using System.Collections;
|
|
using System.IO;
|
|
using NUnit.Framework;
|
|
using UnityEngine;
|
|
using UnityEngine.TestTools;
|
|
using UnityEngine.TextCore.Text;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace Luneraria.UI.Tests
|
|
{
|
|
/// <summary>
|
|
/// U3A decision probe: a UI Toolkit panel renders into a texture in batch mode, with the plate
|
|
/// drawing, all glyphs and the three font weights (Regular, Regular with a 0.25 px outline for
|
|
/// the G3 weight 560, Bold). Writes tools/out/ui-spike.png (docs/port/screenshots/u3/00).
|
|
/// </summary>
|
|
public sealed class UiToolkitProbeTests
|
|
{
|
|
sealed class Plate : VisualElement
|
|
{
|
|
readonly LunePlateStyle _style;
|
|
public Plate(LunePlateStyle style)
|
|
{
|
|
_style = style;
|
|
style.ApplyPadding(this);
|
|
generateVisualContent += context => LunePlates.Draw(context, new Rect(0, 0, layout.width, layout.height), _style);
|
|
}
|
|
}
|
|
|
|
sealed class Glyph : VisualElement
|
|
{
|
|
public Glyph(string name, Color color, float edge)
|
|
{
|
|
this.style.width = edge;
|
|
this.style.height = edge;
|
|
generateVisualContent += context => LuneGlyphs.Draw(context.painter2D, name, new Rect(0, 0, layout.width, layout.height), color);
|
|
}
|
|
}
|
|
|
|
static Label Text(string value, FontAsset font, float size, Color color, float outline = 0f, float spacing = 0f)
|
|
{
|
|
var label = new Label(value);
|
|
label.style.unityFontDefinition = FontDefinition.FromSDFFont(font);
|
|
label.style.fontSize = size;
|
|
label.style.color = color;
|
|
label.style.letterSpacing = spacing;
|
|
label.style.marginLeft = 0;
|
|
label.style.paddingLeft = 0;
|
|
if (outline > 0f)
|
|
{
|
|
label.style.unityTextOutlineWidth = outline;
|
|
label.style.unityTextOutlineColor = color;
|
|
}
|
|
label.style.textShadow = new TextShadow { offset = new Vector2(0f, 1f), blurRadius = 1f, color = new Color(0f, 0f, 0f, .55f) };
|
|
return label;
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator PanelRendersIntoTexture()
|
|
{
|
|
#if UNITY_EDITOR
|
|
var assets = UnityEditor.AssetDatabase.LoadAssetAtPath<LuneUiAssets>("Assets/Luneraria/Settings/LuneUi.asset");
|
|
#else
|
|
LuneUiAssets assets = null;
|
|
#endif
|
|
Assert.IsNotNull(assets);
|
|
var target = new RenderTexture(1920, 1080, 0, RenderTextureFormat.ARGB32);
|
|
var settings = ScriptableObject.CreateInstance<PanelSettings>();
|
|
settings.themeStyleSheet = assets.Theme;
|
|
settings.targetTexture = target;
|
|
settings.scaleMode = PanelScaleMode.ScaleWithScreenSize;
|
|
settings.referenceResolution = new Vector2Int(1600, 960);
|
|
settings.screenMatchMode = PanelScreenMatchMode.Expand;
|
|
settings.clearColor = true;
|
|
settings.colorClearValue = new Color(.28f, .36f, .22f, 1f);
|
|
var host = new GameObject("UiSpike");
|
|
var document = host.AddComponent<UIDocument>();
|
|
document.panelSettings = settings;
|
|
yield return null;
|
|
VisualElement root = document.rootVisualElement;
|
|
var panel = new Plate(LunePlateStyle.Hud(LuneUiTheme.SlateTop, LuneUiTheme.SlateBottom, LuneUiTheme.Edge, 1f, 6f, 12f, 10f));
|
|
panel.style.position = Position.Absolute;
|
|
panel.style.left = 12;
|
|
panel.style.top = 12;
|
|
panel.style.width = 760;
|
|
root.Add(panel);
|
|
panel.Add(Text("WELLE 21", assets.Display, 30, LuneUiTheme.Hex("f4e6c4"), 0f, 3f));
|
|
panel.Add(Text("DEIN ANCIENT · BLAU", assets.TextBold, 14, LuneUiTheme.BronzeLight, 0f, 2f));
|
|
panel.Add(Text("Regular 400: Einheiten mit „Grotte“ entsenden. 12.000 / 12.000", assets.Text, 15, LuneUiTheme.Text));
|
|
panel.Add(Text("Regular + 0,25 Kontur: Einheiten mit „Grotte“ entsenden. 12.000 / 12.000", assets.Text, 15, LuneUiTheme.Text, .25f));
|
|
panel.Add(Text("Regular + 0,45 Kontur: Einheiten mit „Grotte“ entsenden. 12.000 / 12.000", assets.Text, 15, LuneUiTheme.Text, .45f));
|
|
panel.Add(Text("Bold 700: Einheiten mit „Grotte“ entsenden. 12.000 / 12.000", assets.TextBold, 15, LuneUiTheme.Text));
|
|
panel.Add(Text("235", assets.TextBold, 24, LuneUiTheme.Gold));
|
|
var glyphs = new VisualElement();
|
|
glyphs.style.flexDirection = FlexDirection.Row;
|
|
glyphs.style.flexWrap = Wrap.Wrap;
|
|
glyphs.style.marginTop = 8;
|
|
panel.Add(glyphs);
|
|
foreach (string name in LuneGlyphs.Names)
|
|
{
|
|
var glyph = new Glyph(name, name.StartsWith("emblem_1") || name == "shape_1" ? LuneUiTheme.Team[1] : name.StartsWith("emblem_0") || name == "shape_0" ? LuneUiTheme.Team[0] : LuneUiTheme.Text, 28f);
|
|
glyph.style.marginRight = 6;
|
|
glyph.style.marginBottom = 6;
|
|
glyphs.Add(glyph);
|
|
}
|
|
var buttons = new VisualElement();
|
|
buttons.style.flexDirection = FlexDirection.Row;
|
|
panel.Add(buttons);
|
|
var primary = new Plate(LunePlateStyle.Menu(LuneUiTheme.Hex("e8c47e"), LuneUiTheme.Hex("b98a4a"), LuneUiTheme.Hex("fff0cc"), 1.5f, 9f, 30f, 15f));
|
|
primary.Add(Text("BEREIT", assets.Display, 22, LuneUiTheme.Ink, 0f, 2f));
|
|
buttons.Add(primary);
|
|
var card = new Plate(LunePlateStyle.Hud(LuneUiTheme.Hex("19222c"), LuneUiTheme.Hex("10161d"), LuneUiTheme.Hex("34424f"), 1f, 7f, 6f, 6f));
|
|
card.style.width = 116;
|
|
card.style.height = 132;
|
|
card.style.marginLeft = 10;
|
|
buttons.Add(card);
|
|
for (int frame = 0; frame < 6; frame++)
|
|
yield return null;
|
|
RenderTexture.active = target;
|
|
var image = new Texture2D(1920, 1080, TextureFormat.RGBA32, false);
|
|
image.ReadPixels(new Rect(0, 0, 1920, 1080), 0, 0);
|
|
image.Apply();
|
|
RenderTexture.active = null;
|
|
string file = Path.Combine(Path.GetDirectoryName(Application.dataPath), "tools/out/ui-spike.png");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(file));
|
|
File.WriteAllBytes(file, image.EncodeToPNG());
|
|
Color corner = image.GetPixel(1900, 20);
|
|
Color panelPixel = image.GetPixel(100, 1080 - 100);
|
|
Debug.Log("LUNE_SPIKE corner " + corner + " panel " + panelPixel + " layout " + panel.layout);
|
|
Object.Destroy(host);
|
|
Assert.Greater(panel.layout.height, 50f);
|
|
}
|
|
}
|
|
}
|