diff --git a/src/AcDream.App/UI/UiItemList.cs b/src/AcDream.App/UI/UiItemList.cs index 61c85d66..eedb6ff3 100644 --- a/src/AcDream.App/UI/UiItemList.cs +++ b/src/AcDream.App/UI/UiItemList.cs @@ -28,6 +28,23 @@ public sealed class UiItemList : UiElement public Func? SpriteResolve { get; set; } + private uint _cellEmptySprite; + /// Empty-slot sprite for THIS list's cells, resolved from the dat cell template + /// (retail attribute 0x1000000e -> catalog 0x21000037 prototype's ItemSlot_Empty; see + /// ). 0 = leave the + /// default (0x060074CF). Applied to every existing + /// AND future cell. + public uint CellEmptySprite + { + get => _cellEmptySprite; + set + { + _cellEmptySprite = value; + if (value != 0) + foreach (var c in _cells) c.EmptySprite = value; + } + } + /// The drag handler this list routes drops to (a panel controller). /// Null = the list accepts no drops. Retail: UIElement_ItemList::m_dragHandler. public IItemListDragHandler? DragHandler { get; private set; } @@ -53,6 +70,7 @@ public sealed class UiItemList : UiElement public void AddItem(UiItemSlot cell) { cell.SpriteResolve ??= SpriteResolve; + if (_cellEmptySprite != 0) cell.EmptySprite = _cellEmptySprite; // The list lays cells out procedurally (grid offset + scroll clip), so cells must be // EXEMPT from the parent anchor pass — UiElement.DrawSelfAndChildren runs ApplyAnchor // on every child after OnDraw, which would otherwise reset the scroll offset to each diff --git a/tests/AcDream.App.Tests/UI/UiItemListTests.cs b/tests/AcDream.App.Tests/UI/UiItemListTests.cs index 832a8507..b03e9ed6 100644 --- a/tests/AcDream.App.Tests/UI/UiItemListTests.cs +++ b/tests/AcDream.App.Tests/UI/UiItemListTests.cs @@ -22,4 +22,25 @@ public class UiItemListTests var list = new UiItemList(); Assert.Same(list.GetItem(0), list.Cell); } + + [Fact] + public void CellEmptySprite_stamps_existing_and_future_cells() + { + var list = new UiItemList(); // ctor adds one default cell + Assert.Equal(0x060074CFu, list.GetItem(0)!.EmptySprite); // UiItemSlot default before set + + list.CellEmptySprite = 0x06004D20u; // a pack-slot sprite + Assert.Equal(0x06004D20u, list.GetItem(0)!.EmptySprite); // existing cell re-stamped + + list.AddItem(new UiItemSlot()); + Assert.Equal(0x06004D20u, list.GetItem(1)!.EmptySprite); // new cell stamped + } + + [Fact] + public void CellEmptySprite_zero_leaves_the_UiItemSlot_default() + { + var list = new UiItemList(); + list.CellEmptySprite = 0u; + Assert.Equal(0x060074CFu, list.GetItem(0)!.EmptySprite); // unchanged default + } }