#[cfg(feature = "bevy_app")]
pub use app::*;
#[cfg(feature = "bevy_app")]
mod app {
use core::marker::PhantomData;
use bevy_app::{App, Plugin};
use crate::schedule::StateFlush;
use super::*;
pub struct FlushMessagePlugin<S: State + Clone>(PhantomData<S>);
impl<S: State + Clone> Plugin for FlushMessagePlugin<S> {
fn build(&self, app: &mut App) {
app.add_message::<StateFlushMessage<S>>();
schedule_flush_message::<S>(app.get_schedule_mut(StateFlush).unwrap());
}
}
impl<S: State + Clone> Default for FlushMessagePlugin<S> {
fn default() -> Self {
Self(PhantomData)
}
}
pub struct LocalFlushMessagePlugin<S: State + Clone>(PhantomData<S>);
impl<S: LocalState + Clone> Plugin for LocalFlushMessagePlugin<S> {
fn build(&self, app: &mut App) {
app.add_message::<LocalStateFlushMessage<S>>();
schedule_local_flush_message::<S>(app.get_schedule_mut(StateFlush).unwrap());
}
}
impl<S: LocalState + Clone> Default for LocalFlushMessagePlugin<S> {
fn default() -> Self {
Self(PhantomData)
}
}
}
use bevy_ecs::{
entity::Entity,
message::{Message, MessageWriter},
schedule::{IntoScheduleConfigs as _, Schedule},
system::{Query, StaticSystemParam},
};
use crate::{
access::FlushRef,
next_state::{NextState, TriggerStateFlush},
schedule::ResolveStateSystems,
state::{LocalState, State},
};
#[derive(Message)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct StateFlushMessage<S: State> {
pub old: Option<S>,
pub new: Option<S>,
}
#[derive(Message)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct LocalStateFlushMessage<S: LocalState> {
pub entity: Entity,
pub old: Option<S>,
pub new: Option<S>,
}
fn write_flush_message<S: State + Clone>(
state: FlushRef<S>,
mut message: MessageWriter<StateFlushMessage<S>>,
) {
let (old, new) = state.get();
message.write(StateFlushMessage {
old: old.cloned(),
new: new.cloned(),
});
}
pub fn schedule_flush_message<S: State + Clone>(schedule: &mut Schedule) {
schedule.add_systems(write_flush_message::<S>.in_set(ResolveStateSystems::<S>::AnyFlush));
}
fn write_local_flush_message<S: LocalState + Clone>(
next_param: StaticSystemParam<<S::Next as NextState>::Param>,
state_query: Query<(Entity, Option<&S>, &S::Next, &TriggerStateFlush<S>)>,
mut messages: MessageWriter<LocalStateFlushMessage<S>>,
) {
for (entity, current, next, trigger) in &state_query {
if !trigger.0 {
continue;
}
messages.write(LocalStateFlushMessage {
entity,
old: current.cloned(),
new: next.next_state(&next_param).cloned(),
});
}
}
pub fn schedule_local_flush_message<S: LocalState + Clone>(schedule: &mut Schedule) {
schedule.add_systems(write_local_flush_message::<S>.in_set(ResolveStateSystems::<S>::Flush));
}