fix(ui): restore retail magic shortcut bar

Port the retail horizontal ItemList empty-slot padding and share UIItem shortcut-number graphics with the status toolbar. Preserve all authored face children on compound DAT buttons so the three-piece Cast control reflows and renders as one complete button.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-15 19:11:07 +02:00
parent 0527325b25
commit e3605672bb
12 changed files with 466 additions and 62 deletions

View file

@ -165,6 +165,43 @@ Selecting a spell updates its name and current spell. Cast invokes
retail spell input actions change tab/selection; the cast-current action casts
the current selection. Favorite edits are sent to ACE.
The visible row is still an ordinary `UIElement_ItemList`; it is not a
spell-specific strip painted by `gmSpellcastingUI`:
```text
UIElement_ItemList::UpdateEmptySlots @ 0x004E3700
if list is visible and FixedSlots (0x10000015) == -1:
read row/column constraints 0x5F and 0x60
when the horizontal constraint is unbounded:
occupiedWidth = itemCount * cellWidth
append floor((listWidth - occupiedWidth) / cellWidth) empty UIItems
when the list shrinks, remove only trailing UIItems in ItemSlot_Empty state
never remove an occupied trailing item merely because it exceeds the viewport
SpellCastSubMenu::UpdateShortcutOverlays @ 0x004C5BE0
for each UIItem in list order:
if index < 9: SetShortcutNum(item, index, ghosted=false)
else: SetShortcutNum(item, -1, ghosted=false)
UIElement_UIItem::SetShortcutNum @ 0x004E1590
occupied spell shortcut -> regular digit array 0x10000042
empty padding cell -> empty digit array 0x1000005E
```
Thus the first nine visible cells use the same blue 19 UIItem overlays as the
main status toolbar, including empty cells, while later cells retain only the
authored `ItemSlot_Empty` background. The count is based on the reflowed list
width (639 pixels at the 800-pixel design parent, 439 pixels inside the live
600-pixel combat page, yielding 13 whole 32-pixel cells).
The Cast button is likewise fully DAT-authored rather than a synthesized red
rectangle. Element `0x100000B2` is 75 by 32 pixels and its face is three stateful
children authored against a 79-pixel design parent: left `0..31`, middle
`32..46`, and right `47..78`. Apply each child's independent retail edge policy
after the button reflows; at 75 pixels they become `0..31`, `32..42`, and
`43..74`. Collapsing child-authored button media to the first child renders only
the left cap and is not retail behavior.
Outbound character events (`CM_Character`):
```text