feat(ui): port retained widget foundations

This commit is contained in:
Erik 2026-07-10 17:55:41 +02:00
parent 44f9ec13d9
commit d825572e31
44 changed files with 84813 additions and 292 deletions

View file

@ -138,8 +138,6 @@ public static class CharacterStatController
// State names as returned by UIStateId.ToString() — used as ActiveState keys on UiButton.
private const string StateOpen = "Open"; // UIStateId.Open = 0x0C — active tab
private const string StateClosed = "Closed"; // UIStateId.Closed = 0x0B — inactive tab
private const string StateNormal = "Normal"; // UIStateId.Normal = 0x01 — affordable / default
private const string StateGhosted = "Ghosted"; // UIStateId.Ghosted = 0x0D — disabled button
private static readonly Vector4 Body = new(0.92f, 0.90f, 0.82f, 1f); // parchment-white body text
private static readonly Vector4 Gold = new(1f, 0.82f, 0.36f, 1f); // section / emphasis gold
@ -338,6 +336,7 @@ public static class CharacterStatController
if (datFont is not null) xpValue.DatFont = datFont;
xpValue.ClickThrough = true;
xpValue.RightAligned = true;
xpValue.OneLine = true;
xpValue.Padding = 0f; // avoid scroll clip
xpValue.LinesProvider = () => new[] { new UiText.Line(data().XpToNextLevel.ToString("N0"), Body) };
}
@ -1053,12 +1052,20 @@ public static class CharacterStatController
bool affordable1 = cost1 > 0 && sheet.UnassignedXp >= cost1;
bool affordable10 = cost10 > 0 && sheet.UnassignedXp >= cost10;
// State "Normal" = affordable/green; "Ghosted" = too expensive or maxed.
string btn1State = affordable1 ? StateNormal : StateGhosted;
string btn10State = affordable10 ? StateNormal : StateGhosted;
foreach (var b in allRaise1) { b.Visible = true; b.ActiveState = btn1State; }
foreach (var b in allRaise10) { b.Visible = true; b.ActiveState = btn10State; }
foreach (var b in allRaise1)
{
b.Visible = true;
b.TrySetRetailState(affordable1
? UiButtonStateMachine.Normal
: UiButtonStateMachine.Ghosted);
}
foreach (var b in allRaise10)
{
b.Visible = true;
b.TrySetRetailState(affordable10
? UiButtonStateMachine.Normal
: UiButtonStateMachine.Ghosted);
}
}
private static void RefreshSkillRaiseButtons(
@ -1079,12 +1086,12 @@ public static class CharacterStatController
bool affordable = trained
? cost > 0 && sheet.UnassignedXp >= cost
: cost > 0 && sheet.SkillCredits >= cost;
string state = affordable ? StateNormal : StateGhosted;
foreach (var b in allRaise1)
{
b.Visible = true;
b.ActiveState = state;
b.TrySetRetailState(affordable
? UiButtonStateMachine.Normal
: UiButtonStateMachine.Ghosted);
}
foreach (var b in allRaise10)
@ -1094,7 +1101,9 @@ public static class CharacterStatController
{
long cost10 = selectedSkill.Raise10Cost;
bool affordable10 = cost10 > 0 && sheet.UnassignedXp >= cost10;
b.ActiveState = affordable10 ? StateNormal : StateGhosted;
b.TrySetRetailState(affordable10
? UiButtonStateMachine.Normal
: UiButtonStateMachine.Ghosted);
}
}
}
@ -1334,6 +1343,7 @@ public static class CharacterStatController
DatFont = datFont,
ClickThrough = true,
RightAligned = true,
OneLine = true,
Anchors = AnchorEdges.Left | AnchorEdges.Top,
};
var capturedProvider = valueProvider;
@ -1435,6 +1445,7 @@ public static class CharacterStatController
// BackgroundSprite cleared: its full-height sprite would cover line-1/line-2.
titleEl.BackgroundSprite = 0;
titleEl.VerticalJustify = VJustify.Top; // dat says Center; override to Top (see comment above)
titleEl.OneLine = true;
}
// Title (FooterTitle 0x1000024E, 20px from dat): pass null → keep dat font.
// Fix C: the dat has a 20px font for the footer title. Let it drive.
@ -1706,6 +1717,7 @@ public static class CharacterStatController
// Non-null = controller explicit override.
if (datFont is not null) t.DatFont = datFont;
t.Centered = true;
t.OneLine = true;
t.ClickThrough = true;
t.LinesProvider = () => new[] { new UiText.Line(text(), color) };
}
@ -1829,6 +1841,7 @@ public static class CharacterStatController
DatFont = datFont,
ClickThrough = true,
Centered = true,
OneLine = true,
Anchors = AnchorEdges.Left | AnchorEdges.Top,
};
labelEl.LinesProvider = () => new[] { new UiText.Line(capturedLabel, labelColor) };