use bevy::prelude::*;
#[cfg(not(target_arch = "wasm32"))]
use bevy::window::WindowMode;
use bevy::window::{CursorOptions, PrimaryWindow, Window};
use bevy_rapier3d::prelude::*;
use crate::level_loader::LevelAdvanceState;
use crate::ui::pause_overlay::{despawn_pause_overlay, spawn_pause_overlay};
#[derive(Resource, Default, Debug, Clone, Copy, PartialEq, Eq)]
pub enum PauseState {
#[default]
Active,
Paused {
#[cfg(not(target_arch = "wasm32"))]
window_mode_before_pause: WindowMode,
},
}
pub struct PausePlugin;
impl Plugin for PausePlugin {
fn build(&self, app: &mut App) {
app.init_resource::<PauseState>();
app.add_systems(Startup, hide_cursor_on_startup);
app.add_systems(
Update,
(
(handle_pause_input, handle_resume_input),
apply_pause_to_physics.after(crate::level_loader::LevelAdvanceSystems),
apply_pause_to_window_mode,
apply_pause_to_cursor,
(spawn_pause_overlay, despawn_pause_overlay),
)
.chain(),
);
}
}
fn handle_pause_input(
keyboard: Res<ButtonInput<KeyCode>>,
mut pause_state: ResMut<PauseState>,
level_advance: Res<LevelAdvanceState>,
#[cfg(not(target_arch = "wasm32"))] window: Single<&Window, With<PrimaryWindow>>,
) {
if keyboard.just_pressed(KeyCode::Escape)
&& matches!(*pause_state, PauseState::Active)
&& !level_advance.active
{
#[cfg(not(target_arch = "wasm32"))]
{
*pause_state = PauseState::Paused {
window_mode_before_pause: window.mode,
};
}
#[cfg(target_arch = "wasm32")]
{
*pause_state = PauseState::Paused {};
}
}
}
fn apply_pause_to_physics(
pause_state: Res<PauseState>,
mut rapier_config: Query<&mut RapierConfiguration>,
) {
let mut config = rapier_config.single_mut().unwrap();
match *pause_state {
PauseState::Active => {
config.physics_pipeline_active = true;
}
PauseState::Paused { .. } => {
config.physics_pipeline_active = false;
}
}
}
fn handle_resume_input(mouse: Res<ButtonInput<MouseButton>>, mut pause_state: ResMut<PauseState>) {
if mouse.just_pressed(MouseButton::Left) && matches!(*pause_state, PauseState::Paused { .. }) {
*pause_state = PauseState::Active;
}
}
#[cfg(not(target_arch = "wasm32"))]
fn apply_pause_to_window_mode(
pause_state: Res<PauseState>,
mut window: Single<&mut Window, With<PrimaryWindow>>,
mut previous_state: Local<Option<PauseState>>,
) {
if !pause_state.is_changed() {
return;
}
let current_state = *pause_state;
let prev = *previous_state;
match (prev, current_state) {
(
_,
PauseState::Paused {
window_mode_before_pause,
},
) => {
match window_mode_before_pause {
WindowMode::BorderlessFullscreen(_) | WindowMode::Fullscreen { .. } => {
window.mode = WindowMode::Windowed;
}
WindowMode::Windowed => {
}
}
}
(
Some(PauseState::Paused {
window_mode_before_pause,
}),
PauseState::Active,
) => {
window.mode = window_mode_before_pause;
}
_ => {
}
}
*previous_state = Some(current_state);
}
#[cfg(target_arch = "wasm32")]
fn apply_pause_to_window_mode(_pause_state: Res<PauseState>) {
}
fn apply_pause_to_cursor(
pause_state: Res<PauseState>,
mut cursor_options: Single<&mut CursorOptions, With<PrimaryWindow>>,
) {
if !pause_state.is_changed() {
return;
}
match *pause_state {
PauseState::Active => {
cursor_options.visible = false;
}
PauseState::Paused { .. } => {
cursor_options.visible = true;
}
}
}
fn hide_cursor_on_startup(mut cursor_options: Single<&mut CursorOptions, With<PrimaryWindow>>) {
cursor_options.visible = false;
}
pub fn not_paused(pause_state: Res<PauseState>) -> bool {
matches!(*pause_state, PauseState::Active)
}