use std::marker::PhantomData;
use derivative::Derivative;
use amethyst_error::Error;
use crate::{
ecs::prelude::{DispatcherBuilder, RunNow, System, World},
RunNowDesc, SystemBundle, SystemDesc,
};
pub trait DispatcherOperation<'a, 'b> {
fn exec(
self: Box<Self>,
world: &mut World,
dispatcher_builder: &mut DispatcherBuilder<'a, 'b>,
) -> Result<(), Error>;
}
#[derive(Debug)]
pub struct AddBarrier;
impl<'a, 'b> DispatcherOperation<'a, 'b> for AddBarrier {
fn exec(
self: Box<Self>,
_world: &mut World,
dispatcher_builder: &mut DispatcherBuilder<'a, 'b>,
) -> Result<(), Error> {
dispatcher_builder.add_barrier();
Ok(())
}
}
#[derive(Derivative)]
#[derivative(Debug)]
pub struct AddSystem<S> {
#[derivative(Debug = "ignore")]
pub system: S,
pub name: String,
pub dependencies: Vec<String>,
}
impl<'a, 'b, S> DispatcherOperation<'a, 'b> for AddSystem<S>
where
S: for<'s> System<'s> + Send + 'a,
{
fn exec(
self: Box<Self>,
_world: &mut World,
dispatcher_builder: &mut DispatcherBuilder<'a, 'b>,
) -> Result<(), Error> {
let dependencies = self
.dependencies
.iter()
.map(String::as_str)
.collect::<Vec<&str>>();
dispatcher_builder.add(self.system, &self.name, &dependencies);
Ok(())
}
}
#[derive(Derivative)]
#[derivative(Debug)]
pub struct AddSystemDesc<SD, S> {
#[derivative(Debug = "ignore")]
pub system_desc: SD,
pub name: String,
pub dependencies: Vec<String>,
pub marker: PhantomData<S>,
}
impl<'a, 'b, SD, S> DispatcherOperation<'a, 'b> for AddSystemDesc<SD, S>
where
SD: SystemDesc<'a, 'b, S>,
S: for<'s> System<'s> + Send + 'a,
{
fn exec(
self: Box<Self>,
world: &mut World,
dispatcher_builder: &mut DispatcherBuilder<'a, 'b>,
) -> Result<(), Error> {
let system = self.system_desc.build(world);
let dependencies = self
.dependencies
.iter()
.map(String::as_str)
.collect::<Vec<&str>>();
dispatcher_builder.add(system, &self.name, &dependencies);
Ok(())
}
}
#[derive(Derivative)]
#[derivative(Debug)]
pub struct AddThreadLocal<S> {
#[derivative(Debug = "ignore")]
pub system: S,
}
impl<'a, 'b, S> DispatcherOperation<'a, 'b> for AddThreadLocal<S>
where
S: for<'c> RunNow<'c> + 'b,
{
fn exec(
self: Box<Self>,
_world: &mut World,
dispatcher_builder: &mut DispatcherBuilder<'a, 'b>,
) -> Result<(), Error> {
dispatcher_builder.add_thread_local(self.system);
Ok(())
}
}
#[derive(Derivative)]
#[derivative(Debug)]
pub struct AddThreadLocalDesc<SD, S> {
#[derivative(Debug = "ignore")]
pub system_desc: SD,
pub marker: PhantomData<S>,
}
impl<'a, 'b, SD, S> DispatcherOperation<'a, 'b> for AddThreadLocalDesc<SD, S>
where
SD: RunNowDesc<'a, 'b, S>,
S: for<'c> RunNow<'c> + 'b,
{
fn exec(
self: Box<Self>,
world: &mut World,
dispatcher_builder: &mut DispatcherBuilder<'a, 'b>,
) -> Result<(), Error> {
let system = self.system_desc.build(world);
dispatcher_builder.add_thread_local(system);
Ok(())
}
}
#[derive(Derivative)]
#[derivative(Debug)]
pub struct AddBundle<B> {
#[derivative(Debug = "ignore")]
pub bundle: B,
}
impl<'a, 'b, B> DispatcherOperation<'a, 'b> for AddBundle<B>
where
B: SystemBundle<'a, 'b>,
{
fn exec(
self: Box<Self>,
world: &mut World,
dispatcher_builder: &mut DispatcherBuilder<'a, 'b>,
) -> Result<(), Error> {
self.bundle.build(world, dispatcher_builder)?;
Ok(())
}
}