fix(studio): Character pilot — CREATE m_pMainText (it's a runtime element, not static)

The character report element m_pMainText (0x1000011d) is created at RUNTIME by
gmCharacterInfoUI — it is NOT in any static LayoutDesc (confirmed: acdream's
dat-import of both 0x2100002E and 0x2100006E lacks it; only a runtime UI-tree
capture has it). So CharacterController.Bind now CREATES the UiText report
element + attaches it to the panel body (Left 12 / Top 44 / fills, ZOrder above
chrome) and fills it via LinesProvider — replicating what the retail gm*UI does.
Verified: the studio (--layout 0x2100002E) renders the full report — identity,
birth/age/deaths, vitals, the 6 attributes, skills, augmentations, encumbrance.
Tests rewritten to assert the CREATED element (10 pass); full App suite 619 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-25 19:01:09 +02:00
parent 4988dd4dfe
commit 33693c6412
2 changed files with 51 additions and 75 deletions

View file

@ -61,15 +61,28 @@ public static class CharacterController
Func<CharacterSheet> data,
UiDatFont? datFont = null)
{
if (layout.FindElement(MainTextId) is not UiText text)
return;
// Retail's gmCharacterInfoUI CREATES m_pMainText (0x1000011d) at RUNTIME — it is NOT a static
// element in any LayoutDesc (confirmed: acdream's dat-import of 0x2100002E AND 0x2100006E both
// lack it; only a runtime UI-tree capture has it). So replicate that: build the report text
// element ourselves and place it in the panel body, exactly as the gm*UI does at runtime.
var root = layout.Root;
if (root is null) return;
text.DatFont = datFont;
text.ClickThrough = false; // retail allows text selection in the report
text.AcceptsFocus = true;
text.IsEditControl = true;
text.CapturesPointerDrag = true;
var text = new UiText
{
EventId = MainTextId,
Name = "m_pMainText",
Left = 12f,
Top = 44f, // below the window header row
Width = System.Math.Max(40f, root.Width - 24f),
Height = System.Math.Max(40f, root.Height - 56f),
Anchors = AnchorEdges.None,
ZOrder = 1_000_000, // draw above the static chrome
DatFont = datFont,
ClickThrough = false,
};
text.LinesProvider = () => BuildReport(data());
root.AddChild(text);
}
// ── Report builder ────────────────────────────────────────────────────────