use std::sync::Mutex;
use crate::ecs::archetype::ComponentBundle;
use crate::ecs::entity::Entity;
use crate::ecs::universe::Universe;
pub enum Command {
SpawnEmpty,
SpawnWith(Box<dyn ComponentBundleSend>),
Despawn(Entity),
}
pub trait ComponentBundleSend: Send + Sync {
fn spawn_into(self: Box<Self>, universe: &mut Universe);
}
impl<B: ComponentBundle + Send + Sync + 'static> ComponentBundleSend for B {
fn spawn_into(self: Box<Self>, universe: &mut Universe) {
universe.spawn(*self);
}
}
pub struct Commands {
queue: Mutex<Vec<Command>>,
}
impl Commands {
pub fn new() -> Self {
Self {
queue: Mutex::new(Vec::new()),
}
}
pub fn spawn_empty(&self) {
self.queue
.lock()
.expect("commands lock")
.push(Command::SpawnEmpty);
}
pub fn spawn<B: ComponentBundle + Send + Sync + 'static>(&self, bundle: B) {
self.queue
.lock()
.expect("commands lock")
.push(Command::SpawnWith(Box::new(bundle)));
}
pub fn despawn(&self, entity: Entity) {
self.queue
.lock()
.expect("commands lock")
.push(Command::Despawn(entity));
}
pub fn apply(&self, universe: &mut Universe) {
let mut queue = self.queue.lock().expect("commands lock");
for cmd in queue.drain(..) {
match cmd {
Command::SpawnEmpty => {
universe.spawn_empty();
}
Command::SpawnWith(bundle) => {
bundle.spawn_into(universe);
}
Command::Despawn(entity) => {
universe.despawn(entity);
}
}
}
}
}
impl Default for Commands {
fn default() -> Self {
Self::new()
}
}
unsafe impl Send for Commands {}
unsafe impl Sync for Commands {}