4f6de793529e4f1a6a28a3708c419d7334fc555d
The nine coordinate helpers on GameWorldView were the first seam of the planned decomposition: stateless math that every draw method, the placement validation, and the belt-drag code reached into private state to get at. WorldCoordinates is an immutable value built from the viewport size, the world height, and the scroll center. It lives in lib/core rather than ui, following BeltDragPath and TunnelCompletion — UI-only helpers kept there so Catch2 can reach them. That is what lets the transform math be unit-tested at all, since the test target links lib only. Rather than leave delegating one-liners behind, the snapshot is threaded through the call graph: paintGL builds one per frame, every world-space draw takes a const WorldCoordinates&, and the screen-space draws (vignettes, replay overlay, debug text) take none. Those methods no longer touch m_scrollXTiles, width(), or height(), which is most of the groundwork for extracting WorldRenderer later. The mouse handlers each take their own snapshot. The snapshot is deliberately not cached in a member: a resize or a scroll would silently invalidate it, and a stale transform surfaces as misaligned hit-testing rather than as a visible failure. widgetToTile and widgetToWorld had the same arithmetic inlined separately; the former now goes through the latter. The architecture doc's coordinate section was already stale — it described a painter.translate approach and a hardcoded tilePx = 20, neither of which was true — so it is rewritten to match the code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
Description
No description provided
Languages
C++
96%
CMake
2.2%
Python
1.2%
C
0.6%