feat(D.5.1): ToolbarController — bind 18 slots, populate, deferred rebind, click-to-use

Port of gmToolbarUI::PostInit (slot wiring) + UpdateFromPlayerDesc (flush-and-bind
shortcuts from PlayerDescription) + SetDelayedShortcutNum (deferred ItemAdded rebind)
+ UseShortcut (click → useItem callback).

UiItemSlot gains Clicked (Action?) + OnEvent override (MouseDown → Clicked?.Invoke())
matching the retail UIElement_UIItem click dispatch pattern. UiEvent is a positional
record struct so the OnEvent override reads e.Type (int) against UiEventType.MouseDown
(const int 0x201) — confirmed from UiEvent.cs + UiText.cs before writing.

Three tests green (populate bound slot, deferred rebind on ItemAdded, click fires useItem).
Full suite: 0 failures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-16 22:36:48 +02:00
parent 9327fb64bf
commit 383a969c70
3 changed files with 235 additions and 0 deletions

View file

@ -37,6 +37,17 @@ public sealed class UiItemSlot : UiElement
public void Clear() { ItemId = 0; IconTexture = 0; }
/// <summary>Invoked by <see cref="OnEvent"/> when a left-button-down lands on
/// a bound slot. Wired by <c>ToolbarController</c> to the use-item callback.</summary>
public Action? Clicked { get; set; }
/// <inheritdoc/>
public override bool OnEvent(in UiEvent e)
{
if (e.Type == UiEventType.MouseDown) { Clicked?.Invoke(); return true; }
return false;
}
protected override void OnDraw(UiRenderContext ctx)
{
if (ItemId != 0 && IconTexture != 0)