fix(ui): D.2b-B — inventory panels render over the backdrop (#145 continuation) + captions
Visual verification surfaced two render bugs (controller LOGIC was already correct): 1. BACKDROP WASH-OUT (the big one — #145 continuation). The mounted backpack/ 3D-items panels inherited their sub-window root's ZLevel 1000 via the merge's zero-wins-base rule. The #145 ZOrder fold (ReadOrder − ZLevel·10000) turned 1000 into ZOrder ≈ −10,000,000 — sinking the panels BEHIND the frame's Alphablend backdrop (ZLevel 100 → ≈ −1,000,000). The backdrop then overpainted the panels' captions/burden-meter/cells (the paperdoll root is ZLevel 0 so it escaped, which is why the previous session thought #145 was done). Fix: the sub-window mount now keeps each slot's OWN frame ZLevel, so panels sit in front of the backdrop. Root-caused via a one-shot sprite-segment-order dump (backdrop was painting after the panel content) + a live ZLevel probe. 2. CAPTIONS. The caption elements resolve to UiText; driving a nested child UiText didn't paint. AttachCaption now drives the host UiText directly. Locked by InventoryFrameImportProbe (real-dat smoke: asserts each mounted panel's ZOrder > the backdrop's). Visually confirmed by the user: dark backdrop behind, Burden 17% + vertical bar + Contents-of-Backpack + full item grid all visible. Build + App(532)/Core(1526) tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1ccf07b705
commit
417b1375fd
3 changed files with 108 additions and 3 deletions
|
|
@ -82,9 +82,9 @@ public sealed class InventoryController
|
|||
_burdenMeter.Fill = () => _burdenFill;
|
||||
}
|
||||
|
||||
// Captions: attach a centered UiText child carrying the known string. "Contents of
|
||||
// Backpack" + "%d%%" are procedural in retail (gm3DItemsUI/gmBackpackUI PostInit/
|
||||
// SetLoadLevel); "Burden" is the dat label. (Caption pass, spec §5.)
|
||||
// Captions: drive each host UiText directly with the known string (the caption
|
||||
// elements resolve to UiText). "Contents of Backpack" + "%d%%" are procedural in retail
|
||||
// (gm3DItemsUI/gmBackpackUI PostInit/SetLoadLevel); "Burden" is the dat label. (Spec §5.)
|
||||
AttachCaption(layout.FindElement(BurdenCaptionId), () => "Burden", datFont);
|
||||
AttachCaption(layout.FindElement(ContentsCaptionId), () => "Contents of Backpack", datFont);
|
||||
AttachCaption(layout.FindElement(BurdenTextId), () => _burdenPercent + "%", datFont);
|
||||
|
|
@ -168,6 +168,30 @@ public sealed class InventoryController
|
|||
private void AttachCaption(UiElement? host, Func<string> text, UiDatFont? datFont)
|
||||
{
|
||||
if (host is null) return;
|
||||
|
||||
// The caption elements (0x100001D7 "Burden", 0x100001C5 "Contents of Backpack",
|
||||
// 0x100001D8 "%") resolve to UiText (Type-0 inheriting a text base — confirmed live).
|
||||
// Drive the host UiText DIRECTLY: it is already in the paint tree and renders, whereas
|
||||
// a nested child UiText did not paint. Set it to a static centered single-line label.
|
||||
if (host is UiText t)
|
||||
{
|
||||
t.Centered = true;
|
||||
t.DatFont = datFont;
|
||||
t.ClickThrough = true;
|
||||
t.AcceptsFocus = false;
|
||||
t.IsEditControl = false;
|
||||
t.CapturesPointerDrag = false;
|
||||
t.LinesProvider = () =>
|
||||
{
|
||||
var s = text();
|
||||
return string.IsNullOrEmpty(s)
|
||||
? Array.Empty<UiText.Line>()
|
||||
: new[] { new UiText.Line(s, CaptionColor) };
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback (non-UiText host): attach a centered label child.
|
||||
var label = new UiText
|
||||
{
|
||||
Left = 0f, Top = 0f, Width = host.Width, Height = host.Height,
|
||||
|
|
|
|||
|
|
@ -242,8 +242,21 @@ public static class LayoutImporter
|
|||
// (vitals/chat/toolbar). See ShouldMountBaseChildren + the B-Grid spec.
|
||||
if (baseChildren is not null
|
||||
&& ShouldMountBaseChildren(d.Children.Count, self.StateMedia.Count, baseChildren.Count))
|
||||
{
|
||||
result.Children.AddRange(baseChildren);
|
||||
|
||||
// The mounted slot's layer WITHIN THE FRAME is its OWN ZLevel, not the mounted
|
||||
// sub-window root's. The gm*UI sub-window roots carry ZLevel 1000 (their standalone
|
||||
// top-window layer); ElementReader.Merge's zero-wins-base rule made the slot (own
|
||||
// ZLevel 0) inherit that 1000, and the #145 ZOrder fold (ReadOrder − ZLevel·10000)
|
||||
// turns 1000 into ZOrder ≈ −10,000,000 — sinking the whole panel BEHIND the frame's
|
||||
// Alphablend backdrop (ZLevel 100 → ≈ −1,000,000). The backdrop then overpaints the
|
||||
// panel's captions/meter/cells (the wash-out bug; the paperdoll root happens to be
|
||||
// ZLevel 0 so it escaped). Restore the slot's own frame-layer so the panel sits in
|
||||
// FRONT of the backdrop. (B-Controller debug 2026-06-21; continuation of #145.)
|
||||
result.ZLevel = self.ZLevel;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue