From bc0ef5fbfa3fd927260325b3d278efe6a93a78d7 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Sat, 5 Jul 2025 16:04:43 -0400 Subject: [PATCH] State+Scene Transititions --- src/macros.rs | 15 +++---- src/plugins/camera.rs | 8 ++-- src/plugins/follow_cam.rs | 7 ++- src/plugins/game.rs | 17 ++------ src/plugins/main_menu.rs | 38 +++++++++++++++++ src/plugins/mod.rs | 2 + src/plugins/player.rs | 11 +++-- src/plugins/ship.rs | 6 +-- src/plugins/state_management.rs | 75 ++++++++++++++++++++++++++++----- src/states/game.rs | 9 +++- src/states/loading.rs | 18 -------- src/states/menu.rs | 2 + src/states/mod.rs | 1 - src/states/play.rs | 2 + 14 files changed, 145 insertions(+), 66 deletions(-) create mode 100644 src/plugins/main_menu.rs delete mode 100644 src/states/loading.rs diff --git a/src/macros.rs b/src/macros.rs index 84f02ee..050882f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -2,15 +2,14 @@ macro_rules! configure_sets { ( $app: expr, - $system_set: expr, $condition: expr ) => { - $app.configure_sets(PreUpdate, $system_set.run_if($condition)) - .configure_sets(Update, $system_set.run_if($condition)) - .configure_sets(PostUpdate, $system_set.run_if($condition)) - .configure_sets(Last, $system_set.run_if($condition)); - $app.configure_sets(FixedPreUpdate, $system_set.run_if($condition)) - .configure_sets(FixedUpdate, $system_set.run_if($condition)) - .configure_sets(FixedPostUpdate, $system_set.run_if($condition)); + $app.configure_sets(PreUpdate, $condition) + .configure_sets(Update, $condition) + .configure_sets(PostUpdate, $condition) + .configure_sets(Last, $condition); + $app.configure_sets(FixedPreUpdate, $condition) + .configure_sets(FixedUpdate, $condition) + .configure_sets(FixedPostUpdate, $condition); }; } diff --git a/src/plugins/camera.rs b/src/plugins/camera.rs index 3814b87..869772b 100644 --- a/src/plugins/camera.rs +++ b/src/plugins/camera.rs @@ -2,16 +2,16 @@ use bevy::prelude::*; #[cfg(feature = "dev")] use bevy::window::PrimaryWindow; -use crate::components::camera::*; +use crate::{components::camera::*, states::play::PlaySystems}; pub struct CameraPlugin; impl Plugin for CameraPlugin { fn build(&self, app: &mut App) { - app.add_systems(Update, camera_pitch); - app.add_systems(Update, camera_attachment); + app.add_systems(Update, camera_pitch.in_set(PlaySystems)); + app.add_systems(Update, camera_attachment.in_set(PlaySystems)); #[cfg(feature = "dev")] - app.add_systems(Update, camera_toggle); + app.add_systems(Update, camera_toggle.in_set(PlaySystems)); } } diff --git a/src/plugins/follow_cam.rs b/src/plugins/follow_cam.rs index 16014b2..5296f63 100644 --- a/src/plugins/follow_cam.rs +++ b/src/plugins/follow_cam.rs @@ -1,12 +1,15 @@ use bevy::prelude::*; -use crate::components::camera::{FollowCam, FollowTarget}; +use crate::{ + components::camera::{FollowCam, FollowTarget}, + states::play::PlaySystems, +}; pub struct FollowCamPlugin; impl Plugin for FollowCamPlugin { fn build(&self, app: &mut App) { - app.add_systems(Update, (set_cam_target, follow_cam).chain()); + app.add_systems(Update, (set_cam_target, follow_cam).chain().in_set(PlaySystems)); } } diff --git a/src/plugins/game.rs b/src/plugins/game.rs index ea2b051..162ccb2 100644 --- a/src/plugins/game.rs +++ b/src/plugins/game.rs @@ -8,8 +8,8 @@ use crate::{ states::{ game::*, input::{InputState, PlayerState}, - loading::{AssetLoadingState, StartupLoadingState}, menu::MenuState, + play::PlayStartupSystems, }, }; use bevy::{ @@ -24,22 +24,11 @@ pub struct GamePlugin; impl Plugin for GamePlugin { fn build(&self, app: &mut bevy::app::App) { - app.init_state::(); - app.init_state::(); - app.insert_state(GameState::Startup); - app.init_state::(); - app.init_state::(); - app.add_loading_state( - LoadingState::new(AssetLoadingState::Loading).continue_to_state(AssetLoadingState::Finalizing), - ) - .add_loading_state( - LoadingState::new(StartupLoadingState::Loading).continue_to_state(StartupLoadingState::Finalizing), - ); - app.add_plugins(( FollowCamPlugin, CameraPlugin, StateManagementPlugin, + MainMenuPlugin, // ShipPlugin, TypesPlugin, PlayerPlugin, @@ -49,7 +38,7 @@ impl Plugin for GamePlugin { #[cfg(feature = "dev-phys")] RapierDebugRenderPlugin::default(), )); - app.add_systems(Startup, (setup_scene, spawn_ship).chain()); + app.add_systems(Update, (setup_scene, spawn_ship).chain().in_set(PlayStartupSystems)); } } diff --git a/src/plugins/main_menu.rs b/src/plugins/main_menu.rs new file mode 100644 index 0000000..71d5513 --- /dev/null +++ b/src/plugins/main_menu.rs @@ -0,0 +1,38 @@ +use bevy::prelude::*; + +use crate::states::{ + game::GameState, + menu::{MainMenuSystems, MenuCleanupSystems, MenuStartupSystems, MenuState}, + play::PlayState, +}; + +pub struct MainMenuPlugin; + +impl Plugin for MainMenuPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Update, spawn_menu.in_set(MenuStartupSystems)); + app.add_systems(Update, clean_menu.in_set(MenuCleanupSystems)); + app.add_systems(Update, main_menu.in_set(MainMenuSystems)); + } +} + +fn spawn_menu(mut next: ResMut>) { + next.set(MenuState::Main); + info_once!("Moving to MenuState:{:?}", MenuState::Main); +} + +fn clean_menu(mut next: ResMut>) { + next.set(MenuState::Idle); + info_once!("Moving to MenuState:{:?}", MenuState::Loading); +} + +fn main_menu( + mut next_menu: ResMut>, + mut next_game: ResMut>, + mut next_play_state: ResMut>, +) { + next_menu.set(MenuState::Cleanup); + next_game.set(GameState::InGame); + next_play_state.set(PlayState::Loading); + info_once!("Moving to InGame"); +} diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index 6cace2a..7c277e5 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -2,6 +2,7 @@ mod camera; mod follow_cam; mod game; +mod main_menu; mod player; mod ship; mod ship_cam; @@ -12,6 +13,7 @@ mod types; pub use camera::*; pub use follow_cam::*; pub use game::*; +pub use main_menu::*; pub use player::*; pub use ship::*; pub use ship_cam::*; diff --git a/src/plugins/player.rs b/src/plugins/player.rs index eb06b5f..e6e8c56 100644 --- a/src/plugins/player.rs +++ b/src/plugins/player.rs @@ -9,7 +9,7 @@ use crate::{ player::{GravityDirection, JumpSpeed, MoveSpeed, PlayerDrag, PlayerForce, PlayerMotion, PlayerVelocity}, tags::Player, }, - states::input::PlayerInputSystems, + states::{input::PlayerInputSystems, play::PlaySystems}, utils::{input::get_mouse_delta, rotation::get_alignment_rotation_preserve_twist}, }; @@ -18,8 +18,13 @@ pub struct PlayerPlugin; impl Plugin for PlayerPlugin { fn build(&self, app: &mut App) { app.add_systems(PreUpdate, (keyboard_input, player_look).in_set(PlayerInputSystems)); - app.add_systems(Update, (apply_gravity, apply_forces, apply_motion, apply_drag).chain()); - app.add_systems(Update, align_with_gravity); + app.add_systems( + Update, + (apply_gravity, apply_forces, apply_motion, apply_drag) + .chain() + .in_set(PlaySystems), + ); + app.add_systems(Update, align_with_gravity.in_set(PlaySystems)); } } diff --git a/src/plugins/ship.rs b/src/plugins/ship.rs index 237b8ff..9a6c253 100644 --- a/src/plugins/ship.rs +++ b/src/plugins/ship.rs @@ -1,15 +1,15 @@ use bevy::{input::mouse::MouseMotion, prelude::*}; use bevy_rapier3d::prelude::*; -use crate::{components::tags::Ship, utils::input::get_mouse_delta}; +use crate::{components::tags::Ship, states::play::PlaySystems, utils::input::get_mouse_delta}; pub struct ShipPlugin; impl Plugin for ShipPlugin { fn build(&self, app: &mut App) { - app.add_systems(Update, ship_controls); + app.add_systems(Update, ship_controls.in_set(PlaySystems)); #[cfg(feature = "dev-viz")] - app.add_systems(Update, ship_debug); + app.add_systems(Update, ship_debug.in_set(PlaySystems)); } } diff --git a/src/plugins/state_management.rs b/src/plugins/state_management.rs index 7c0d24d..ae40bb4 100644 --- a/src/plugins/state_management.rs +++ b/src/plugins/state_management.rs @@ -1,8 +1,10 @@ use bevy::prelude::*; +use bevy_asset_loader::prelude::*; use crate::{ configure_sets, states::{ + game::{GameState, InGameSystems, MenuSystems}, input::{InputState, PlayerInputSystems, PlayerState}, menu::{ MainMenuSystems, MenuCleanupSystems, MenuStartupSystems, MenuState, OptionsMenuSystems, SavesMenuSystems, @@ -17,25 +19,76 @@ impl Plugin for StateManagementPlugin { fn build(&self, app: &mut App) { app.init_state::(); app.init_state::(); + app.init_state::(); + app.init_state::(); + app.init_state::(); + + //Loading + app.add_loading_state(LoadingState::new(MenuState::Loading).continue_to_state(MenuState::Startup)) + .add_loading_state(LoadingState::new(PlayState::Loading).continue_to_state(PlayState::Startup)); + + //Game + configure_sets!(app, MenuSystems.run_if(in_state(GameState::MainMenu))); + configure_sets!(app, InGameSystems.run_if(in_state(GameState::InGame))); //Menu - configure_sets!(app, MenuStartupSystems, in_state(MenuState::Startup)); - configure_sets!(app, MainMenuSystems, in_state(MenuState::Main)); - configure_sets!(app, OptionsMenuSystems, in_state(MenuState::Options)); - configure_sets!(app, SavesMenuSystems, in_state(MenuState::Saves)); - configure_sets!(app, MenuCleanupSystems, in_state(MenuState::Cleanup)); + configure_sets!( + app, + MenuStartupSystems + .run_if(in_state(MenuState::Startup)) + .in_set(MenuSystems) + ); + configure_sets!( + app, + MainMenuSystems.run_if(in_state(MenuState::Main)).in_set(MenuSystems) + ); + configure_sets!( + app, + OptionsMenuSystems + .run_if(in_state(MenuState::Options)) + .in_set(MenuSystems) + ); + configure_sets!( + app, + SavesMenuSystems.run_if(in_state(MenuState::Saves)).in_set(MenuSystems) + ); + configure_sets!(app, MenuCleanupSystems.run_if(in_state(MenuState::Cleanup))); //Play - configure_sets!(app, PlayStartupSystems, in_state(PlayState::Startup)); - configure_sets!(app, PausedSystems, in_state(PlayState::Paused)); - configure_sets!(app, PlaySystems, in_state(PlayState::Playing)); - configure_sets!(app, PlayCleanupSystems, in_state(PlayState::Cleanup)); + configure_sets!( + app, + PlayStartupSystems + .run_if(in_state(PlayState::Startup)) + .in_set(InGameSystems) + ); + configure_sets!( + app, + PausedSystems.run_if(in_state(PlayState::Paused)).in_set(InGameSystems) + ); + configure_sets!( + app, + PlaySystems.run_if(in_state(PlayState::Playing)).in_set(InGameSystems) + ); + configure_sets!(app, PlayCleanupSystems.run_if(in_state(PlayState::Cleanup))); //Input configure_sets!( app, - PlayerInputSystems, - in_state(InputState::World).and(in_state(PlayState::Playing)) + PlayerInputSystems + .run_if(in_state(InputState::World)) + .in_set(PlaySystems) ); + + //State Transitions + app.add_systems(Update, game_startup.in_set(PlayStartupSystems)); + app.add_systems(Update, game_cleanup.in_set(PlayCleanupSystems)); } } + +fn game_startup(mut next: ResMut>) { + next.set(PlayState::Playing); +} + +fn game_cleanup(mut next: ResMut>) { + next.set(PlayState::Idle); +} diff --git a/src/states/game.rs b/src/states/game.rs index 302e5f6..8c19e22 100644 --- a/src/states/game.rs +++ b/src/states/game.rs @@ -3,7 +3,12 @@ use bevy::prelude::*; #[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)] pub enum GameState { #[default] - Startup, MainMenu, - PlayGame, + InGame, } + +#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] +pub struct MenuSystems; + +#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] +pub struct InGameSystems; diff --git a/src/states/loading.rs b/src/states/loading.rs deleted file mode 100644 index ecf71aa..0000000 --- a/src/states/loading.rs +++ /dev/null @@ -1,18 +0,0 @@ -use bevy::prelude::*; -#[derive(States, Debug, Default, Clone, PartialEq, Eq, Hash)] -pub enum StartupLoadingState { - #[default] - Pending, - Loading, - Finalizing, - Done, -} - -#[derive(States, Debug, Default, Clone, PartialEq, Eq, Hash)] -pub enum AssetLoadingState { - #[default] - Pending, - Loading, - Finalizing, - Done, -} diff --git a/src/states/menu.rs b/src/states/menu.rs index ee529c7..746d216 100644 --- a/src/states/menu.rs +++ b/src/states/menu.rs @@ -3,7 +3,9 @@ use bevy::prelude::*; #[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)] pub enum MenuState { #[default] + Idle, Loading, + AssetFinalize, Startup, Main, Saves, diff --git a/src/states/mod.rs b/src/states/mod.rs index 3a8bdc0..7d3163a 100644 --- a/src/states/mod.rs +++ b/src/states/mod.rs @@ -1,5 +1,4 @@ pub mod game; pub mod input; -pub mod loading; pub mod menu; pub mod play; diff --git a/src/states/play.rs b/src/states/play.rs index 628eebc..93221f0 100644 --- a/src/states/play.rs +++ b/src/states/play.rs @@ -2,8 +2,10 @@ use bevy::prelude::*; #[derive(States, Debug, Reflect, Default, Clone, Copy, PartialEq, Eq, Hash)] pub enum PlayState { + Idle, #[default] Loading, + AssetFinalize, Startup, Playing, Paused,