pub use bevy::prelude::*;
use bevy::state::state::FreelyMutableState;
pub use double_dot_macro::*;
use prelude::{DoubleStateEvent, DoubleStateTransition};
pub mod prelude {
pub use bevy::prelude::*;
use bevy::state::state::FreelyMutableState;
pub use double_dot_macro::DoubleStates;
use crate::watch_state_event;
#[derive(Debug, Clone)]
pub enum DoubleStateTransition<S>
where
S: DoubleStates,
{
Linear,
Arbitrary(S),
}
pub enum DoubleStateSchedule<S>
where
S: DoubleStates + States,
{
OnEnter(OnEnter<S>),
OnExit(OnExit<S>),
}
pub struct DoubleStateSystemConfig<S>
where
S: DoubleStates + States,
{
pub schedule: DoubleStateSchedule<S>,
pub transition: DoubleStateTransition<S>,
}
#[derive(Debug, Clone, Message)]
pub struct DoubleStateEvent<S: DoubleStates>(pub DoubleStateTransition<S>);
pub trait AppExt {
fn add_double_state<S: DoubleStates + States + FreelyMutableState>(&mut self) -> &mut Self;
}
impl AppExt for App {
fn add_double_state<S: DoubleStates + States + FreelyMutableState>(&mut self) -> &mut Self {
self.init_state::<S>()
.add_message::<DoubleStateEvent<S>>()
.add_systems(Update, watch_state_event::<S>)
}
}
}
fn watch_state_event<S: DoubleStates + States + FreelyMutableState>(
mut state_event: MessageReader<DoubleStateEvent<S>>,
mut next_state: ResMut<NextState<S>>,
state: Res<State<S>>,
) {
for event in state_event.read() {
match &event.0 {
DoubleStateTransition::Linear => {
next_state.set(state.linear_transition())
}
DoubleStateTransition::Arbitrary(arb_state) => {
next_state.set(state.arbitrary_transition(&arb_state))
}
}
}
}
#[derive(Clone, Eq, PartialEq, Debug, Hash, DoubleStates, Default)]
#[allow(dead_code)]
enum TestState {
#[linear(MainMenu)]
Loading,
#[arbitrary(Playing, Exit)]
MainMenu,
#[default]
#[linear(Paused)]
Playing,
#[arbitrary(MainMenu, Exit)]
Paused,
Exit,
}