extract BuildModeController, fixing a silent blueprint exit
Builder, blueprint and deconstruct were three independent flags, and every entry point cleared the other two by hand. The copies had drifted, and one had a real bug: enterBuilderMode reset the blueprint directly instead of calling exitBlueprintMode, so BlueprintModeExitedEvent never fired and BlueprintPanel never ran clearActiveBlueprintButton. Activating a blueprint and then picking a building left the blueprint button highlighted for a mode that had ended. Exclusivity is now structural. One mode is active, and every transition runs through enterMode(), which exits whatever was active first. Which mode the player switches to can no longer change what the mode they left announces - a test covers all four crossings, plus the blueprint regression above. The controller also owns the state that belongs to a mode and had to be cleared with it: ghost tile/rotation/validity, the resolved tunnel end and its completion partner, the belt drag, and the deconstruct hover. Those were the things the hand-written resets kept forgetting. Everything needing the simulation stays in GameWorldView - placement validity, tunnel matching, belt path building - and is handed back through setGhostValidity, setTunnelGhost and setBeltDragPath. That is what keeps the controller a plain value with tests. Two smaller behaviour changes, both dropping redundant events. Restart now announces only the mode that was actually active rather than all three exits unconditionally; and entering builder or blueprint mode no longer publishes DeconstructModeChangedEvent(false) when deconstruct mode was not on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include <QVector2D>
|
||||
|
||||
#include "Blueprint.h"
|
||||
#include "BuildModeController.h"
|
||||
#include "BuildingConfig.h"
|
||||
#include "BlueprintModeExitedEvent.h"
|
||||
#include "BlueprintPlacementRequestedEvent.h"
|
||||
@@ -262,14 +263,9 @@ private:
|
||||
void stepSpeed(int delta);
|
||||
void placeAtTile(QPoint tile);
|
||||
|
||||
// Unified tunnel build mode (REQ-BLD-TUNNEL-MODE). Active while the builder type
|
||||
// is TunnelEntry; the ghost then resolves to an entry or exit by hovered position.
|
||||
bool inTunnelMode() const;
|
||||
// The building type the ghost currently represents: the position-resolved tunnel
|
||||
// type in tunnel mode, otherwise the plain builder type.
|
||||
BuildingType effectiveBuilderType() const;
|
||||
// Recomputes m_tunnelGhostType and m_tunnelPartnerTile from the current ghost
|
||||
// tile, rotation, and sub-tile cursor position. Only meaningful in tunnel mode.
|
||||
// Re-resolves the tunnel ghost type and completion partner from the current
|
||||
// ghost tile, rotation, and sub-tile cursor position, storing both on the build
|
||||
// mode controller. Only meaningful in tunnel mode (REQ-BLD-TUNNEL-MODE).
|
||||
void updateTunnelGhost();
|
||||
// Indexes every tunnel entry/exit — built or still a construction site — by its
|
||||
// single-cell tile. Shared by the placement preview and the selection highlight.
|
||||
@@ -291,8 +287,8 @@ private:
|
||||
bool affordable; // meaningful only for PlaceNew
|
||||
std::optional<BuildingId> rotateId; // set only for RotateInPlace
|
||||
};
|
||||
// Recomputes m_beltDragPath from m_beltDragAnchor to cursorTile using the
|
||||
// current ghost orientation.
|
||||
// Recomputes the drag path from its anchor to cursorTile using the current ghost
|
||||
// orientation, and stores it on the build mode controller.
|
||||
void recomputeBeltDragPath(QPoint cursorTile);
|
||||
// Classifies each path tile against the current sim state, applying cumulative
|
||||
// affordability to the PlaceNew tiles.
|
||||
@@ -306,11 +302,9 @@ private:
|
||||
void copyConfigFrom(BuildingId id);
|
||||
void pasteConfigTo(BuildingId id);
|
||||
|
||||
void enterBuilderMode(BuildingType type);
|
||||
void exitBuilderMode();
|
||||
void enterBlueprintMode(Blueprint blueprint);
|
||||
void exitBlueprintMode();
|
||||
void toggleDeconstructMode();
|
||||
// Turns the ghost and refreshes everything that depends on its facing: placement
|
||||
// validity, the tunnel completion match, and an in-progress belt drag's path.
|
||||
// The mode transitions themselves live on m_buildMode.
|
||||
void rotateGhost(bool clockwise);
|
||||
|
||||
struct ActiveBeam
|
||||
@@ -364,28 +358,15 @@ private:
|
||||
|
||||
std::vector<ActiveBeam> m_activeBeams;
|
||||
|
||||
std::optional<BuildingType> m_builderType;
|
||||
Rotation m_ghostRotation;
|
||||
QPoint m_ghostTile;
|
||||
bool m_ghostValid;
|
||||
// Unified tunnel build mode (REQ-BLD-TUNNEL-MODE): while m_builderType is
|
||||
// TunnelEntry the ghost resolves to an entry or an exit based on the hovered
|
||||
// position; m_tunnelPartnerTile is the existing tunnel it would complete (drawn
|
||||
// as the green connection preview), or unset when there is no completion match.
|
||||
BuildingType m_tunnelGhostType = BuildingType::TunnelEntry;
|
||||
std::optional<QPoint> m_tunnelPartnerTile;
|
||||
// Deferred belt drag placement (REQ-BLD-BELT-DRAG): while dragging, the
|
||||
// rectilinear anchor->cursor path is recomputed on each move and only applied
|
||||
// on release. Empty unless a belt drag is in progress.
|
||||
std::vector<BeltPathTile> m_beltDragPath;
|
||||
QPoint m_beltDragAnchor;
|
||||
// Last known cursor position in world (tile) units; used to pick the belt-drag
|
||||
// end tile closest to the cursor when snapping to a building (REQ-BLD-BELT-DRAG).
|
||||
QVector2D m_cursorWorldPos;
|
||||
bool m_dragging;
|
||||
// The active build mode (builder / blueprint / deconstruct, or none) and the
|
||||
// ghost, tunnel and belt-drag state belonging to it. Owns the transitions
|
||||
// between them; this widget supplies the parts that need the simulation.
|
||||
BuildModeController m_buildMode;
|
||||
|
||||
std::optional<Blueprint> m_blueprintMode;
|
||||
QPoint m_blueprintGhostTile;
|
||||
// Last known cursor position in world (tile) units; used to pick the belt-drag
|
||||
// end tile closest to the cursor when snapping to a building (REQ-BLD-BELT-DRAG)
|
||||
// and to resolve the tunnel ghost sub-tile (REQ-BLD-TUNNEL-MODE).
|
||||
QVector2D m_cursorWorldPos;
|
||||
|
||||
// Temporary cache for the copy-settings gesture (REQ-BLD-COPY-CONFIG); held
|
||||
// only while Shift is down and cleared on Shift release.
|
||||
@@ -403,8 +384,6 @@ private:
|
||||
std::vector<CopyConfigFlash> m_copyConfigFlashes;
|
||||
static constexpr qint64 kCopyFlashDurationMs = 300;
|
||||
|
||||
bool m_deconstructMode;
|
||||
std::optional<BuildingId> m_deconstructHoverBuildingId;
|
||||
bool m_debugDraw;
|
||||
|
||||
// Owns the selection across all three categories and the rules for moving
|
||||
|
||||
Reference in New Issue
Block a user