fix(engine): eliminate panics, fix dismiss hit-test scope, guard home respawn
CR-2: dismiss_modal_on_scrim_click now queries only the target scrim's
Children rather than all ModalCard entities globally. Prevents
dismissing the wrong scrim when two overlapping modals are open.
CR-5: handle_home_draw_mode_buttons and handle_home_difficulty_toggle
now check other_modal_scrims.is_empty() before the despawn+respawn
cycle, preventing a concurrent second ModalScrim in the same frame.
H-1: solitaire_core::game_state — replaced all panicking piles[&key]
index accesses with safe .get().ok_or(MoveError::InvalidSource)?,
.get().is_some_and(...), or .get().and_then(...) in draw(),
check_auto_complete(), next_auto_complete_move(), foundation_slot_for().
H-5: input_plugin end_drag and touch_end_drag — replaced piles[&target]
with .get(&target).is_some_and(...) so missing pile types reject the
move rather than panicking.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -589,6 +589,7 @@ fn handle_home_draw_mode_buttons(
|
||||
one_buttons: Query<&Interaction, (With<HomeDrawOneButton>, Changed<Interaction>)>,
|
||||
three_buttons: Query<&Interaction, (With<HomeDrawThreeButton>, Changed<Interaction>)>,
|
||||
screens: Query<Entity, With<HomeScreen>>,
|
||||
other_modal_scrims: Query<(), (With<crate::ui_modal::ModalScrim>, Without<HomeScreen>)>,
|
||||
mut settings: Option<ResMut<SettingsResource>>,
|
||||
storage_path: Option<Res<SettingsStoragePath>>,
|
||||
mut changed: MessageWriter<SettingsChangedEvent>,
|
||||
@@ -601,6 +602,12 @@ fn handle_home_draw_mode_buttons(
|
||||
if screens.is_empty() {
|
||||
return;
|
||||
}
|
||||
// Don't respawn while another modal sits on top — the despawn queues
|
||||
// immediately but executes at end of frame, so a respawn in the same
|
||||
// frame would create a second concurrent ModalScrim.
|
||||
if !other_modal_scrims.is_empty() {
|
||||
return;
|
||||
}
|
||||
let want_one = one_buttons.iter().any(|i| *i == Interaction::Pressed);
|
||||
let want_three = three_buttons.iter().any(|i| *i == Interaction::Pressed);
|
||||
if !want_one && !want_three {
|
||||
@@ -658,6 +665,7 @@ fn handle_home_difficulty_toggle(
|
||||
mut commands: Commands,
|
||||
toggles: Query<&Interaction, (With<HomeDifficultyToggle>, Changed<Interaction>)>,
|
||||
screens: Query<Entity, With<HomeScreen>>,
|
||||
other_modal_scrims: Query<(), (With<crate::ui_modal::ModalScrim>, Without<HomeScreen>)>,
|
||||
mut diff_expanded: ResMut<DifficultyExpanded>,
|
||||
progress: Option<Res<ProgressResource>>,
|
||||
stats: Option<Res<StatsResource>>,
|
||||
@@ -668,6 +676,9 @@ fn handle_home_difficulty_toggle(
|
||||
if screens.is_empty() {
|
||||
return;
|
||||
}
|
||||
if !other_modal_scrims.is_empty() {
|
||||
return;
|
||||
}
|
||||
if !toggles.iter().any(|i| *i == Interaction::Pressed) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user