use core::marker::PhantomData;
use bevy_ecs::{
component::{Component, Mutable},
resource::Resource,
system::{Res, ResMut},
};
use crate::{
access::{CurrentRef, FlushMut, FlushRef, NextMut, NextRef},
next_state::{NextState, NextStateMut, TriggerStateFlush},
pattern::{AnyStatePattern, AnyStateTransPattern, FnStatePattern, FnStateTransPattern},
};
pub trait State: Resource + Sized {
type Next: NextState<State = Self>;
const ANY: AnyStatePattern<Self> = AnyStatePattern(PhantomData);
const ANY_TO_ANY: AnyStateTransPattern<Self> = AnyStateTransPattern(PhantomData);
fn with<F>(f: F) -> FnStatePattern<Self, F>
where
F: 'static + Send + Sync + Fn(&Self) -> bool,
{
FnStatePattern::new(f)
}
fn when<F>(f: F) -> FnStateTransPattern<Self, F>
where
F: 'static + Send + Sync + Fn(&Self, &Self) -> bool,
{
FnStateTransPattern::new(f)
}
fn is_disabled(state: CurrentRef<Self>) -> bool {
state.is_disabled()
}
fn is_enabled(state: CurrentRef<Self>) -> bool {
state.is_enabled()
}
fn will_be_disabled(next: NextRef<Self>) -> bool {
next.get().is_none()
}
fn will_be_enabled(next: NextRef<Self>) -> bool {
next.get().is_some()
}
fn is_triggered(trigger: Res<TriggerStateFlush<Self>>) -> bool {
trigger.0
}
fn trigger(mut trigger: ResMut<TriggerStateFlush<Self>>) {
trigger.0 = true;
}
fn reset_trigger(mut trigger: ResMut<TriggerStateFlush<Self>>) {
trigger.0 = false;
}
}
pub trait StateExtEq: State + Eq {
fn will_change(state: FlushRef<Self>) -> bool {
state.will_change()
}
}
impl<S: State + Eq> StateExtEq for S {}
pub trait StateMut: State<Next: NextStateMut> {
fn disable(mut state: NextMut<Self>) {
state.set(None);
}
}
impl<S: State<Next: NextStateMut>> StateMut for S {}
pub trait StateMutExtClone: StateMut + Clone {
fn enable(self) -> impl Fn(FlushMut<Self>) + 'static + Send + Sync {
move |mut state| {
state.enable(self.clone());
}
}
fn toggle(self) -> impl Fn(FlushMut<Self>) + 'static + Send + Sync {
move |mut state| {
state.toggle(self.clone());
}
}
fn enter(self) -> impl Fn(NextMut<Self>) + 'static + Send + Sync {
move |mut state| {
state.enter(self.clone());
}
}
fn reset(mut state: FlushMut<Self>) {
state.reset();
}
fn refresh(mut state: FlushMut<Self>) {
state.refresh();
}
}
impl<S: StateMut + Clone> StateMutExtClone for S {}
pub trait StateMutExtDefault: StateMut + Default {
fn enable_default(mut state: FlushMut<Self>) {
state.enable_default();
}
fn toggle_default(mut state: FlushMut<Self>) {
state.toggle_default();
}
fn enter_default(mut state: NextMut<Self>) {
state.enter_default();
}
}
impl<S: StateMut + Default> StateMutExtDefault for S {}
pub trait LocalState: State<Next: Component> + Component<Mutability = Mutable> {}
impl<S: State<Next: Component> + Component<Mutability = Mutable>> LocalState for S {}