UiMeter gains SpriteResolve/BackSpriteId/FrontSpriteId; when both are set, OnDraw draws the empty-track sprite full-width then the colored-fill sprite UV-cropped to the live fill fraction (left-to-right drain). Falls back to solid rects when sprite ids are absent, keeping existing behavior and tests intact. MarkupDocument.Build() parses `back`/`front` hex attrs on <meter> and passes `resolve` into every UiMeter. vitals.xml wires the authoritative LayoutDesc 0x21000014 sprites (Health 0x06005F3C/3D, Stamina 3E/3F, Mana 40/41). The bar prove-out block in GameWindow.cs was already gone. If the sprites decode as 1x1 magenta at runtime they are paletted (INDEX16/P8) — the solid-color fallback will display instead and can be investigated separately. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
72 lines
2.9 KiB
C#
72 lines
2.9 KiB
C#
using AcDream.App.UI;
|
|
|
|
namespace AcDream.App.Tests.UI;
|
|
|
|
public class MarkupDocumentTests
|
|
{
|
|
private sealed class FakeBinding
|
|
{
|
|
public float HealthPercent => 0.5f;
|
|
public uint? HealthCurrent => 109;
|
|
public uint? HealthMax => 218;
|
|
public float? ManaPercent => null;
|
|
public uint? ManaCurrent => null;
|
|
public uint? ManaMax => null;
|
|
}
|
|
|
|
[Fact]
|
|
public void Build_CreatesPanelWithMeterFillLabelAndGeometry()
|
|
{
|
|
const string xml =
|
|
"<panel id=\"acdream.vitals\" x=\"10\" y=\"30\" w=\"220\" h=\"96\" title=\"Vitals\">" +
|
|
" <meter id=\"health\" x=\"8\" y=\"24\" w=\"200\" h=\"14\" fill=\"{HealthPercent}\" cur=\"{HealthCurrent}\" max=\"{HealthMax}\" color=\"#FFFF0000\"/>" +
|
|
"</panel>";
|
|
|
|
var panel = MarkupDocument.Build(xml, new FakeBinding(), _ => ((uint)1, 32, 32));
|
|
|
|
Assert.IsType<UiNineSlicePanel>(panel);
|
|
Assert.Equal(10f, panel.Left);
|
|
Assert.Equal(220f, panel.Width);
|
|
Assert.Equal(2, panel.Children.Count); // title UiLabel + 1 meter
|
|
var meter = Assert.IsType<UiMeter>(panel.Children[1]);
|
|
Assert.Equal(8f, meter.Left);
|
|
Assert.Equal(200f, meter.Width);
|
|
Assert.Equal(0.5f, meter.Fill());
|
|
Assert.Equal("109/218", meter.Label());
|
|
}
|
|
|
|
[Fact]
|
|
public void Build_NullBindingValuesYieldNullFillAndLabel()
|
|
{
|
|
const string xml =
|
|
"<panel id=\"v\" x=\"0\" y=\"0\" w=\"10\" h=\"10\" title=\"V\">" +
|
|
" <meter id=\"mana\" x=\"0\" y=\"0\" w=\"10\" h=\"2\" fill=\"{ManaPercent}\" cur=\"{ManaCurrent}\" max=\"{ManaMax}\" color=\"#FF0000FF\"/>" +
|
|
"</panel>";
|
|
var panel = MarkupDocument.Build(xml, new FakeBinding(), _ => ((uint)1, 32, 32));
|
|
var meter = Assert.IsType<UiMeter>(panel.Children[1]);
|
|
Assert.Null(meter.Fill());
|
|
Assert.Null(meter.Label());
|
|
}
|
|
|
|
[Fact]
|
|
public void Build_ResizeAttrX_SetsHorizontalOnly()
|
|
{
|
|
const string xml = "<panel id=\"v\" x=\"0\" y=\"0\" w=\"100\" h=\"50\" title=\"V\" resize=\"x\"></panel>";
|
|
var panel = MarkupDocument.Build(xml, new object(), _ => ((uint)1, 32, 32));
|
|
Assert.True(panel.ResizeX);
|
|
Assert.False(panel.ResizeY);
|
|
}
|
|
|
|
[Fact]
|
|
public void Build_ParsesBackFrontSpriteIds()
|
|
{
|
|
const string xml = "<panel id=\"v\" x=\"0\" y=\"0\" w=\"100\" h=\"50\" title=\"V\">" +
|
|
"<meter id=\"h\" x=\"0\" y=\"0\" w=\"100\" h=\"14\" fill=\"{HealthPercent}\" back=\"0x06005F3C\" front=\"0x06005F3D\"/>" +
|
|
"</panel>";
|
|
var panel = MarkupDocument.Build(xml, new FakeBinding(), _ => ((uint)7, 32, 32));
|
|
var meter = Assert.IsType<UiMeter>(panel.Children[1]);
|
|
Assert.Equal(0x06005F3Cu, meter.BackSpriteId);
|
|
Assert.Equal(0x06005F3Du, meter.FrontSpriteId);
|
|
Assert.NotNull(meter.SpriteResolve);
|
|
}
|
|
}
|