move the debug stats panel out of the renderer

It was the one thing in WorldRenderer positioned in pixels rather than tiles,
kept there only to preserve its draw order. With the order agreed not to matter,
the world-space / screen-space split becomes exact.

The real payoff is translation. drawDebugOverlay was the only caller of tr() in
the renderer, so Q_DECLARE_TR_FUNCTIONS and the QCoreApplication include go with
it. Nothing left in the renderer draws translatable text - its text is
config-driven glyphs, ASCII port arrows and numbers - so it no longer needs a
tie to the meta-object system at all. That is the argument I should have weighed
originally instead of anchoring on draw order.

The panel now paints on top of ships and beams rather than under them, and the
widget gates it on its own m_debugDraw directly. The frame still carries
isDebugDrawEnabled, because the sensor ranges and target lines it also gates are
genuinely world-space.

Dropped the painter.resetTransform() the function opened with: it was vestigial
from the older design that drew the world through painter.translate, and has
been a no-op since every conversion became explicit arithmetic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
This commit is contained in:
2026-08-05 21:23:38 +02:00
parent afb4b8b744
commit 3eec462b4a
5 changed files with 57 additions and 64 deletions

View File

@@ -331,7 +331,7 @@ Buildings and the belt subsystem stay outside any entity model regardless of wha
The game world is drawn into a single `GameWorldView` widget that inherits `QOpenGLWidget` and uses `QPainter` for all drawing. This gives the same imperative paint API as a plain `QWidget` with GPU acceleration, comfortably handling the expected scale (hundreds of ships, thousands of belt items) without blocking the main thread on CPU rasterization.
The drawing itself lives in `WorldRenderer`, not in the widget. `paintGL` is a call sequence: build the frame's `WorldCoordinates`, hand the renderer a `WorldRenderFrame`, then draw the screen-anchored chrome. The split is the world-space / screen-space line: the renderer draws everything positioned in tiles, while the pause and deconstruct vignettes and the replay overlay — which are anchored to the viewport and never took a `WorldCoordinates` — stay with the widget.
The drawing itself lives in `WorldRenderer`, not in the widget. `paintGL` is a call sequence: build the frame's `WorldCoordinates`, hand the renderer a `WorldRenderFrame`, then draw the screen-anchored chrome. The split is the world-space / screen-space line, and it is exact: the renderer draws everything positioned in tiles, while everything positioned in pixels — the pause and deconstruct vignettes, the replay overlay, the debug stats panel — stays with the widget. A useful consequence is that the renderer draws no translatable text at all (its text is config-driven glyphs, ASCII port arrows, and numbers), so it needs no `tr()` and no tie to the meta-object system.
`WorldRenderFrame` is what makes the renderer independent of the widget. The renderer reads the simulation directly, but everything else it draws is interaction state the widget owns — the selection, the active build mode, live beams, the copy-settings feedback, the box-select rectangle. Those are gathered into the frame each `paintGL` and passed by reference, so the renderer keeps no copy that a later click could invalidate. The renderer knows nothing about input: the widget resolves clicks and hit-tests, and the renderer only draws the result.