Move StateTransitionSteps registration to states plugin (#13939)

# Objective

Fixes #13920

## Solution

As described in the issue.

## Testing

Moved a custom transition plugin in example before any of the app-state
methods.
This commit is contained in:
MiniaczQ 2024-06-20 02:57:40 +02:00 committed by GitHub
parent ee2487a6e2
commit 31af724944
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 6 deletions

View file

@ -70,7 +70,6 @@ impl AppExtStates for SubApp {
fn init_state<S: FreelyMutableState + FromWorld>(&mut self) -> &mut Self { fn init_state<S: FreelyMutableState + FromWorld>(&mut self) -> &mut Self {
warn_if_no_states_plugin_installed(self); warn_if_no_states_plugin_installed(self);
if !self.world().contains_resource::<State<S>>() { if !self.world().contains_resource::<State<S>>() {
setup_state_transitions_in_world(self.world_mut(), Some(Startup.intern()));
self.init_resource::<State<S>>() self.init_resource::<State<S>>()
.init_resource::<NextState<S>>() .init_resource::<NextState<S>>()
.add_event::<StateTransitionEvent<S>>(); .add_event::<StateTransitionEvent<S>>();
@ -92,7 +91,6 @@ impl AppExtStates for SubApp {
fn insert_state<S: FreelyMutableState>(&mut self, state: S) -> &mut Self { fn insert_state<S: FreelyMutableState>(&mut self, state: S) -> &mut Self {
warn_if_no_states_plugin_installed(self); warn_if_no_states_plugin_installed(self);
if !self.world().contains_resource::<State<S>>() { if !self.world().contains_resource::<State<S>>() {
setup_state_transitions_in_world(self.world_mut(), Some(Startup.intern()));
self.insert_resource::<State<S>>(State::new(state.clone())) self.insert_resource::<State<S>>(State::new(state.clone()))
.init_resource::<NextState<S>>() .init_resource::<NextState<S>>()
.add_event::<StateTransitionEvent<S>>(); .add_event::<StateTransitionEvent<S>>();
@ -123,7 +121,6 @@ impl AppExtStates for SubApp {
.world() .world()
.contains_resource::<Events<StateTransitionEvent<S>>>() .contains_resource::<Events<StateTransitionEvent<S>>>()
{ {
setup_state_transitions_in_world(self.world_mut(), Some(Startup.intern()));
self.add_event::<StateTransitionEvent<S>>(); self.add_event::<StateTransitionEvent<S>>();
let schedule = self.get_schedule_mut(StateTransition).unwrap(); let schedule = self.get_schedule_mut(StateTransition).unwrap();
S::register_computed_state_systems(schedule); S::register_computed_state_systems(schedule);
@ -149,7 +146,6 @@ impl AppExtStates for SubApp {
.world() .world()
.contains_resource::<Events<StateTransitionEvent<S>>>() .contains_resource::<Events<StateTransitionEvent<S>>>()
{ {
setup_state_transitions_in_world(self.world_mut(), Some(Startup.intern()));
self.init_resource::<NextState<S>>(); self.init_resource::<NextState<S>>();
self.add_event::<StateTransitionEvent<S>>(); self.add_event::<StateTransitionEvent<S>>();
let schedule = self.get_schedule_mut(StateTransition).unwrap(); let schedule = self.get_schedule_mut(StateTransition).unwrap();
@ -221,6 +217,7 @@ impl Plugin for StatesPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
let mut schedule = app.world_mut().resource_mut::<MainScheduleOrder>(); let mut schedule = app.world_mut().resource_mut::<MainScheduleOrder>();
schedule.insert_after(PreUpdate, StateTransition); schedule.insert_after(PreUpdate, StateTransition);
setup_state_transitions_in_world(app.world_mut(), Some(Startup.intern()));
} }
} }
@ -228,6 +225,7 @@ impl Plugin for StatesPlugin {
mod tests { mod tests {
use crate::{ use crate::{
self as bevy_state, self as bevy_state,
app::StatesPlugin,
state::{State, StateTransition, StateTransitionEvent}, state::{State, StateTransition, StateTransitionEvent},
}; };
use bevy_app::App; use bevy_app::App;
@ -247,6 +245,7 @@ mod tests {
#[test] #[test]
fn insert_state_can_overwrite_init_state() { fn insert_state_can_overwrite_init_state() {
let mut app = App::new(); let mut app = App::new();
app.add_plugins(StatesPlugin);
app.init_state::<TestState>(); app.init_state::<TestState>();
app.insert_state(TestState::B); app.insert_state(TestState::B);
@ -266,6 +265,7 @@ mod tests {
#[test] #[test]
fn insert_state_can_overwrite_insert_state() { fn insert_state_can_overwrite_insert_state() {
let mut app = App::new(); let mut app = App::new();
app.add_plugins(StatesPlugin);
app.insert_state(TestState::B); app.insert_state(TestState::B);
app.insert_state(TestState::C); app.insert_state(TestState::C);

View file

@ -26,14 +26,17 @@ enum AppState {
fn main() { fn main() {
App::new() App::new()
.add_plugins(DefaultPlugins) // We insert the custom transitions plugin for `AppState`.
.add_plugins((
DefaultPlugins,
IdentityTransitionsPlugin::<AppState>::default(),
))
.init_state::<AppState>() .init_state::<AppState>()
.add_systems(Startup, setup) .add_systems(Startup, setup)
.add_systems(OnEnter(AppState::Menu), setup_menu) .add_systems(OnEnter(AppState::Menu), setup_menu)
.add_systems(Update, menu.run_if(in_state(AppState::Menu))) .add_systems(Update, menu.run_if(in_state(AppState::Menu)))
.add_systems(OnExit(AppState::Menu), cleanup_menu) .add_systems(OnExit(AppState::Menu), cleanup_menu)
// We will restart the game progress every time we re-enter into it. // We will restart the game progress every time we re-enter into it.
.add_plugins(IdentityTransitionsPlugin::<AppState>::default())
.add_systems(OnReenter(AppState::InGame), setup_game) .add_systems(OnReenter(AppState::InGame), setup_game)
.add_systems(OnReexit(AppState::InGame), teardown_game) .add_systems(OnReexit(AppState::InGame), teardown_game)
// Doing it this way allows us to restart the game without any additional in-between states. // Doing it this way allows us to restart the game without any additional in-between states.
@ -225,10 +228,12 @@ fn setup_game(mut commands: Commands, asset_server: Res<AssetServer>) {
texture: asset_server.load("branding/icon.png"), texture: asset_server.load("branding/icon.png"),
..default() ..default()
}); });
info!("Setup game");
} }
fn teardown_game(mut commands: Commands, player: Query<Entity, With<Sprite>>) { fn teardown_game(mut commands: Commands, player: Query<Entity, With<Sprite>>) {
commands.entity(player.single()).despawn(); commands.entity(player.single()).despawn();
info!("Teardown game");
} }
#[derive(Resource)] #[derive(Resource)]