diff --git a/crates/bevy_app/src/sub_app.rs b/crates/bevy_app/src/sub_app.rs index b6974cc60f..aece290d39 100644 --- a/crates/bevy_app/src/sub_app.rs +++ b/crates/bevy_app/src/sub_app.rs @@ -308,6 +308,11 @@ impl SubApp { .add_event::>(); let schedule = self.get_schedule_mut(StateTransition).unwrap(); S::register_state(schedule); + let state = self.world.resource::>().get().clone(); + self.world.send_event(StateTransitionEvent { + exited: None, + entered: Some(state), + }); } self @@ -318,12 +323,15 @@ impl SubApp { pub fn insert_state(&mut self, state: S) -> &mut Self { if !self.world.contains_resource::>() { setup_state_transitions_in_world(&mut self.world, Some(Startup.intern())); - self.insert_resource::>(State::new(state)) + self.insert_resource::>(State::new(state.clone())) .init_resource::>() .add_event::>(); - let schedule = self.get_schedule_mut(StateTransition).unwrap(); S::register_state(schedule); + self.world.send_event(StateTransitionEvent { + exited: None, + entered: Some(state), + }); } self @@ -340,6 +348,11 @@ impl SubApp { self.add_event::>(); let schedule = self.get_schedule_mut(StateTransition).unwrap(); S::register_computed_state_systems(schedule); + let state = self.world.resource::>().get().clone(); + self.world.send_event(StateTransitionEvent { + exited: None, + entered: Some(state), + }); } self @@ -357,6 +370,11 @@ impl SubApp { self.add_event::>(); let schedule = self.get_schedule_mut(StateTransition).unwrap(); S::register_sub_state_systems(schedule); + let state = self.world.resource::>().get().clone(); + self.world.send_event(StateTransitionEvent { + exited: None, + entered: Some(state), + }); } self diff --git a/crates/bevy_state/src/state/freely_mutable_state.rs b/crates/bevy_state/src/state/freely_mutable_state.rs index 1fc809f9e5..c1e4e72e5c 100644 --- a/crates/bevy_state/src/state/freely_mutable_state.rs +++ b/crates/bevy_state/src/state/freely_mutable_state.rs @@ -17,17 +17,17 @@ pub trait FreelyMutableState: States { apply_state_transition::.in_set(ApplyStateTransition::::apply()), ) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_enter::) .in_set(StateTransitionSteps::EnterSchedules), ) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_exit::) .in_set(StateTransitionSteps::ExitSchedules), ) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_transition::) .in_set(StateTransitionSteps::TransitionSchedules), ) diff --git a/crates/bevy_state/src/state/state_set.rs b/crates/bevy_state/src/state/state_set.rs index 067711829d..feb9f6e7ac 100644 --- a/crates/bevy_state/src/state/state_set.rs +++ b/crates/bevy_state/src/state/state_set.rs @@ -9,9 +9,8 @@ use self::sealed::StateSetSealed; use super::{ apply_state_transition, computed_states::ComputedStates, internal_apply_state_transition, - run_enter, run_exit, run_transition, should_run_transition, sub_states::SubStates, - ApplyStateTransition, OnEnter, OnExit, OnTransition, State, StateTransitionEvent, - StateTransitionSteps, States, + last_transition, run_enter, run_exit, run_transition, sub_states::SubStates, + ApplyStateTransition, State, StateTransitionEvent, StateTransitionSteps, States, }; mod sealed { @@ -117,17 +116,17 @@ impl StateSet for S { schedule .add_systems(system.in_set(ApplyStateTransition::::apply())) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_enter::) .in_set(StateTransitionSteps::EnterSchedules), ) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_exit::) .in_set(StateTransitionSteps::ExitSchedules), ) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_transition::) .in_set(StateTransitionSteps::TransitionSchedules), ) @@ -181,17 +180,17 @@ impl StateSet for S { apply_state_transition::.in_set(StateTransitionSteps::ManualTransitions), ) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_enter::) .in_set(StateTransitionSteps::EnterSchedules), ) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_exit::) .in_set(StateTransitionSteps::ExitSchedules), ) .add_systems( - should_run_transition::> + last_transition:: .pipe(run_transition::) .in_set(StateTransitionSteps::TransitionSchedules), ) @@ -232,9 +231,9 @@ macro_rules! impl_state_set_sealed_tuples { schedule .add_systems(system.in_set(ApplyStateTransition::::apply())) - .add_systems(should_run_transition::>.pipe(run_enter::).in_set(StateTransitionSteps::EnterSchedules)) - .add_systems(should_run_transition::>.pipe(run_exit::).in_set(StateTransitionSteps::ExitSchedules)) - .add_systems(should_run_transition::>.pipe(run_transition::).in_set(StateTransitionSteps::TransitionSchedules)) + .add_systems(last_transition::.pipe(run_enter::).in_set(StateTransitionSteps::EnterSchedules)) + .add_systems(last_transition::.pipe(run_exit::).in_set(StateTransitionSteps::ExitSchedules)) + .add_systems(last_transition::.pipe(run_transition::).in_set(StateTransitionSteps::TransitionSchedules)) .configure_sets( ApplyStateTransition::::apply() .in_set(StateTransitionSteps::DependentTransitions) @@ -271,9 +270,9 @@ macro_rules! impl_state_set_sealed_tuples { schedule .add_systems(system.in_set(ApplyStateTransition::::apply())) .add_systems(apply_state_transition::.in_set(StateTransitionSteps::ManualTransitions)) - .add_systems(should_run_transition::>.pipe(run_enter::).in_set(StateTransitionSteps::EnterSchedules)) - .add_systems(should_run_transition::>.pipe(run_exit::).in_set(StateTransitionSteps::ExitSchedules)) - .add_systems(should_run_transition::>.pipe(run_transition::).in_set(StateTransitionSteps::TransitionSchedules)) + .add_systems(last_transition::.pipe(run_enter::).in_set(StateTransitionSteps::EnterSchedules)) + .add_systems(last_transition::.pipe(run_exit::).in_set(StateTransitionSteps::ExitSchedules)) + .add_systems(last_transition::.pipe(run_transition::).in_set(StateTransitionSteps::TransitionSchedules)) .configure_sets( ApplyStateTransition::::apply() .in_set(StateTransitionSteps::DependentTransitions) diff --git a/crates/bevy_state/src/state/transitions.rs b/crates/bevy_state/src/state/transitions.rs index 1e54911df9..bb3480765b 100644 --- a/crates/bevy_state/src/state/transitions.rs +++ b/crates/bevy_state/src/state/transitions.rs @@ -1,11 +1,11 @@ -use std::{marker::PhantomData, mem, ops::DerefMut}; +use std::{marker::PhantomData, mem}; use bevy_ecs::{ event::{Event, EventReader, EventWriter}, schedule::{ InternedScheduleLabel, IntoSystemSetConfigs, Schedule, ScheduleLabel, Schedules, SystemSet, }, - system::{Commands, In, Local, Res, ResMut}, + system::{Commands, In, ResMut}, world::World, }; @@ -202,34 +202,18 @@ pub fn apply_state_transition( *next_state_resource.as_mut() = NextState::::Unchanged; } -pub(crate) fn should_run_transition( - mut first: Local, - res: Option>>, - mut event: EventReader>, -) -> (Option>, PhantomData) { - let first_mut = first.deref_mut(); - if !*first_mut { - *first_mut = true; - if let Some(res) = res { - event.clear(); - - return ( - Some(StateTransitionEvent { - exited: None, - entered: Some(res.get().clone()), - }), - PhantomData, - ); - } - } - (event.read().last().cloned(), PhantomData) +/// Returns the latest state transition event of type `S`, if any are available. +pub fn last_transition( + mut reader: EventReader>, +) -> Option> { + reader.read().last().cloned() } pub(crate) fn run_enter( - In((transition, _)): In<(Option>, PhantomData>)>, + transition: In>>, world: &mut World, ) { - let Some(transition) = transition else { + let Some(transition) = transition.0 else { return; }; let Some(entered) = transition.entered else { @@ -240,10 +224,10 @@ pub(crate) fn run_enter( } pub(crate) fn run_exit( - In((transition, _)): In<(Option>, PhantomData>)>, + transition: In>>, world: &mut World, ) { - let Some(transition) = transition else { + let Some(transition) = transition.0 else { return; }; let Some(exited) = transition.exited else { @@ -254,13 +238,10 @@ pub(crate) fn run_exit( } pub(crate) fn run_transition( - In((transition, _)): In<( - Option>, - PhantomData>, - )>, + transition: In>>, world: &mut World, ) { - let Some(transition) = transition else { + let Some(transition) = transition.0 else { return; }; let Some(exited) = transition.exited else {