Malte Langkabel 1eca61e934 extract SelectionController
The selection rules were written out twice - once for point clicks and once for
box drags - and the two copies had already drifted. Unlike the earlier seams on
this branch this is a real de-duplication, not a relocation.

SelectionController owns all three categories and the rules for moving between
them: buildings win over field objects, so selecting a building clears actors and
debris and selecting either of those clears buildings, while actors and debris
coexist. It also publishes the change events, so callers never emit by hand.

A point click and a box drag now differ only in the SelectionMode they pass and
in how many hits they pass. That names the difference that was previously implicit
in two separate loops: Ctrl+click toggles, so dragging back over a selected
building would deselect it, whereas Ctrl+box adds and never deselects.

Hit-testing stays in GameWorldView, which is what keeps the controller free of any
simulation dependency and therefore testable - including the published events,
via a spy handler. That coverage is the point: these rules had none, and the two
copies were the kind of thing that drifts silently.

One behaviour difference, deliberate. Clearing the building selection was guarded
by "only if non-empty" in three of the four places and unguarded in the fourth
(the empty-box drag), which emitted a redundant SelectionChangedEvent with an
empty list. The unified rule is the guarded one. Subscribers re-read from
Simulation on every event, so dropping a redundant no-op refresh cannot change
what any of them display.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
2026-08-05 14:24:52 +02:00
2026-07-12 09:16:49 +02:00
2026-08-05 14:24:52 +02:00
2026-07-22 21:44:20 +02:00
Description
No description provided
20 MiB
Languages
C++ 96%
CMake 2.2%
Python 1.2%
C 0.6%