//! HUD interaction: action-button handlers, Modes/Menu popovers, and //! the chrome tap-to-toggle gesture. use super::*; /// `Changed` filter ensures we only react on the frame the /// interaction state transitions, avoiding repeat events while the button /// is held down. Each click handler fires the corresponding request event, /// which `pause_plugin` / `help_plugin` / `game_plugin` consume alongside /// their existing keyboard handlers. pub(super) fn handle_new_game_button( interaction_query: Query<&Interaction, (With, Changed)>, mut new_game: MessageWriter, ) { for interaction in &interaction_query { if *interaction == Interaction::Pressed { new_game.write(NewGameRequestEvent::default()); } } } pub(super) fn handle_undo_button( interaction_query: Query<&Interaction, (With, Changed)>, mut undo: MessageWriter, ) { for interaction in &interaction_query { if *interaction == Interaction::Pressed { undo.write(UndoRequestEvent); } } } /// Seconds the Undo button must be continuously held before hold-to-repeat /// kicks in. Long enough that a normal tap (press + release inside one or /// two frames) never triggers a second undo. const UNDO_HOLD_INITIAL_DELAY_SECS: f32 = 0.45; /// Interval between repeated undos while the hold continues. ~5.5 undos/s — /// fast enough to unwind a long line, slow enough to release in time when /// the board reaches the state the player wants. const UNDO_HOLD_REPEAT_INTERVAL_SECS: f32 = 0.18; /// Hold-to-repeat undo (Phase F): while the Undo button stays pressed, /// fire additional [`UndoRequestEvent`]s after an initial delay, one per /// repeat interval. The plain tap path stays in [`handle_undo_button`] /// (its `Changed` filter fires exactly once per press); /// this system only adds events once the hold outlives the delay, so a /// tap never double-undoes. /// /// Each repeat goes through the normal request queue — the scoring /// penalty and No-Undo-mode gating in the consumer apply to every step. pub(super) fn repeat_undo_on_hold( time: Res