From 0c4eb480be5d67b6440705fb4590cb493f248da0 Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Tue, 21 Jul 2026 21:06:54 +0200 Subject: [PATCH] Update belt drag L-path immediately on rotate --- docs/requirements.md | 1 + src/ui/GameWorldView.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/docs/requirements.md b/docs/requirements.md index c327d31..abc9b23 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -107,6 +107,7 @@ Modules in `modules.toml` define a `surface_mask` — a list of strings that des - REQ-BLD-PLACE-VALID: A placement position is valid only if (a) every footprint cell in the rotated `surface_mask` is satisfied by the underlying terrain — `A` cells coincide with asteroid tiles, `S` cells coincide with space tiles — (b) no footprint cell overlaps an existing placed building or construction site, except as allowed by REQ-BLD-ROTATE-IN-PLACE, and (c) the player has enough building blocks to afford the building. The ghost (REQ-BLD-GHOST) is rendered in a distinct "invalid" color — overriding its per-building coloring (REQ-BLD-GHOST) — when the current cursor position fails any of these conditions. - REQ-BLD-ROTATE-IN-PLACE: If the ghost's footprint exactly coincides with the footprint of an existing placed building or construction site of the same building type, clicking places no new construction site and consumes no building blocks. Instead, the existing building or site is rotated to match the ghost's rotation. If the target is a construction site, its construction progress is preserved. This applies in both normal builder mode and blueprint placement mode; in blueprint placement mode it is evaluated per building in the blueprint independently — buildings in the blueprint whose footprint coincides with an existing same-type building or site are rotated in place, while the remaining buildings in the blueprint are placed as normal construction sites (subject to the usual validity checks and total cost). - REQ-BLD-BELT-DRAG: **Belt drag placement.** For belts, placement is a deferred drag gesture rather than immediate per-tile placement: construction sites are not placed while the cursor hovers new tiles, but only once the player releases the left mouse button. Pressing the left mouse button in the game world while in belt builder mode starts a drag anchored at the tile under the cursor. As the cursor moves, a **rectilinear (L-shaped) path** of belt tiles is computed from the anchor tile to the tile under the cursor: the path first runs along the axis **parallel to the belt's current orientation** (REQ-BLD-ROTATE) — stepping toward the cursor's coordinate on that axis to a corner tile — and then runs along the orthogonal axis to the cursor tile. When the cursor shares the anchor's row or column the path degenerates to a straight line, and when it is on the anchor tile the path is a single tile. + - **Rotating during the drag.** Rotating the belt with R / Shift+R (REQ-BLD-ROTATE) while a drag is in progress re-picks the path's primary axis immediately from the new orientation and re-derives the whole path from the anchor to the current cursor tile, without waiting for the next cursor movement. - **Ghosts.** While dragging, a belt ghost (REQ-BLD-GHOST) is rendered on every path tile that would be acted on, instead of a single ghost under the cursor. Each ghost is oriented to point toward the next tile along the path toward the cursor, so the path forms one connected belt run that turns at the corner (curved belts along the path auto-derive per REQ-BLD-BELT); the final tile keeps the direction of its incoming step, and a single-tile path keeps the belt's current orientation. A tile occupied by only an existing belt or belt construction site is a valid target — its belt is re-oriented to follow the path — and shows a normal belt ghost. A tile occupied by a non-belt building or construction site, or otherwise an invalid belt position (REQ-BLD-PLACE-VALID), is drawn in the distinct invalid color, overriding the belt coloring. A tile whose new belt is unaffordable — the cumulative cost of the belts newly placed up to and including it exceeds the global stock — shows **no ghost at all**. - **Placement on release.** No construction site is placed while dragging. On releasing the left mouse button, the path is applied in order (anchor to cursor): each cell occupied by only an existing belt or belt construction site has that belt re-oriented in place to its path direction, consuming no building blocks and preserving any construction progress (REQ-BLD-ROTATE-IN-PLACE); each empty, valid cell gets a new belt construction site, consuming building blocks from the global stock (REQ-BLD-COST). Cells occupied by a non-belt building or construction site, cells that are otherwise invalid (REQ-BLD-PLACE-VALID), and cells whose new belt can no longer be afforded once the running total has been spent are skipped. This supersedes the click-to-place of REQ-BLD-PLACE for belts, including both the single-tile case and multi-tile drags that pass over existing belts. - **Right-click cancels the drag.** Right-clicking while a belt drag is in progress cancels it: the path is discarded, no construction site is placed, and belt builder mode stays active (the exception to REQ-BLD-BUILDER-MODE). Right-clicking when no drag is in progress exits builder mode as usual (REQ-BLD-BUILDER-MODE). diff --git a/src/ui/GameWorldView.cpp b/src/ui/GameWorldView.cpp index 9a4993c..ffe9dbb 100644 --- a/src/ui/GameWorldView.cpp +++ b/src/ui/GameWorldView.cpp @@ -2531,6 +2531,9 @@ void GameWorldView::rotateGhost(bool clockwise) m_ghostRotation = clockwise ? rotateClockwise(m_ghostRotation) : rotateCounterClockwise(m_ghostRotation); m_ghostValid = isValidPlacement(*m_builderType, m_ghostTile, m_ghostRotation); + // Rotating during a belt drag re-picks the path's primary axis immediately, + // without waiting for the next mouse move (REQ-BLD-BELT-DRAG). + if (m_dragging) { recomputeBeltDragPath(m_ghostTile); } } else if (m_blueprintMode.has_value()) {