@@ -4,7 +4,7 @@ use std::mem;
4
4
5
5
use crate as bevy_ecs;
6
6
use crate :: change_detection:: DetectChangesMut ;
7
- use crate :: schedule:: { ScheduleLabel , SystemSet } ;
7
+ use crate :: schedule:: { ScheduleLabel , Schedules , SystemSet } ;
8
8
use crate :: system:: Resource ;
9
9
use crate :: world:: World ;
10
10
@@ -54,6 +54,18 @@ pub struct OnEnter<S: States>(pub S);
54
54
#[ derive( ScheduleLabel , Clone , Debug , PartialEq , Eq , Hash ) ]
55
55
pub struct OnExit < S : States > ( pub S ) ;
56
56
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
+
57
69
/// A [`SystemSet`] that will run within `CoreSet::Update` when this state is active.
58
70
///
59
71
/// 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) {
105
117
next_state_resource. set_changed ( ) ;
106
118
107
119
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
+
109
130
world. run_schedule ( OnEnter ( entered) ) ;
110
131
}
111
132
}
0 commit comments