fix(engine): resolve input coordination bugs in selection/pause/keyboard

- SelectionPlugin: add clear_selection_on_state_change system so undo/move/reject
  never leave a stale selection pointing at the wrong card
- SelectionPlugin: expose SelectionKeySet system set for cross-plugin ordering
- PausePlugin: skip Escape→pause when a card is keyboard-selected; toggle_pause
  now runs before SelectionKeySet so it reads SelectionState before it is cleared
- InputPlugin: guard Space→DrawRequestEvent when SelectionState has an active pile
  so Space executes a card move instead of also drawing from stock
- window: enforce 800×600 minimum via WindowResizeConstraints
- game_state: add precondition doc to next_auto_complete_move (waste exclusion)
- card_plugin: 12 unit tests for constants, face_colour, label_visibility, label_for
- pause_plugin: add paused_resource_default and draw_mode_label exhaustiveness tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-04-28 22:13:10 +00:00
parent ffc79447d4
commit 1ec2593137
6 changed files with 207 additions and 4 deletions
+7 -1
View File
@@ -43,6 +43,7 @@ use crate::pause_plugin::PausedResource;
use crate::progress_plugin::ProgressResource;
use crate::layout::{Layout, LayoutResource};
use crate::resources::{DragState, GameStateResource, HintCycleIndex};
use crate::selection_plugin::SelectionState;
use crate::time_attack_plugin::TimeAttackResource;
/// Z-depth used for cards while being dragged — above all resting cards.
@@ -144,6 +145,7 @@ fn handle_keyboard_core(
mut confirm: ResMut<KeyboardConfirmState>,
mut ev: CoreKeyboardMessages<'_>,
mut time_attack: Option<ResMut<TimeAttackResource>>,
selection: Option<Res<SelectionState>>,
) {
if paused.is_some_and(|p| p.0) {
return;
@@ -224,7 +226,11 @@ fn handle_keyboard_core(
}
}
if keys.just_pressed(KeyCode::KeyD) || keys.just_pressed(KeyCode::Space) {
// Space draws only when no card is keyboard-selected; when a card IS selected,
// SelectionPlugin handles Space to execute the move.
let space_draws = keys.just_pressed(KeyCode::Space)
&& selection.as_ref().is_none_or(|s| s.selected_pile.is_none());
if keys.just_pressed(KeyCode::KeyD) || space_draws {
// Cancel any pending forfeit when the player takes another action.
confirm.forfeit_countdown = 0.0;
ev.draw.write(DrawRequestEvent);