use bevy::ecs::system::{BoxedSystem, EntityCommands};
use bevy::prelude::*;
use std::marker::PhantomData;
#[derive(Resource)]
struct InitializedSystem<I, O, S>
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: Send + Sync + 'static
{
sys : BoxedSystem<I, O>,
_phantom : PhantomData<S>
}
pub fn syscall<I, O, S, Marker>(world: &mut World, input: <I as bevy::prelude::SystemInput>::Inner<'_>, system: S) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static,
{
syscall_with_validation(world, input, system, |_|{})
}
pub fn syscall_with_validation<I, O, S, Marker>(
world: &mut World,
input: <I as bevy::prelude::SystemInput>::Inner<'_>,
system: S,
validation: fn(&mut World)
) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static,
{
let mut system =
match world.remove_resource::<InitializedSystem<I, O, S>>()
{
Some(system) => system,
None =>
{
(validation)(world);
let mut sys = IntoSystem::into_system(system);
sys.initialize(world);
InitializedSystem::<I, O, S>{ sys: Box::new(sys), _phantom: PhantomData::<S>{} }
}
};
let result = system.sys.run(input, world);
world.insert_resource(system);
return result;
}
pub fn prep_fncall<I, O, Marker>(
input : <I as bevy::prelude::SystemInput>::Inner<'static>,
system : impl IntoSystem<I, O, Marker> + Send + Sync + 'static + Clone
) -> impl Fn(&mut World) -> O + Send + Sync + 'static
where
I: Send + Sync + SystemInput + 'static + Clone, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync, <I as bevy::prelude::SystemInput>::Inner<'static>: Clone,
O: Send + Sync + 'static,
{
move |world: &mut World| syscall(world, input.clone(), system.clone())
}
pub trait WorldSyscallExt
{
fn syscall<I, O, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static;
fn syscall_with_validation<I, O, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World)) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static;
fn syscall_once<I, O, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static;
fn syscall_once_with_validation<I, O, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World)) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static;
}
impl WorldSyscallExt for World
{
fn syscall<I, O, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static
{
syscall(self, input, system)
}
fn syscall_with_validation<I, O, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World)) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static
{
syscall_with_validation(self, input, system, validation)
}
fn syscall_once<I, O, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static
{
let mut sys = IntoSystem::into_system(system);
sys.initialize(self);
sys.run(input, self)
}
fn syscall_once_with_validation<I, O, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World)) -> O
where
I: Send + Sync + SystemInput + 'static,
O: Send + Sync + 'static,
S: IntoSystem<I, O, Marker> + Send + Sync + 'static
{
(validation)(self);
let mut sys = IntoSystem::into_system(system);
sys.initialize(self);
sys.run(input, self)
}
}
pub trait CommandsSyscallExt
{
fn syscall<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S)
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static;
fn syscall_with_validation<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World))
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static;
fn syscall_once<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S)
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static;
fn syscall_once_with_validation<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World))
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static;
}
impl CommandsSyscallExt for Commands<'_, '_>
{
fn syscall<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S)
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static
{
self.queue(move |world: &mut World| { world.syscall(input, system); });
}
fn syscall_with_validation<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World))
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static
{
self.queue(move |world: &mut World| { world.syscall_with_validation(input, system, validation); });
}
fn syscall_once<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S)
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static
{
self.queue(move |world: &mut World| { world.syscall_once(input, system); });
}
fn syscall_once_with_validation<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World))
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static
{
self.queue(move |world: &mut World| { world.syscall_once_with_validation(input, system, validation); });
}
}
impl CommandsSyscallExt for EntityCommands<'_>
{
fn syscall<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S)
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static
{
self.commands().syscall(input, system);
}
fn syscall_with_validation<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World))
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static
{
self.commands().syscall_with_validation(input, system, validation);
}
fn syscall_once<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S)
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static
{
self.commands().syscall_once(input, system);
}
fn syscall_once_with_validation<I, S, Marker>(&mut self, input: <I as bevy::prelude::SystemInput>::Inner<'static>, system: S, validation: fn(&mut World))
where
I: Send + Sync + SystemInput + 'static, <I as bevy::prelude::SystemInput>::Inner<'static>: Send, <I as bevy::prelude::SystemInput>::Inner<'static>: Sync,
S: IntoSystem<I, (), Marker> + Send + Sync + 'static
{
self.commands().syscall_once_with_validation(input, system, validation);
}
}