fix #375: Configure Keyboard live mount — string resolver + parked template prototypes
Campaign OP gate 2: the screen opened as a visual mess (textless buttons/tabs, buttons above the window, overlapping text) while the fixture conformance suite stayed green — the #372 class again. Two root causes, both proven by the new env-gated live-DAT probe before fixing: 1. MountKeyboardConfig's main LayoutImporter.Build was the ONE mount in RetailUiRuntime not passing strings.Resolve — every AUTHORED caption (OK/Cancel/Defaults/Revert/Load/Save, the six ActionClass tab labels, the Command/Mapping column headers) built empty, while the controller's own resolveString row captions worked, which is why the screen was recognizable but textless. Fixed by passing the resolver like every sibling mount. 2. gmKeyboardUI authors its ListBox row templates (header 0x1000002E, action row 0x1000002F with the three 100x32 key buttons) as TOP-LEVEL siblings referenced by dat property 0x64. Retail never instantiates template-list elements as live widgets (AddItemFromTemplateList clones from the desc — the same re-import UiTemplateListBox's TemplateResolver performs), but ImportInfos built them parked at the screen's (0,0): three key buttons at y=0..32 ABOVE the framed panel (top y=62) — the 'outside the window' buttons — under a 570x40 header text overlapping them and the top chrome. ImportInfos now skips top-level elements referenced by a SAME-LAYOUT template list (the same skip class as the existing BaseElement-prototype filter; same-layout only because element ids collide across layouts — 0x10000211 is a page in BOTH the options and keyboard layouts). The probe (ACDREAM_PROBE_LIVE_MOUNT=1) pins both against the real DATs: prototypes absent from the built tree, and Defaults/Revert/OK/Cancel resolving on the resolver-passing build. Post-fix the import collapses to the framed 600x476 panel with every screen button inside its bounds. Full Release suite: 13,082 passed / 4 skipped / 0 failed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
355c86a6f6
commit
8bd7e3b88d
5 changed files with 302 additions and 23 deletions
|
|
@ -220,6 +220,35 @@ public static class LayoutImporter
|
|||
tops.Add(Resolve(dats, d, new HashSet<(uint, uint)>()));
|
||||
}
|
||||
|
||||
// #375: a Type-5 ListBox's row-template list (dat property 0x64) can
|
||||
// name SAME-LAYOUT elements as its row prototypes — gmKeyboardUI
|
||||
// (0x21000009) authors its header (0x1000002E) and action-row
|
||||
// (0x1000002F, the three key buttons) templates as ordinary top-level
|
||||
// siblings of the screen. Retail never instantiates a template-list
|
||||
// element as a live widget (AddItemFromTemplateList clones from the
|
||||
// desc on demand — the SAME re-import our UiTemplateListBox's
|
||||
// TemplateResolver performs), so building them here parked two live
|
||||
// prototype rows at the screen's (0,0), over and outside the framed
|
||||
// panel. Same skip class as the BaseElement prototypes above, keyed on
|
||||
// the template-list reference instead. Same-LAYOUT references only:
|
||||
// element ids collide across layouts (0x10000211 is a page in BOTH the
|
||||
// options and keyboard layouts), so a cross-layout entry must never
|
||||
// suppress a coincidentally-same-id element here.
|
||||
var referencedAsTemplate = new HashSet<uint>();
|
||||
foreach (ElementInfo top in tops)
|
||||
CollectTemplateRefs(top, layoutId, referencedAsTemplate);
|
||||
if (referencedAsTemplate.Count > 0)
|
||||
{
|
||||
for (int i = tops.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!referencedAsTemplate.Contains(tops[i].Id)) continue;
|
||||
Console.WriteLine(
|
||||
$"[D.2b] LayoutImporter: skipping row-template element 0x{tops[i].Id:X8} "
|
||||
+ $"in layout 0x{layoutId:X8} (referenced by a same-layout template list).");
|
||||
tops.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (tops.Count == 1)
|
||||
return tops[0];
|
||||
|
||||
|
|
@ -235,6 +264,21 @@ public static class LayoutImporter
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>Recursively gathers every SAME-LAYOUT element id referenced by a
|
||||
/// row-template list (dat property 0x64) anywhere in <paramref name="info"/>'s
|
||||
/// resolved subtree — the skip set for the #375 parked-prototype filter above.</summary>
|
||||
private static void CollectTemplateRefs(
|
||||
ElementInfo info, uint layoutId, HashSet<uint> referenced)
|
||||
{
|
||||
foreach (UiTemplateListEntry entry in info.TemplateList)
|
||||
{
|
||||
if (entry.TemplateLayoutId == layoutId)
|
||||
referenced.Add(entry.TemplateElementId);
|
||||
}
|
||||
foreach (ElementInfo child in info.Children)
|
||||
CollectTemplateRefs(child, layoutId, referenced);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retail <c>UIElementManager::CreateRootElementByDataID</c> counterpart: resolve one
|
||||
/// authored root from a catalog-style LayoutDesc instead of instantiating every
|
||||
|
|
|
|||
|
|
@ -2283,15 +2283,23 @@ public sealed class RetailUiRuntime : IDisposable
|
|||
lock (_bindings.Assets.DatLock)
|
||||
{
|
||||
info = LayoutImporter.ImportInfos(_bindings.Assets.Dats, Layout.KeyboardConfigController.LayoutId);
|
||||
strings = new DatStringResolver(_bindings.Assets.Dats);
|
||||
layout = info is null
|
||||
? null
|
||||
: LayoutImporter.Build(
|
||||
info,
|
||||
_bindings.Assets.ResolveSprite,
|
||||
_bindings.Assets.DefaultFont,
|
||||
_bindings.Assets.ResolveFont);
|
||||
_bindings.Assets.ResolveFont,
|
||||
// #375: the main screen build was the ONE mount in this class
|
||||
// missing the string resolver — every AUTHORED caption
|
||||
// (OK/Cancel/Defaults/Revert/Load/Save, the six ActionClass
|
||||
// tab labels, the Command/Mapping column headers) rendered
|
||||
// empty at the gate, while the controller's own resolveString
|
||||
// lookups (row captions, headers) worked. Keep in step with
|
||||
// every sibling Mount* Build call above.
|
||||
strings.Resolve);
|
||||
snapshot = RetailActionMapReader.Read(_bindings.Assets.Dats);
|
||||
strings = new DatStringResolver(_bindings.Assets.Dats);
|
||||
}
|
||||
if (layout is null || snapshot is null)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue