@@ -4,7 +4,7 @@ use std::mem;
44
55use crate as bevy_ecs;
66use crate :: change_detection:: DetectChangesMut ;
7- use crate :: schedule:: { ScheduleLabel , SystemSet } ;
7+ use crate :: schedule:: { ScheduleLabel , Schedules , SystemSet } ;
88use crate :: system:: Resource ;
99use crate :: world:: World ;
1010
@@ -54,6 +54,18 @@ pub struct OnEnter<S: States>(pub S);
5454#[ derive( ScheduleLabel , Clone , Debug , PartialEq , Eq , Hash ) ]
5555pub struct OnExit < S : States > ( pub S ) ;
5656
57+ /// The label of a [`Schedule`](super::Schedule) that **only** runs whenever [`State<S>`]
58+ /// exits the `from` state, AND enters the `to` state.
59+ ///
60+ /// Systems added to this schedule are always ran *after* [`OnExit`], and *before* [`OnEnter`].
61+ #[ derive( ScheduleLabel , Clone , Debug , PartialEq , Eq , Hash ) ]
62+ pub struct OnTransition < S : States > {
63+ /// The state being exited.
64+ pub from : S ,
65+ /// The state being entered.
66+ pub to : S ,
67+ }
68+
5769/// A [`SystemSet`] that will run within `CoreSet::Update` when this state is active.
5870///
5971/// This set, when created via `App::add_state`, is configured with both a base set and a run condition.
@@ -105,7 +117,16 @@ pub fn apply_state_transition<S: States>(world: &mut World) {
105117 next_state_resource. set_changed ( ) ;
106118
107119 let exited = mem:: replace ( & mut world. resource_mut :: < State < S > > ( ) . 0 , entered. clone ( ) ) ;
108- world. run_schedule ( OnExit ( exited) ) ;
120+ world. run_schedule ( OnExit ( exited. clone ( ) ) ) ;
121+
122+ let transition_schedule = OnTransition {
123+ from : exited,
124+ to : entered. clone ( ) ,
125+ } ;
126+ if world. resource :: < Schedules > ( ) . contains ( & transition_schedule) {
127+ world. run_schedule ( transition_schedule) ;
128+ }
129+
109130 world. run_schedule ( OnEnter ( entered) ) ;
110131 }
111132}
0 commit comments