feat(D.2b): per-container capacity bar on inventory cells

Faithful port of retail UIElement_UIItem::UpdateCapacityDisplay (0x004e16e0):
each container cell (side bags + main pack) shows a vertical UIElement_Meter
(element 0x10000347, back 0x06004D22 / fill 0x06004D23) filled to
GetNumContainedItems / ItemsCapacity, clamped [0,1]; hidden for non-containers
(CapacityFill=-1). Drawn procedurally on UiItemSlot like the triangle/square
overlays (back full + front clipped bottom-up). Right-anchored flush to the cell
edge (visual gate: the dat X=26 sat ~5px off the right edge). Visually confirmed
2026-06-22. Divergence AP-59; polish deferred to ISSUES #146 (exact rect/anchor,
fill direction vs m_eDirection 0x6f, closed-bag lazy-load).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-22 15:54:54 +02:00
parent 077586a0f0
commit a45c421bd1
6 changed files with 112 additions and 1 deletions

View file

@ -380,6 +380,29 @@ public class InventoryControllerTests
Assert.Equal(0x0600127Eu, mainPackCall.Value.icon);
}
[Fact]
public void SideBagCell_capacityBar_reflectsContents()
{
var (layout, _, containers, _, _, _, _, _) = BuildLayout();
var objects = new ClientObjectTable();
SeedBag(objects, 0xC, slot: 0, itemsCapacity: 24); // a side bag (cap 24)
for (uint i = 0; i < 6; i++) SeedContained(objects, 0xB0u + i, 0xC, slot: (int)i); // 6 items inside
Bind(layout, objects);
// Retail UpdateCapacityDisplay: fill = contained / itemsCapacity = 6/24 = 0.25 (exact in float).
Assert.Equal(0.25f, containers.GetItem(0)!.CapacityFill);
}
[Fact]
public void LooseGridItem_hasNoCapacityBar()
{
var (layout, grid, _, _, _, _, _, _) = BuildLayout();
var objects = new ClientObjectTable();
SeedContained(objects, 0xA, Player, slot: 0); // a loose, non-container item
Bind(layout, objects);
Assert.Equal(-1f, grid.GetItem(0)!.CapacityFill); // hidden — not a container
}
// Reads the text of the UiText caption child attached by the controller.
private static string CaptionText(UiElement host)
{

View file

@ -157,4 +157,14 @@ public class UiItemSlotTests
[Fact]
public void OpenContainerSprite_default_isTriangle()
=> Assert.Equal(0x06005D9Cu, new UiItemSlot().OpenContainerSprite);
// ── Container capacity bar (decomp UpdateCapacityDisplay 0x004e16e0, element 0x10000347) ──
[Fact]
public void CapacityFill_defaultsHidden() => Assert.Equal(-1f, new UiItemSlot().CapacityFill);
[Fact]
public void CapacityBackSprite_default() => Assert.Equal(0x06004D22u, new UiItemSlot().CapacityBackSprite);
[Fact]
public void CapacityFrontSprite_default() => Assert.Equal(0x06004D23u, new UiItemSlot().CapacityFrontSprite);
}