feat(D.2b): Character Attributes tab — 9-row list (icons + values + vitals) + footer State-A
Pass 1 of the Attributes tab interactive controller. Replaces the placeholder UiText attribute list with 9 real manual-layout rows matching retail's gmAttributeUI::PostInit (0x0049db70) structure: - 6 attribute rows (Strength/Endurance/Coordination/Quickness/Focus/Self) in retail display order (Coord enum 4 before Quick enum 3 — spec §1) - 3 vital rows (Health/Stamina/Mana) with cur/max format per Attribute2ndInfoRegion::Update (0x004f19e0) - Each row: icon (UiText.BackgroundSprite = 0x06xxxxxx RenderSurface via spriteResolve), name (left-justified), value (new RightAligned mode) Icon DataIDs from SubMap 0x25000006/0x25000007 via spec §2: STR 0x060002C8, END 0x060002C4, COORD 0x060002C9, QUICK 0x060002C6, FOCUS 0x060002C5, SELF 0x060002C7, HP 0x06004C3B, SP 0x06004C3C, MP 0x06004C3D Footer State-A (DisplayDefaultFooter 0x0049cde0): 0x1000024e title = "", 0x10000243 line-1-value = "Select an Attribute to Improve", 0x10000245 line-2-value = SkillCredits (InqInt(0x18)) Other changes: - UiText: add RightAligned bool (single-line right-justified, mirrors Centered path) - CharacterSheet: add SkillCredits property (retail InqInt(0x18)) - SampleData: update to spec fixture values (Str/Quick=200, rest=10, SkillCredits=96, Health=5/5, Stamina=10/10, Mana=10/10) - FixtureProvider: pass stack.ResolveChrome as spriteResolve for icon rendering - Tests: 13 targeted tests (9-row count, row order, attr+vital values, icon DataIDs, RightAligned flag, footer State-A all 5 elements) Pass 2 (selection/raise buttons) is separate per spec. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
27819514af
commit
902160098a
6 changed files with 552 additions and 74 deletions
|
|
@ -71,6 +71,13 @@ public sealed class UiText : UiElement
|
|||
/// after the rewire. Pair with <c>ClickThrough = true</c> for non-interactive labels.</summary>
|
||||
public bool Centered { get; set; }
|
||||
|
||||
/// <summary>Static right-aligned single-line mode: draws the FIRST line right-justified
|
||||
/// within the element rect, vertically centered, with NO scroll/selection machinery.
|
||||
/// Used for value labels in attribute/skill rows where the number must hug the right edge.
|
||||
/// Mutually exclusive with <see cref="Centered"/> — if both are true, Centered takes
|
||||
/// precedence. Pair with <c>ClickThrough = true</c> for non-interactive labels.</summary>
|
||||
public bool RightAligned { get; set; }
|
||||
|
||||
/// <summary>The scroll model — also read by the linked UiScrollbar.</summary>
|
||||
public UiScrollable Scroll { get; } = new();
|
||||
|
||||
|
|
@ -153,6 +160,28 @@ public sealed class UiText : UiElement
|
|||
return;
|
||||
}
|
||||
|
||||
// Static right-aligned single-line mode: draw the first line flush with the right
|
||||
// edge, vertically centered, then skip the scroll/selection machinery.
|
||||
if (RightAligned)
|
||||
{
|
||||
var rLines = LinesProvider();
|
||||
if (rLines.Count == 0) return;
|
||||
var line0 = rLines[0];
|
||||
if (DatFont is { } rdf)
|
||||
{
|
||||
float rx = Width - rdf.MeasureWidth(line0.Text) - Padding;
|
||||
float ry = (Height - rdf.LineHeight) * 0.5f;
|
||||
ctx.DrawStringDat(rdf, line0.Text, rx, ry, line0.Color);
|
||||
}
|
||||
else if ((Font ?? ctx.DefaultFont) is { } rbf)
|
||||
{
|
||||
float rx = Width - rbf.MeasureWidth(line0.Text) - Padding;
|
||||
float ry = (Height - rbf.LineHeight) * 0.5f;
|
||||
ctx.DrawString(line0.Text, rx, ry, line0.Color, rbf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Prefer the retail dat font when set; fall back to BitmapFont.
|
||||
var datFont = DatFont;
|
||||
var bitmapFont = datFont is null ? (Font ?? ctx.DefaultFont) : null;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue