list what a belt is carrying, and clear it by name

The belt card's only content was a button reading "Clear stuck items", which
assumed a state the items need not be in. It now reads "Clear items", and above
it the card lists what the selected tiles hold -- one item chip per type, the
same chip the buffer sections and the HQ's block stock draw -- so a line's
contents can be read before they are removed, and can be read at all: items on a
moving belt are too small and too transient to count by eye, and items inside a
tunnel are drawn nowhere.

BeltSystem gains countItems(tiles), a query of the same kind as
forEachVisualItem: a method rather than exposed tile containers, so the per-tile
representation stays swappable. It walks the same five containers as clearTiles,
in the same order, so the list and the button cannot drift apart.

The tunnel's two ends are now told apart. Items in transit are counted on the
exit they are travelling toward, and a clear removes exactly what the panel
listed for the tile it acts on: the exit discards them, the entry leaves them
travelling. BeltSystemTest's tunnel case splits in two accordingly.

Splitters now aggregate with belts and tunnel ends. Their output filters are
per-object configuration, which an aggregate simply does not show -- a splitter
selected alone still gets them. Both cards share one BeltItemList widget, and
both derive their tiles from collectBeltTiles, so nothing is stated twice.

The mixed count summary loses the clear action it carried: a button acting on
part of a selection is worse than no button, and the tiles can be selected by
themselves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
This commit is contained in:
2026-08-19 14:38:45 +02:00
parent 7547d954f1
commit fbb1af85e3
18 changed files with 444 additions and 92 deletions

View File

@@ -190,6 +190,10 @@ public:
void forEachVisualItem(QRect viewportTiles,
std::function<void(VisualItem)> visit) const;
// Inspection
std::map<ItemType, int> countItems( // REQ-UI-BELT-ITEMS
const std::vector<QPoint>& tiles) const; // transit items on the exit
// Determinism (docs/replay_design.md)
void appendChecksum(Hasher& hasher) const;
};
@@ -200,7 +204,7 @@ struct VisualItem {
};
```
Item *transport* is still reached only through push and pull: `tryPutItem` / `tryTakeItem` move items, `peekItem` reveals the leading item's type but never an identity, and rendering reads only through `forEachVisualItem`. The growth is in tile **topology** — placement, removal and splitter filters — which `BuildingSystem` drives because belts are `Building`s for cost, construction and deconstruction. That coupling is real and is not going away.
Item *transport* is still reached only through push and pull: `tryPutItem` / `tryTakeItem` move items, `peekItem` reveals the leading item's type but never an identity, and rendering reads only through `forEachVisualItem`. `countItems` is a query of the same kind, added for the selection panel's item list (REQ-UI-BELT-ITEMS): it answers *how many of what* over a set of tiles and is deliberately a method rather than exposed tile containers, which would freeze the per-tile representation into its callers and cost the v2 migration described below. The growth is in tile **topology** — placement, removal and splitter filters — which `BuildingSystem` drives because belts are `Building`s for cost, construction and deconstruction. That coupling is real and is not going away.
### Implementation Strategy