Esc and the main menu leave PLACE and DEMOLISH (#139) #145

Merged
liamjd merged 1 commit from 139-esc-leaves-place-demolish into main 2026-10-09 06:12:26 +01:00
Owner

Closes #139

What changed

  • GameState.cancel() is what Esc means in game. If a mode is armed, it sets the mode to NONE and does nothing else; with no mode, it toggles the main menu. One press never does both.
  • Opening the main menu by any route sets interaction_mode to NONE, before main_menu_changed fires, so a menu listener never sees an armed mode.
  • game.gd calls GameState.cancel() on ui_cancel, and MenuLayer.visible now follows main_menu_changed instead of being toggled alongside the flag.
  • PlacementController drops its selected type and rotation whenever PLACE ends. Esc and the menu end PLACE without going through cancel_placement(), and the panel un-presses the card without emitting building_type_selected(null), so the hidden ghost's state would otherwise survive and the rotate keys would keep acting on it.

Verification

  • test/unit/test_cancel.gd: 12 tests on the mode/menu transitions. Full suite 883 passing, 1 pre-existing pending. The new script fails on main, because cancel() does not exist there.
  • Headed: tools/screenshot_esc_cancel.gd loads the game scene, presses a card and sends real Escape key events through Input. Screenshots confirm: ghost visible, then the first Esc removes the ghost with the menu still closed, then the second Esc opens the menu (clock paused).
  • Tested manually by Liam.

Caveats

  • Esc in the options and keybindings panels is unchanged code. It still works because those panels sit later in the tree and handle ui_cancel first. Covered by the manual test, not by a unit test.
  • cancel() clears any non-NONE mode, so it will also cover TERRAIN once that mode is used.

🤖 Generated with Claude Code

Closes #139 ## What changed - **`GameState.cancel()`** is what Esc means in game. If a mode is armed, it sets the mode to NONE and does nothing else; with no mode, it toggles the main menu. One press never does both. - **Opening the main menu by any route** sets `interaction_mode` to NONE, before `main_menu_changed` fires, so a menu listener never sees an armed mode. - **`game.gd`** calls `GameState.cancel()` on `ui_cancel`, and `MenuLayer.visible` now follows `main_menu_changed` instead of being toggled alongside the flag. - **`PlacementController`** drops its selected type and rotation whenever PLACE ends. Esc and the menu end PLACE without going through `cancel_placement()`, and the panel un-presses the card without emitting `building_type_selected(null)`, so the hidden ghost's state would otherwise survive and the rotate keys would keep acting on it. ## Verification - `test/unit/test_cancel.gd`: 12 tests on the mode/menu transitions. Full suite 883 passing, 1 pre-existing pending. The new script fails on `main`, because `cancel()` does not exist there. - Headed: `tools/screenshot_esc_cancel.gd` loads the game scene, presses a card and sends real Escape key events through `Input`. Screenshots confirm: ghost visible, then the first Esc removes the ghost with the menu still closed, then the second Esc opens the menu (clock paused). - Tested manually by Liam. ## Caveats - Esc in the options and keybindings panels is unchanged code. It still works because those panels sit later in the tree and handle `ui_cancel` first. Covered by the manual test, not by a unit test. - `cancel()` clears any non-NONE mode, so it will also cover TERRAIN once that mode is used. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Esc now goes through GameState.cancel(): an armed mode is left first, and
only Esc with no mode toggles the menu, so one press never does both.
Opening the main menu by any route clears the mode before main_menu_changed
fires. The menu layer follows the flag instead of being toggled alongside it.

PlacementController drops its selected type and rotation whenever PLACE ends,
since Esc and the menu end it without going through cancel_placement().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
liamjd merged commit b96e820e7d into main 2026-10-09 06:12:26 +01:00
liamjd deleted branch 139-esc-leaves-place-demolish 2026-10-09 06:12:26 +01:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
liamjd/UntitledColonyBuilder!145
No description provided.