67 lines
2.6 KiB
C#
67 lines
2.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace AcDream.App.UI;
|
|
|
|
/// <summary>
|
|
/// A container of item cells (port of retail UIElement_ItemList, class 0x10000031).
|
|
/// Behavioral LEAF: it creates/owns its UiItemSlot children procedurally, so the
|
|
/// LayoutImporter must NOT build dat children. The toolbar uses single-cell
|
|
/// instances (one slot); the inventory phase will grow this to an N-cell grid.
|
|
/// </summary>
|
|
public sealed class UiItemList : UiElement
|
|
{
|
|
private readonly List<UiItemSlot> _cells = new();
|
|
|
|
public UiItemList(Func<uint, (uint tex, int w, int h)>? spriteResolve = null)
|
|
{
|
|
SpriteResolve = spriteResolve;
|
|
// Single-cell default: every toolbar slot always shows one cell (empty or filled).
|
|
AddItem(new UiItemSlot { SpriteResolve = spriteResolve });
|
|
}
|
|
|
|
public override bool ConsumesDatChildren => true;
|
|
|
|
public Func<uint, (uint tex, int w, int h)>? SpriteResolve { get; set; }
|
|
|
|
/// <summary>Convenience for single-cell slots (the toolbar): the first cell.
|
|
/// Valid only while the list has at least one cell; after <see cref="Flush"/>
|
|
/// (the inventory-phase rebuild path) the list is empty until <see cref="AddItem"/>
|
|
/// runs, so use <see cref="GetItem"/> there instead.</summary>
|
|
/// <exception cref="InvalidOperationException">the list has no cells (e.g. after Flush).</exception>
|
|
public UiItemSlot Cell => _cells.Count > 0
|
|
? _cells[0]
|
|
: throw new InvalidOperationException("UiItemList has no cells; call AddItem first or use GetItem(index).");
|
|
|
|
public int GetNumUIItems() => _cells.Count;
|
|
|
|
public UiItemSlot? GetItem(int index)
|
|
=> index >= 0 && index < _cells.Count ? _cells[index] : null;
|
|
|
|
public void AddItem(UiItemSlot cell)
|
|
{
|
|
cell.SpriteResolve ??= SpriteResolve;
|
|
cell.Left = 0; cell.Top = 0; cell.Width = Width; cell.Height = Height;
|
|
_cells.Add(cell);
|
|
AddChild(cell);
|
|
}
|
|
|
|
public void Flush()
|
|
{
|
|
foreach (var c in _cells) RemoveChild(c);
|
|
_cells.Clear();
|
|
}
|
|
|
|
protected override void OnDraw(UiRenderContext ctx)
|
|
{
|
|
// The factory sets THIS list's Width/Height AFTER construction, so the cell
|
|
// (added in the ctor) starts 0x0. For the single-cell toolbar slot, keep the
|
|
// cell sized to the list each frame; the cell paints itself in the children
|
|
// pass that follows. (N-cell grid layout is the inventory phase.)
|
|
if (_cells.Count > 0)
|
|
{
|
|
var cell = _cells[0];
|
|
cell.Left = 0; cell.Top = 0; cell.Width = Width; cell.Height = Height;
|
|
}
|
|
}
|
|
}
|