feat(ui): port retail selected-stack quantity

Bind the authored stack count entry and horizontal slider to one Core split-quantity owner, preserve retail count-first naming and exact 1000-step rounding, refresh on stack changes, and consume the selected amount during merges. Conformance covers the production DAT fixture and retained pointer/focus paths.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-11 10:07:25 +02:00
parent dc1649c493
commit a20e5c68c7
19 changed files with 595 additions and 51 deletions

View file

@ -142,8 +142,27 @@ public static class DatWidgetFactory
{
SpriteResolve = resolve,
TrackSprite = DefaultImage(info),
Horizontal = info.Width > info.Height,
};
if (bar.Horizontal)
{
// gmToolbarUI stack slider (0x100001A4) has two direct Type-3 media
// children: a full-width 90x14 track (element 4) and a 16x14 thumb
// (element 1). Their geometry, not a button class, defines the roles.
ElementInfo? track = info.Children
.Where(child => DefaultImage(child) != 0u)
.OrderByDescending(child => child.Width)
.FirstOrDefault();
ElementInfo? scalarThumb = info.Children
.Where(child => !ReferenceEquals(child, track) && DefaultImage(child) != 0u)
.OrderBy(child => child.Width)
.FirstOrDefault();
bar.TrackSprite = track is null ? 0u : DefaultImage(track);
bar.ThumbSprite = scalarThumb is null ? 0u : DefaultImage(scalarThumb);
return bar;
}
uint incrementId = ReferencedElementId(info, 0x77u);
uint decrementId = ReferencedElementId(info, 0x78u);
ElementInfo? increment = info.Children.FirstOrDefault(child => child.Id == incrementId);