stop hovering when the cursor points at no tile

A cursor resting on a panel or outside the window kept whatever it last
pointed at: the ghost, the tunnel preview, the deconstruct tint all stayed
put, because "not hovering" was not a state the build mode could hold. Make
both ghost tiles optional, clear the hover with them, and re-derive it when
the cursor comes back or a mode is entered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x
This commit is contained in:
2026-08-17 15:19:22 +02:00
parent 9490a96e12
commit b2148f00ac
7 changed files with 167 additions and 31 deletions

View File

@@ -897,13 +897,16 @@ void WorldRenderer::drawOverlays(QPainter& painter, const WorldCoordinates& coor
/*showPortTargetGlyphs*/ true);
}
}
else
// A cursor that points at no tile — resting on a floating panel, or outside
// the window — hovers nothing, and builder mode then shows no ghost at all
// (REQ-BLD-GHOST).
else if (frame.buildMode.getGhostTile().has_value())
{
// In tunnel mode the ghost shows the position-resolved type (entry or
// exit) and, when it would complete an existing tunnel, the matched end
// and the tiles between it and the ghost are tinted green
// (REQ-BLD-TUNNEL-MODE).
const QPoint ghostTile = frame.buildMode.getGhostTile();
const QPoint ghostTile = *frame.buildMode.getGhostTile();
const std::optional<QPoint>& partnerTile = frame.buildMode.getTunnelPartnerTile();
if (frame.buildMode.isTunnelMode() && frame.buildMode.isGhostValid()
&& partnerTile.has_value())
@@ -931,14 +934,16 @@ void WorldRenderer::drawOverlays(QPainter& painter, const WorldCoordinates& coor
}
}
// Blueprint placement ghost
if (frame.buildMode.isBlueprintMode())
// Blueprint placement ghost, drawn only while the cursor points at a tile, as for
// the builder ghost above (REQ-BLD-GHOST).
if (frame.buildMode.isBlueprintMode()
&& frame.buildMode.getBlueprintGhostTile().has_value())
{
// A single-building blueprint hit-tests the cursor for its transfer target; a
// constellation does not (REQ-UI-BLUEPRINT-TRANSFER). The stored building count,
// not the count after locked types are dropped, so the rule does not shift as the
// player unlocks things.
const QPoint cursorTile = frame.buildMode.getBlueprintGhostTile();
const QPoint cursorTile = *frame.buildMode.getBlueprintGhostTile();
const std::optional<QPoint> hoverTile =
frame.buildMode.getBlueprint().buildings.size() == 1
? std::make_optional(cursorTile) : std::nullopt;