Add OnTransition schedule that is ran between OnExit and OnEnter (#7936)

This commit is contained in:
Christian Hughes 2023-03-10 03:06:23 -06:00 committed by GitHub
parent 7d9cb1c4ab
commit 8aa217cc8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 4 deletions

View file

@ -40,8 +40,8 @@ pub mod prelude {
schedule::{
apply_state_transition, apply_system_buffers, common_conditions::*, Condition,
IntoSystemConfig, IntoSystemConfigs, IntoSystemSet, IntoSystemSetConfig,
IntoSystemSetConfigs, NextState, OnEnter, OnExit, OnUpdate, Schedule, Schedules, State,
States, SystemSet,
IntoSystemSetConfigs, NextState, OnEnter, OnExit, OnTransition, OnUpdate, Schedule,
Schedules, State, States, SystemSet,
},
system::{
adapter as system_adapter,

View file

@ -4,7 +4,7 @@ use std::mem;
use crate as bevy_ecs;
use crate::change_detection::DetectChangesMut;
use crate::schedule::{ScheduleLabel, SystemSet};
use crate::schedule::{ScheduleLabel, Schedules, SystemSet};
use crate::system::Resource;
use crate::world::World;
@ -54,6 +54,18 @@ pub struct OnEnter<S: States>(pub S);
#[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)]
pub struct OnExit<S: States>(pub S);
/// The label of a [`Schedule`](super::Schedule) that **only** runs whenever [`State<S>`]
/// exits the `from` state, AND enters the `to` state.
///
/// Systems added to this schedule are always ran *after* [`OnExit`], and *before* [`OnEnter`].
#[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)]
pub struct OnTransition<S: States> {
/// The state being exited.
pub from: S,
/// The state being entered.
pub to: S,
}
/// A [`SystemSet`] that will run within `CoreSet::Update` when this state is active.
///
/// 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) {
next_state_resource.set_changed();
let exited = mem::replace(&mut world.resource_mut::<State<S>>().0, entered.clone());
world.run_schedule(OnExit(exited));
world.run_schedule(OnExit(exited.clone()));
let transition_schedule = OnTransition {
from: exited,
to: entered.clone(),
};
if world.resource::<Schedules>().contains(&transition_schedule) {
world.run_schedule(transition_schedule);
}
world.run_schedule(OnEnter(entered));
}
}