//! This example illustrates the use of [`SubStates`] for more complex state handling patterns. //! //! [`SubStates`] are [`States`] that only exist while the App is in another [`State`]. They can //! be used to create more complex patterns while relying on simple enums, or to de-couple certain //! elements of complex state objects. //! //! In this case, we're transitioning from a `Menu` state to an `InGame` state, at which point we create //! a substate called `IsPaused` to track whether the game is paused or not. use bevy::prelude::*; use ui::*; #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] enum AppState { #[default] Menu, InGame, } // In this case, instead of deriving `States`, we derive `SubStates` #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, SubStates)] // And we need to add an attribute to let us know what the source state is // and what value it needs to have. This will ensure that unless we're // in [`AppState::InGame`], the [`IsPaused`] state resource // will not exist. #[source(AppState = AppState::InGame)] enum IsPaused { #[default] Running, Paused, } fn main() { App::new() .add_plugins(DefaultPlugins) .init_state::() .add_sub_state::() // We set the substate up here. // Most of these remain the same .add_systems(Startup, setup) .add_systems(OnEnter(AppState::Menu), setup_menu) .add_systems(Update, menu.run_if(in_state(AppState::Menu))) .add_systems(OnExit(AppState::Menu), cleanup_menu) .add_systems(OnEnter(AppState::InGame), setup_game) .add_systems(OnEnter(IsPaused::Paused), setup_paused_screen) .add_systems( OnExit(IsPaused::Paused), clear_state_bound_entities(IsPaused::Paused), ) .add_systems( Update, ( // Instead of relying on [`AppState::InGame`] here, we're relying on // [`IsPaused::Running`], since we don't want movement or color changes // if we're paused (movement, change_color).run_if(in_state(IsPaused::Running)), // The pause toggle, on the other hand, needs to work whether we're // paused or not, so it uses [`AppState::InGame`] instead. toggle_pause.run_if(in_state(AppState::InGame)), ), ) .add_systems(Update, log_transitions) .run(); } fn menu( mut next_state: ResMut>, mut interaction_query: Query< (&Interaction, &mut UiImage), (Changed, With