use crate::prelude::*;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
use std::any::type_name;
use std::marker::PhantomData;
#[derive(Resource)]
pub(crate) struct WorldReactorRes<T: WorldReactor>
{
sys_command: SystemCommand,
p: PhantomData<T>,
}
impl<T: WorldReactor> WorldReactorRes<T>
{
pub(crate) fn new(sys_command: SystemCommand) -> Self
{
Self{ sys_command, p: PhantomData::default() }
}
}
pub trait WorldReactor: Send + Sync + 'static
{
type StartingTriggers: ReactionTriggerBundle;
type Triggers: ReactionTriggerBundle;
fn reactor(self) -> SystemCommandCallback;
}
#[derive(SystemParam)]
pub struct Reactor<'w, T: WorldReactor>
{
inner: Option<Res<'w, WorldReactorRes<T>>>,
}
impl<'w, T: WorldReactor> Reactor<'w, T>
{
pub(crate) fn add_starting_triggers(&self, c: &mut Commands, triggers: T::StartingTriggers) -> bool
{
let Some(inner) = &self.inner
else
{
tracing::warn!("failed adding starting triggers, world reactor {:?} is missing; add it to your app with \
ReactAppExt::add_world_reactor", type_name::<T>());
return false;
};
c.react().with(triggers, inner.sys_command, ReactorMode::Persistent);
true
}
pub fn add(&self, c: &mut Commands, triggers: T::Triggers) -> bool
{
let Some(inner) = &self.inner
else
{
tracing::warn!("failed adding triggers, world reactor {:?} is missing; add it to your app with \
ReactAppExt::add_world_reactor", type_name::<T>());
return false;
};
c.react().with(triggers, inner.sys_command, ReactorMode::Persistent);
true
}
pub fn remove(&self, c: &mut Commands, triggers: impl ReactionTriggerBundle) -> bool
{
let Some(inner) = &self.inner
else
{
tracing::warn!("failed removing triggers, world reactor {:?} is missing; add it to your app with \
ReactAppExt::add_world_reactor", type_name::<T>());
return false;
};
let token = RevokeToken::new_from(inner.sys_command, triggers);
c.react().revoke(token);
true
}
pub fn run(&self, commands: &mut Commands) -> bool
{
let Some(inner) = &self.inner
else
{
tracing::warn!("failed running world reactor {:?} because it is missing; add it to your app with \
ReactAppExt::add_world_reactor", type_name::<T>());
return false;
};
commands.queue(inner.sys_command);
true
}
}