diff --git a/Cargo.toml b/Cargo.toml index e8a4c6426..f6aadea40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,5 +9,6 @@ license = "Apache-2.0" authors = ["Dzmitry Malyshau"] [dependencies] +mopa = "0.2" pulse = "0.5" threadpool = "1.0" diff --git a/examples/basic.rs b/examples/basic.rs index a03ec2dac..8d61eb488 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -19,11 +19,14 @@ fn main() { parsec::Scheduler::new(w, 4) }; scheduler.add_entity().with(CompInt(4)).with(CompBool(false)).build(); + let e = scheduler.add_entity().with(CompInt(9)).with(CompBool(true)).build(); scheduler.add_entity().with(CompInt(-1)).with(CompBool(false)).build(); scheduler.run1w1r(|b: &mut CompBool, a: &CompInt| { b.0 = a.0 > 0; }); + scheduler.del_entity(e); + scheduler.run(|warg| { let (mut sa, sb, entities) = warg.fetch(|comp| { (comp.write::(), diff --git a/src/lib.rs b/src/lib.rs index b6c5ac9f7..bddd88dae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,17 @@ +#[macro_use] +extern crate mopa; extern crate pulse; extern crate threadpool; -use std::any::{Any, TypeId}; +use std::any::TypeId; use std::cell::RefCell; use std::collections::HashMap; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use mopa::Any; use pulse::{Pulse, Signal}; use threadpool::ThreadPool; -pub use storage::{Storage, VecStorage, HashMapStorage}; +pub use storage::{Storage, StorageBase, VecStorage, HashMapStorage}; mod storage; @@ -52,16 +55,32 @@ impl<'a> Iterator for EntityIter<'a> { } } - pub trait Component: Any + Sized { type Storage: Storage + Any + Send + Sync; } +trait StorageLock: Any + Send + Sync { + fn del_slice(&self, &[Entity]); +} + +mopafy!(StorageLock); + +impl StorageLock for RwLock { + fn del_slice(&self, entities: &[Entity]) { + let mut guard = self.write().unwrap(); + for &e in entities.iter() { + guard.del(e); + } + } +} + + pub struct World { generations: RwLock>, - components: HashMap>, + components: HashMap>, } + impl World { pub fn new() -> World { World { @@ -74,9 +93,8 @@ impl World { self.components.insert(TypeId::of::(), Box::new(any)); } fn lock(&self) -> &RwLock { - use std::ops::Deref; let boxed = self.components.get(&TypeId::of::()).unwrap(); - (boxed.deref() as &Any).downcast_ref().unwrap() + boxed.downcast_ref().unwrap() } pub fn read<'a, T: Component>(&'a self) -> RwLockReadGuard<'a, T::Storage> { self.lock::().read().unwrap() @@ -172,9 +190,8 @@ impl Scheduler { EntityBuilder(ent, &self.world) } pub fn del_entity(&mut self, entity: Entity) { - for _boxed in self.world.components.values() { - //TODO! - //let lock = (boxed.deref() as &Any).downcast_ref().unwrap(); + for boxed in self.world.components.values() { + boxed.del_slice(&[entity]); } let mut gens = self.world.generations.write().unwrap(); let mut gen = &mut gens[entity.get_id() as usize]; diff --git a/src/storage.rs b/src/storage.rs index bb368c1ee..ee5721a70 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -2,7 +2,12 @@ use std::collections::HashMap; use {Entity, Generation}; -pub trait Storage: Sized { + +pub trait StorageBase { + fn del(&mut self, Entity); +} + +pub trait Storage: StorageBase + Sized { fn new() -> Self; fn get(&self, Entity) -> Option<&T>; fn get_mut(&mut self, Entity) -> Option<&mut T>; @@ -10,9 +15,15 @@ pub trait Storage: Sized { fn sub(&mut self, Entity) -> Option; } + #[derive(Debug)] pub struct VecStorage(pub Vec>); +impl StorageBase for VecStorage { + fn del(&mut self, entity: Entity) { + self.0[entity.get_id()] = None; + } +} impl Storage for VecStorage { fn new() -> Self { VecStorage(Vec::new()) @@ -36,13 +47,21 @@ impl Storage for VecStorage { self.0[entity.get_id()] = Some((entity.get_gen(), value)); } fn sub(&mut self, entity: Entity) -> Option{ - self.0[entity.get_id()].take().map(|(_, v)| v) + self.0[entity.get_id()].take().map(|(g, v)| { + assert_eq!(g, entity.get_gen()); + v + }) } } #[derive(Debug)] pub struct HashMapStorage(pub HashMap); +impl StorageBase for HashMapStorage { + fn del(&mut self, entity: Entity) { + self.0.remove(&entity); + } +} impl Storage for HashMapStorage { fn new() -> Self { HashMapStorage(HashMap::new())