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

@@ -639,7 +639,7 @@ The panel shows exactly one **content** at a time, picked from the catalog in RE
Selections sharing a row of this table get the same content and differ only in the name and symbol in the header. A count in the right slot appears only for an aggregated multi-selection (REQ-UI-SELECTION-AGGREGATE); a single selection of those types shows an empty slot.
- REQ-UI-SELECTION-STATUS: **Status indicator.** For a building whose production state is already rendered in the world as a status light (REQ-UI-STATUS-LIGHT) — Miner, Smelter, Assembler, Reprocessing Plant, Shipyard, Salvage Bay — the header's right slot repeats that same state as a colored dot with a short caption beside it, so the panel and the world never disagree. The state is derived from the evaluation defined in REQ-UI-STATUS-LIGHT rather than from a second definition, and the dot uses that state's fill color from `visuals.toml [status_light]`. The captions name the state: `no recipe` (grey), `producing` (green), `missing input` (red), `output full` (yellow); for the Salvage Bay, `holding scrap` (green) and `empty` (red). A selected **construction site** shows the caption `constructing` with no dot, whatever its type. Buildings with no status light — belts, splitters, tunnel ends, the HQ — show nothing in the slot.
- REQ-UI-SELECTION-AGGREGATE: **Aggregating a homogeneous multi-selection.** When several objects are selected and their content can be shown as one — the same content, with its values aggregated over the whole selection — the panel shows that single content with the number of selected objects in the header's right slot (`x<count>`), instead of the count summary of REQ-UI-MULTI-SELECTION / REQ-UI-FIELD-MULTI-SELECTION. This applies where every part of the **runtime** content aggregates. A **per-object configuration** does not stand in the way: it is simply not shown, there being no single object for it to configure.
- **Belt-subsystem tiles** — any mix of belts, tunnel entries, tunnel exits, and splitters. Their content is the item list and the clear action (REQ-UI-BELT-ITEMS, REQ-UI-BELT-CLEAR), both of which already read and act on the whole selection. A splitter's output filters are per-object, so they are shown only when that splitter is the only selected object (REQ-BLD-SPLITTER); an aggregate holding one or more splitters shows no filters at all. The card is named after the type of the **first tile** in the selection, whatever the mix, and the count in the right slot says how many are held.
- **Belt-subsystem tiles** — any mix of belts, tunnel entries, tunnel exits, and splitters. Their content is the item list and the clear action (REQ-UI-BELT-ITEMS, REQ-UI-BELT-CLEAR), both of which already read and act on the whole selection. A splitter's output filters are per-object, so they are shown only when that splitter is the only selected object (REQ-BLD-SPLITTER); an aggregate holding one or more splitters shows no filters at all. The card is named after the type of the **first tile** in the selection, whatever the mix, and the count in the right slot says how many are held. **Construction sites do not aggregate**: a selection holding one falls back to the count summary, a site having neither items on it nor a tile the belt subsystem knows (REQ-BLD-SITE-CONFIG).
- **Debris** — several pieces of debris and nothing else. Their remaining scrap sums into one value (REQ-UI-DEBRIS-PANEL).
Every other multi-selection falls back to the count summary. In particular several production buildings of one type — three miners, say — still do not aggregate, and the relaxation above does not change that: what stops them is their **runtime** content, not their recipe control. A buffer chip states a count against *that building's* capacity (`a / b`, REQ-MAT-OUTPUT-BUFFER) and a production section states *one* cycle's completion; summing three miners' ore into one chip would state a figure no buffer holds and no belt can draw, and averaging three cycle percentages would describe no building. Only where the runtime content is genuinely a property of the whole selection — items lying on a set of tiles, scrap remaining across a set of debris — is there one card to show.
@@ -676,7 +676,7 @@ The panel shows exactly one **content** at a time, picked from the catalog in RE
- REQ-UI-BELT-ITEMS: When one or more belt, splitter, tunnel entry, or tunnel exit tiles are selected, the panel's runtime group shows a captioned **`Items`** section stating what those tiles are carrying, above the clear action (REQ-UI-BELT-CLEAR) — the player reads what is there before removing it. Each item type present is shown as an **item chip** bearing the item's icon on its colored square (REQ-UI-ITEM-ICON) with the number of units held and the item's name below it, and hovering or clicking the chip shows that item's production tooltip (REQ-UI-ITEM-TOOLTIP) — the same chip the buffer sections and the HQ's block stock use (REQ-UI-SINGLE-SELECTION, REQ-UI-HQ-PANEL). This is what makes a belt's contents readable at all: on a moving line the items are too small and too transient to count by eye, and inside a tunnel they cannot be seen.
- **Counts sum over the whole selection**, so there is one chip per item type however many tiles are held, matching the clear action's reach (REQ-UI-SELECTION-AGGREGATE).
- **Items in transit through a tunnel** (REQ-BLD-TUNNEL-TRANSIT) are counted on the **tunnel exit**, that being where they will arrive; a selected tunnel entry counts only what is on its own tile. Selecting the exit is therefore how the player sees what a tunnel is currently swallowing, and how a tunnel is emptied (REQ-UI-BELT-CLEAR).
- Unlike a building's buffers, a belt has no fixed set of item types it can hold, so the section lists only the types actually present and shows no `0` chips. The chips keep the order the items are declared in config, so a chip does not jump about as counts change. When the selection carries nothing at all the section stays and reads the note `No items`, so the card holds one shape while items come and go.
- Unlike a building's buffers, a belt has no fixed set of item types it can hold, so the section lists only the types actually present and shows no `0` chips. The chips are ordered by **item id**, so a chip does not jump about as counts change — config declares no global item list to take an order from, items being named only where recipes and visuals use them. When the selection carries nothing at all the section stays and reads the note `No items`, so the card holds one shape while items come and go.
- REQ-UI-BELT-CLEAR: Below that list, the panel's runtime group shows a **"Clear items"** button that removes all items from the selected tiles. It is named for what it does rather than for a state it assumes: the items on a belt need not be stuck, and emptying a line is just as often what the player wants of a line that is running. It removes exactly what the list above it shows, tile for tile: clearing a **tunnel exit** therefore also discards the items in transit through that tunnel, which are counted on the exit, while clearing a **tunnel entry** leaves them travelling (REQ-BLD-TUNNEL-TRANSIT, REQ-UI-BELT-ITEMS). This can be used to resolve stalled belts, splitters, and tunnels. The button acts on every selected tile, which is why any mix of belt-subsystem tiles aggregates into one content rather than a count summary (REQ-UI-SELECTION-AGGREGATE).
Both the list and the button appear only where the selection holds **nothing but** belt-subsystem tiles. A selection mixing them with other buildings shows the count summary (REQ-UI-MULTI-SELECTION) and carries neither: a button that silently acted on part of a selection would be worse than no button, and the player can select the tiles alone.