Render each vital bar as a horizontal 3-slice from the real retail
RenderSurface sprites (authoritative ids from the vitals LayoutDesc
0x21000014 via dump-vitals-bars): a fixed-width bevelled left-cap, a
stretched glassy-gradient middle, and a fixed-width right-cap. The
empty back track draws full width; the coloured front fill grows from
the left to the value (the track owns the right end, so the fill omits
its own right-cap). Replaces the flat single-sprite Alphablend overlay
that read as the old UI - this is the bordered gradient look from the
retail screenshot (red HP / gold stamina / blue mana).
UiMeter gains the six 9-slice ids (BackLeft/Tile/Right +
FrontLeft/Tile/Right) and a DrawHBar helper; MarkupDocument parses the
backleft/backtile/backright/frontleft/fronttile/frontright attrs;
vitals.xml carries the 18 per-vital ids. The temporary
ACDREAM_BAR_PROVEOUT component grid is removed.
Adds AcDream.Cli render-vitals-mockup: a headless ImageSharp composite
that assembles the bars with the SAME DrawHBar logic, so the sprite
assembly can be verified by eye (Read the PNG) without launching the
client + server - the fast UI-iteration loop the user asked for.
export-ui-sprite dumps a single RenderSurface to PNG for HTML mockups.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Wires the dormant AcDream.App/UI retained-mode tree into GameWindow under
ACDREAM_RETAIL_UI=1: an 8-piece dat-sprite UiNineSlicePanel framing three
UiMeter vital bars bound to the existing VitalsVM. Render-only (UiHost input not
yet bridged to the InputDispatcher — next sub-phase). Coexists with the ImGui
devtools path; no regression there.
Visually verified against a live retail client: the bars match retail's vitals
structure (three stacked horizontal bars, current/max numbers centered) — so the
earlier "orbs" assumption was wrong (retail vitals ARE bars), and stamina is GOLD
not cyan (the #10F0F0 research note was wrong). UiMeter gains a centered numeric
Label (stub debug font for now). Spec §8 + the markup example corrected to match.
Bookkeeping: retired divergence row TS-30 (flat-rect panels -> real dat chrome)
and added IA-15 (our UiHost/markup engine vs keystone.dll's LayoutDesc tree).
Remaining polish (filed, §15): glassy gradient bar fill sprite + the retail dat
font for the numbers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds UiMeter, the horizontal vital-bar widget for the D.2b retail-look
UI toolkit. Solid-color fill for Spec 1; the retail orb sprite + scissor
crop path is reserved for a later sub-phase. Five unit tests (1 Fact +
4 Theory) cover half-fill geometry and clamping at -1/0/1/2 fractions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>