use crate::prelude::*;
use bevy::prelude::*;
#[derive(Debug, Default, Copy, Clone)]
pub struct SystemCommandCleanup
{
cleanup: Option<fn(&mut World)>,
}
impl SystemCommandCleanup
{
pub fn new(cleanup: fn(&mut World)) -> Self
{
Self{ cleanup: Some(cleanup) }
}
pub(crate) fn run(self, world: &mut World)
{
let Some(cleanup) = self.cleanup else { return; };
(cleanup)(world);
}
}
pub struct SystemCommandCallback
{
inner: Box<dyn FnMut(&mut World, SystemCommandCleanup) + Send + Sync + 'static>,
}
impl SystemCommandCallback
{
pub fn new<S, M>(system: S) -> Self
where
S: IntoSystem<(), (), M> + Send + Sync + 'static
{
let mut callback = RawCallbackSystem::new(system);
let command = move |world: &mut World, cleanup: SystemCommandCleanup|
{
callback.run_with_cleanup(world, (), move |world: &mut World| cleanup.run(world));
};
Self::with(command)
}
pub fn with(callback: impl FnMut(&mut World, SystemCommandCleanup) + Send + Sync + 'static) -> Self
{
Self{ inner: Box::new(callback) }
}
pub(crate) fn run(&mut self, world: &mut World, cleanup: SystemCommandCleanup)
{
(self.inner)(world, cleanup);
}
}
#[derive(Component)]
pub(crate) struct SystemCommandStorage
{
callback: Option<SystemCommandCallback>,
}
impl SystemCommandStorage
{
pub(crate) fn new(callback: SystemCommandCallback) -> Self
{
Self{ callback: Some(callback) }
}
pub(crate) fn insert(&mut self, callback: SystemCommandCallback)
{
self.callback = Some(callback);
}
pub(crate) fn take(&mut self) -> Option<SystemCommandCallback>
{
self.callback.take()
}
}
pub fn spawn_system_command<S, M>(world: &mut World, system: S) -> SystemCommand
where
S: IntoSystem<(), (), M> + Send + Sync + 'static,
{
spawn_system_command_from(world, SystemCommandCallback::new(system))
}
pub fn spawn_system_command_from(world: &mut World, callback: SystemCommandCallback) -> SystemCommand
{
SystemCommand(world.spawn(SystemCommandStorage::new(callback)).id())
}
pub fn spawn_rc_system_command<S, M>(world: &mut World, system: S) -> AutoDespawnSignal
where
S: IntoSystem<(), (), M> + Send + Sync + 'static,
{
let system_command = spawn_system_command(world, system);
world.resource::<AutoDespawner>().prepare(*system_command)
}
pub fn spawn_rc_system_command_from(world: &mut World, callback: SystemCommandCallback) -> AutoDespawnSignal
{
let system_command = spawn_system_command_from(world, callback);
world.resource::<AutoDespawner>().prepare(*system_command)
}