use bevy_ecs::{
message::MessageWriter,
prelude::Schedule,
schedule::IntoScheduleConfigs,
system::{Commands, IntoSystem, ResMut},
};
use super::{states::States, take_next_state, transitions::*, NextState, State};
#[diagnostic::on_unimplemented(note = "consider annotating `{Self}` with `#[derive(States)]`")]
pub trait FreelyMutableState: States {
fn register_state(schedule: &mut Schedule) {
schedule.configure_sets((
ApplyStateTransition::<Self>::default()
.in_set(StateTransitionSystems::DependentTransitions),
ExitSchedules::<Self>::default().in_set(StateTransitionSystems::ExitSchedules),
TransitionSchedules::<Self>::default()
.in_set(StateTransitionSystems::TransitionSchedules),
EnterSchedules::<Self>::default().in_set(StateTransitionSystems::EnterSchedules),
));
schedule
.add_systems(
apply_state_transition::<Self>.in_set(ApplyStateTransition::<Self>::default()),
)
.add_systems(
last_transition::<Self>
.pipe(run_exit::<Self>)
.in_set(ExitSchedules::<Self>::default()),
)
.add_systems(
last_transition::<Self>
.pipe(run_transition::<Self>)
.in_set(TransitionSchedules::<Self>::default()),
)
.add_systems(
last_transition::<Self>
.pipe(run_enter::<Self>)
.in_set(EnterSchedules::<Self>::default()),
);
}
}
fn apply_state_transition<S: FreelyMutableState>(
event: MessageWriter<StateTransitionEvent<S>>,
commands: Commands,
current_state: Option<ResMut<State<S>>>,
next_state: Option<ResMut<NextState<S>>>,
) {
let Some((next_state, allow_same_state_transitions)) = take_next_state(next_state) else {
return;
};
let Some(current_state) = current_state else {
return;
};
internal_apply_state_transition(
event,
commands,
Some(current_state),
Some(next_state),
allow_same_state_transitions,
);
}