diff --git a/src/game.rs b/src/game.rs index 6d34ac8..8b897ba 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,3 +1,5 @@ +use crate::game::dialog::dialog_container; +use crate::game::dialog::{PauseContainer, PauseGame}; use crate::{ color::*, game::{ @@ -17,7 +19,6 @@ use bevy::color::palettes::basic::RED; use bevy::prelude::*; use bevy::time::Stopwatch; use bevy::utils::HashSet; -use bevy::window::WindowFocused; use sudoku::bitset::Set; use sudoku::board::{CellState, Digit}; use sudoku::strategy::StrategySolver; @@ -27,6 +28,7 @@ mod board; mod cell_state; mod control_tab; mod input; +mod dialog; mod position; pub struct SudokuPlugin; @@ -37,6 +39,7 @@ impl Plugin for SudokuPlugin { fn build(&self, app: &mut App) { control_tab::plugin(app); board::plugin(app); + dialog::plugin(app); app.init_resource::() .add_event::() .add_event::() @@ -57,14 +60,12 @@ impl Plugin for SudokuPlugin { on_new_candidate, check_solver, on_clean_cell, - check_window_focus, ) .run_if(in_state(GameState::Playing)), ) .add_observer(check_conflict) .add_observer(on_select_cell) .add_observer(remove_conflict) - .add_observer(on_pause_game) .add_observer(on_unselect_cell); } } @@ -130,111 +131,7 @@ fn setup_ui( }, )) .with_children(|builder| { - builder - .spawn(( - Name::new("dialog-container"), - Node { - display: Display::Flex, - height: Val::Percent(100.0), - width: Val::Percent(100.0), - align_items: AlignItems::Center, - flex_wrap: FlexWrap::NoWrap, - justify_content: JustifyContent::Center, - position_type: PositionType::Absolute, - left: Val::Px(0.0), - right: Val::Px(0.0), - ..default() - }, - ZIndex(999), - - - // BackgroundColor(RED.into()), - )) - .with_children(|builder| { - builder - .spawn(( - Name::new("pause-container"), - Visibility::Hidden, - PauseContainer, - Node { - height: Val::Auto, - width: Val::Px(667.0), - min_height: Val::Px(332.0), - padding: UiRect::all(Val::Px(48.0)), - display: Display::Flex, - flex_direction: FlexDirection::Column, - align_items: AlignItems::Center, - align_content: AlignContent::Center, - justify_content: JustifyContent::Center, - ..default() - }, - BorderRadius::all(Val::Px(4.0)), - BoxShadow { - color: Color::BLACK.with_alpha(0.8), - x_offset: Val::Px(0.0), - y_offset: Val::Px(3.0), - spread_radius: Val::Px(-1.0), - blur_radius: Val::Px(12.0), - - }, - BackgroundColor(WHITE_COLOR), - )) - .with_children(|builder| { - builder - .spawn(( - Name::new("pause-title"), - Node { - margin: UiRect::all(Val::Px(16.0)), - ..default() - }, - )) - .with_children(|builder| { - builder.spawn(( - Text::new("Your game has been paused"), - TextFont { - font_size: 16.0, - font: font_assets.franklin_600.clone(), - ..default() - }, - TextColor(*DARK_BLACK), - )); - }); - - builder - .spawn(( - Name::new("pause-buttons"), - Button, - Node { - display: Display::Flex, - width: Val::Auto, - margin: UiRect { - top: Val::Px(30.0), - ..default() - }, - padding: UiRect::horizontal(Val::Px(38.0)), - min_height: Val::Px(48.0), - justify_content: JustifyContent::Center, - align_items: AlignItems::Center, - ..default() - }, - BorderRadius::all(Val::Px(40.0)), - BackgroundColor(*DARK_BLACK), - )) - .with_children(|builder| { - builder.spawn(( - Text::new("Resume"), - TextFont { - font_size: 14.0, - font: font_assets.franklin_500.clone(), - ..default() - }, - TextColor(WHITE_COLOR), - )); - }).observe(|_trigger: Trigger>, mut commands: Commands| { - commands.trigger(PauseGame(false)); - }); - }); - }); + dialog_container(&font_assets, builder); builder .spawn(Node { @@ -256,6 +153,8 @@ fn setup_ui( }); } + + fn toolbars( font_assets: &Res, texture_assets: &Res, @@ -961,31 +860,3 @@ fn update_game_time( game_timer.tick(time.delta()); text.0 = game_timer.to_string(); } - -fn check_window_focus(mut windows: EventReader, mut commands: Commands) { - for window in windows.read() { - if !window.focused { - commands.trigger(PauseGame(true)); - } - } -} - -#[derive(Event)] -pub struct PauseGame(pub bool); - -fn on_pause_game( - mut ev: Trigger, - mut time: ResMut>, - mut q_pause: Single<&mut Visibility, With>, -) { - if ev.event().0 { - time.pause(); - **q_pause = Visibility::Visible; - } else { - time.unpause(); - **q_pause = Visibility::Hidden; - } -} - -#[derive(Component)] -struct PauseContainer; diff --git a/src/game/dialog.rs b/src/game/dialog.rs new file mode 100644 index 0000000..9ef5d8c --- /dev/null +++ b/src/game/dialog.rs @@ -0,0 +1,149 @@ +use crate::color::{DARK_BLACK, WHITE_COLOR}; +use crate::loading::FontAssets; +use crate::GameState; +use bevy::prelude::*; +use bevy::window::WindowFocused; + +pub(super) fn plugin(app: &mut App) { + app.add_systems( + Update, + (check_window_focus,).run_if(in_state(GameState::Playing)), + ) + .add_observer(on_pause_game); +} + +pub(crate) fn dialog_container(font_assets: &Res, builder: &mut ChildBuilder) { + builder + .spawn(( + Name::new("dialog-container"), + Node { + display: Display::Flex, + height: Val::Percent(100.0), + width: Val::Percent(100.0), + align_items: AlignItems::Center, + flex_wrap: FlexWrap::NoWrap, + justify_content: JustifyContent::Center, + position_type: PositionType::Absolute, + left: Val::Px(0.0), + right: Val::Px(0.0), + ..default() + }, + ZIndex(999), + // BackgroundColor(RED.into()), + )) + .with_children(|builder| { + builder + .spawn(( + Name::new("pause-container"), + Visibility::Hidden, + PauseContainer, + Node { + height: Val::Auto, + width: Val::Px(667.0), + min_height: Val::Px(332.0), + padding: UiRect::all(Val::Px(48.0)), + display: Display::Flex, + flex_direction: FlexDirection::Column, + align_items: AlignItems::Center, + align_content: AlignContent::Center, + justify_content: JustifyContent::Center, + ..default() + }, + BorderRadius::all(Val::Px(4.0)), + BoxShadow { + color: Color::BLACK.with_alpha(0.8), + x_offset: Val::Px(0.0), + y_offset: Val::Px(3.0), + spread_radius: Val::Px(-1.0), + blur_radius: Val::Px(12.0), + }, + BackgroundColor(WHITE_COLOR), + )) + .with_children(|builder| { + builder + .spawn(( + Name::new("pause-title"), + Node { + margin: UiRect::all(Val::Px(16.0)), + ..default() + }, + )) + .with_children(|builder| { + builder.spawn(( + Text::new("Your game has been paused"), + TextFont { + font_size: 16.0, + font: font_assets.franklin_600.clone(), + ..default() + }, + TextColor(*DARK_BLACK), + )); + }); + + builder + .spawn(( + Name::new("pause-buttons"), + Button, + Node { + display: Display::Flex, + width: Val::Auto, + margin: UiRect { + top: Val::Px(30.0), + ..default() + }, + padding: UiRect::horizontal(Val::Px(38.0)), + min_height: Val::Px(48.0), + justify_content: JustifyContent::Center, + align_items: AlignItems::Center, + ..default() + }, + BorderRadius::all(Val::Px(40.0)), + BackgroundColor(*DARK_BLACK), + )) + .with_children(|builder| { + builder.spawn(( + Text::new("Resume"), + TextFont { + font_size: 14.0, + font: font_assets.franklin_500.clone(), + ..default() + }, + TextColor(WHITE_COLOR), + )); + }) + .observe( + |_trigger: Trigger>, mut commands: Commands| { + commands.trigger(PauseGame(false)); + }, + ); + }); + }); +} + +fn check_window_focus(mut windows: EventReader, mut commands: Commands) { + for window in windows.read() { + if !window.focused { + commands.trigger(PauseGame(true)); + } + } +} + +#[derive(Event)] +pub struct PauseGame(pub bool); + +fn on_pause_game( + ev: Trigger, + mut time: ResMut>, + mut q_pause: Single<&mut Visibility, With>, +) { + if ev.event().0 { + time.pause(); + **q_pause = Visibility::Visible; + } else { + time.unpause(); + **q_pause = Visibility::Hidden; + } +} + +#[derive(Component)] +pub struct PauseContainer;