#[cfg(feature = "bevy_app")]
pub use app::*;
#[cfg(feature = "bevy_app")]
mod app {
use bevy_app::{App, MainScheduleOrder, Plugin, PreUpdate};
use tiny_bail::prelude::*;
use crate::schedule::StateFlush;
use super::*;
pub struct StatePlugin;
impl Plugin for StatePlugin {
fn build(&self, app: &mut App) {
#[cfg(feature = "bevy_state")]
app.add_plugins(bevy_state::app::StatesPlugin);
r!(app
.init_schedule(StateFlush)
.world_mut()
.get_resource_mut::<MainScheduleOrder>())
.insert_before(PreUpdate, StateFlush);
}
}
pub trait AppExtState {
fn register_state<S: RegisterState>(&mut self) -> &mut Self;
fn add_state<S: RegisterState>(&mut self) -> &mut Self;
fn init_state<S: RegisterState<Next: FromWorld>>(&mut self) -> &mut Self;
fn insert_state<T: NextState<State: RegisterState>>(&mut self, next: T) -> &mut Self;
}
impl AppExtState for App {
fn register_state<S: RegisterState>(&mut self) -> &mut Self {
if !state_exists::<S>(self.world()) {
S::register_state(self);
}
self
}
fn add_state<S: RegisterState>(&mut self) -> &mut Self {
if !state_exists::<S>(self.world()) {
insert_state(self.world_mut(), None::<S::Next>);
S::register_state(self);
}
self
}
fn init_state<S: RegisterState<Next: FromWorld>>(&mut self) -> &mut Self {
if !state_exists::<S>(self.world()) {
let next = S::Next::from_world(self.world_mut());
insert_state(self.world_mut(), Some(next));
S::register_state(self);
}
self
}
fn insert_state<T: NextState<State: RegisterState>>(&mut self, next: T) -> &mut Self {
insert_state(self.world_mut(), Some(next));
if !state_exists::<T::State>(self.world()) {
T::State::register_state(self);
}
self
}
}
pub trait RegisterState: State {
fn register_state(app: &mut App);
}
}
use bevy_ecs::{
system::{Commands, EntityCommands},
world::{EntityWorldMut, FromWorld, World},
};
use crate::{
next_state::{NextState, TriggerStateFlush},
prelude::State,
state::LocalState,
};
fn state_exists<S: State>(world: &World) -> bool {
world.contains_resource::<TriggerStateFlush<S>>()
}
fn insert_state<Next: NextState>(world: &mut World, next: Option<Next>) {
world.insert_resource(next.unwrap_or_else(Next::empty));
world.init_resource::<TriggerStateFlush<Next::State>>();
}
pub trait CommandsExtState {
fn add_state<S: State>(&mut self);
fn init_state<S: State<Next: FromWorld>>(&mut self);
fn insert_state<T: NextState>(&mut self, next: T);
}
impl CommandsExtState for Commands<'_, '_> {
fn add_state<S: State>(&mut self) {
self.queue(|world: &mut World| {
if !state_exists::<S>(world) {
insert_state(world, None::<S::Next>);
}
});
}
fn init_state<S: State<Next: FromWorld>>(&mut self) {
self.queue(|world: &mut World| {
if !state_exists::<S>(world) {
let next = S::Next::from_world(world);
insert_state(world, Some(next));
}
});
}
fn insert_state<T: NextState>(&mut self, next: T) {
self.queue(|world: &mut World| insert_state(world, Some(next)));
}
}
fn local_state_exists<S: LocalState>(entity: &EntityWorldMut) -> bool {
entity.contains::<TriggerStateFlush<S>>()
}
fn insert_local_state<Next: NextState<State: LocalState<Next = Next>>>(
entity: &mut EntityWorldMut,
next: Option<Next>,
) {
entity.insert((
next.unwrap_or_else(Next::empty),
TriggerStateFlush::<Next::State>::default(),
));
}
pub trait EntityCommandsExtState {
fn add_state<S: LocalState>(&mut self);
fn init_state<S: LocalState<Next: FromWorld>>(&mut self);
fn insert_state<T: NextState<State: LocalState<Next = T>>>(&mut self, next: T);
}
impl EntityCommandsExtState for EntityCommands<'_> {
fn add_state<S: LocalState>(&mut self) {
self.queue(|mut entity: EntityWorldMut| {
if !local_state_exists::<S>(&entity) {
insert_local_state(&mut entity, None::<S::Next>);
}
});
}
fn init_state<S: LocalState<Next: FromWorld>>(&mut self) {
self.queue(|mut entity: EntityWorldMut| {
if !local_state_exists::<S>(&entity) {
let next = entity.world_scope(S::Next::from_world);
insert_local_state(&mut entity, Some(next));
}
});
}
fn insert_state<T: NextState<State: LocalState<Next = T>>>(&mut self, next: T) {
self.queue(|mut entity: EntityWorldMut| insert_local_state(&mut entity, Some(next)));
}
}