-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move utilities from examples to
bevy_state
and add concept of state…
…-scoped entities (#13649) # Objective Move `StateScoped` and `log_transitions` to `bevy_state`, since they're useful for end users. Addresses #12852, although not in the way the issue had in mind. ## Solution - Added `bevy_hierarchy` to default features of `bevy_state`. - Move `log_transitions` to `transitions` module. - Move `StateScoped` to `state_scoped` module, gated behind `bevy_hierarchy` feature. - Refreshed implementation. - Added `enable_state_coped_entities<S: States>()` to add required machinery to `App` for clearing state-scoped entities. ## Changelog - Added `log_transitions` for displaying state transitions. - Added `StateScoped` for binding entity lifetime to state and app `enable_state_coped_entities` to register cleaning behavior. --------- Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: François Mockers <[email protected]>
- Loading branch information
1 parent
ad68722
commit 58a0c13
Showing
12 changed files
with
187 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
//! Tools for debugging states. | ||
use bevy_ecs::event::EventReader; | ||
use bevy_state::state::{StateTransitionEvent, States}; | ||
use bevy_utils::tracing::info; | ||
|
||
/// Logs state transitions into console. | ||
/// | ||
/// This system is provided to make debugging easier by tracking state changes. | ||
pub fn log_transitions<S: States>(mut transitions: EventReader<StateTransitionEvent<S>>) { | ||
// State internals can generate at most one event (of type) per frame. | ||
let Some(transition) = transitions.read().last() else { | ||
return; | ||
}; | ||
let name = std::any::type_name::<S>(); | ||
let StateTransitionEvent { exited, entered } = transition; | ||
info!("{} transition: {:?} => {:?}", name, exited, entered); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
use bevy_ecs::{ | ||
component::Component, | ||
entity::Entity, | ||
event::EventReader, | ||
system::{Commands, Query}, | ||
}; | ||
#[cfg(feature = "bevy_hierarchy")] | ||
use bevy_hierarchy::DespawnRecursiveExt; | ||
|
||
use crate::state::{StateTransitionEvent, States}; | ||
|
||
/// Entities marked with this component will be removed | ||
/// when the world's state of the matching type no longer matches the supplied value. | ||
/// | ||
/// To enable this feature remember to configure your application | ||
/// with [`enable_state_scoped_entities`](crate::app::AppExtStates::enable_state_scoped_entities) on your state(s) of choice. | ||
/// | ||
/// If `bevy_hierarchy` feature is enabled, which it is by default, the despawn will be recursive. | ||
/// | ||
/// ``` | ||
/// use bevy_state::prelude::*; | ||
/// use bevy_ecs::prelude::*; | ||
/// | ||
/// #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)] | ||
/// enum GameState { | ||
/// #[default] | ||
/// MainMenu, | ||
/// SettingsMenu, | ||
/// InGame, | ||
/// } | ||
/// | ||
/// # #[derive(Component)] | ||
/// # struct Player; | ||
/// | ||
/// fn spawn_player(mut commands: Commands) { | ||
/// commands.spawn(( | ||
/// StateScoped(GameState::InGame), | ||
/// Player | ||
/// )); | ||
/// } | ||
/// | ||
/// # struct AppMock; | ||
/// # impl AppMock { | ||
/// # fn init_state<S>(&mut self) {} | ||
/// # fn enable_state_scoped_entities<S>(&mut self) {} | ||
/// # fn add_systems<S, M>(&mut self, schedule: S, systems: impl IntoSystemConfigs<M>) {} | ||
/// # } | ||
/// # struct Update; | ||
/// # let mut app = AppMock; | ||
/// | ||
/// app.init_state::<GameState>(); | ||
/// app.enable_state_scoped_entities::<GameState>(); | ||
/// app.add_systems(OnEnter(GameState::InGame), spawn_player); | ||
/// ``` | ||
#[derive(Component)] | ||
pub struct StateScoped<S: States>(pub S); | ||
|
||
/// Removes entities marked with [`StateScoped<S>`] | ||
/// when their state no longer matches the world state. | ||
/// | ||
/// If `bevy_hierarchy` feature is enabled, which it is by default, the despawn will be recursive. | ||
pub fn clear_state_scoped_entities<S: States>( | ||
mut commands: Commands, | ||
mut transitions: EventReader<StateTransitionEvent<S>>, | ||
query: Query<(Entity, &StateScoped<S>)>, | ||
) { | ||
// We use the latest event, because state machine internals generate at most 1 | ||
// transition event (per type) each frame. No event means no change happened | ||
// and we skip iterating all entities. | ||
let Some(transition) = transitions.read().last() else { | ||
return; | ||
}; | ||
let Some(exited) = &transition.exited else { | ||
return; | ||
}; | ||
for (entity, binding) in &query { | ||
if binding.0 == *exited { | ||
#[cfg(feature = "bevy_hierarchy")] | ||
commands.entity(entity).despawn_recursive(); | ||
#[cfg(not(feature = "bevy_hierarchy"))] | ||
commands.entity(entity).despawn(); | ||
} | ||
} | ||
} |
Oops, something went wrong.