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

@ -60,7 +60,8 @@ public class InventoryControllerTests
List<(uint source, uint target)>? mergeNotices = null,
string? ownerName = null,
Action? onClose = null,
SelectionState? selection = null)
SelectionState? selection = null,
StackSplitQuantityState? stackSplitQuantity = null)
=> InventoryController.Bind(layout, objects, () => Player,
iconIds: (_, _, _, _, _) => 0u,
strength: () => strength, datFont: null,
@ -71,7 +72,8 @@ public class InventoryControllerTests
sendStackableMerge: merges is null ? null : (s, t, a) => merges.Add((s, t, a)),
notifyMergeAttempt: mergeNotices is null ? null : (s, t) => mergeNotices.Add((s, t)),
onClose: onClose,
selection: selection ?? new SelectionState());
selection: selection ?? new SelectionState(),
stackSplitQuantity: stackSplitQuantity);
private static UiButton MakeButton(uint id)
{
@ -604,6 +606,35 @@ public class InventoryControllerTests
Assert.Equal(0xBu, selection.SelectedObjectId);
}
[Fact]
public void Drop_selectedStack_usesSharedToolbarSplitQuantity()
{
var (layout, grid, _, _, _, _, _, _) = BuildLayout();
var objects = new ClientObjectTable();
objects.AddOrUpdate(new ClientObject
{
ObjectId = 0xA, WeenieClassId = 0x1234, StackSize = 40, StackSizeMax = 100,
});
objects.MoveItem(0xA, Player, 0);
objects.AddOrUpdate(new ClientObject
{
ObjectId = 0xB, WeenieClassId = 0x1234, StackSize = 50, StackSizeMax = 100,
});
objects.MoveItem(0xB, Player, 1);
var selection = new SelectionState();
selection.Select(0xAu, SelectionChangeSource.Inventory);
var split = new StackSplitQuantityState();
split.Reset(40u);
split.SetValue(7u);
var merges = new List<(uint source, uint target, uint amount)>();
var ctrl = Bind(layout, objects, merges: merges, selection: selection,
stackSplitQuantity: split);
ctrl.HandleDropRelease(grid, grid.GetItem(1)!, Payload(0xAu));
Assert.Equal(new[] { (0xAu, 0xBu, 7u) }, merges);
}
[Fact]
public void Drop_differentStackType_fallsThroughToNormalInventoryInsert()
{