use std::ops::{Deref, DerefMut};
use {BuildData, EntityData, ModifyData};
use {Entity, EntityIter, EntityBuilder, EntityModifier};
use {System};
use entity::EntityManager;
enum Event<'a, T> where T: ComponentManager
{
BuildEntity(Entity, Box<EntityBuilder<T>+'a>),
ModifyEntity(Entity, Box<EntityModifier<T>+'a>),
RemoveEntity(Entity),
}
pub struct World<T, U> where T: ComponentManager, U: SystemManager<Components=T>
{
pub systems: U,
pub data: DataHelper<T>,
}
pub struct DataHelper<T> where T: ComponentManager
{
pub components: T,
entities: EntityManager,
event_queue: Vec<Event<'static, T>>,
}
pub unsafe trait ComponentManager: 'static
{
unsafe fn new() -> Self;
unsafe fn remove_all(&mut self, en: &Entity);
}
pub unsafe trait SystemManager: 'static
{
type Components: ComponentManager;
unsafe fn new() -> Self;
unsafe fn activated(&mut self, en: EntityData, co: &Self::Components);
unsafe fn reactivated(&mut self, en: EntityData, co: &Self::Components);
unsafe fn deactivated(&mut self, en: EntityData, co: &Self::Components);
unsafe fn update(&mut self, co: &mut DataHelper<Self::Components>);
}
impl<T: ComponentManager, U: SystemManager<Components=T>> Deref for World<T, U>
{
type Target = DataHelper<T>;
fn deref(&self) -> &DataHelper<T>
{
&self.data
}
}
impl<T: ComponentManager, U: SystemManager<Components=T>> DerefMut for World<T, U>
{
fn deref_mut(&mut self) -> &mut DataHelper<T>
{
&mut self.data
}
}
impl<T: ComponentManager> Deref for DataHelper<T>
{
type Target = T;
fn deref(&self) -> &T
{
&self.components
}
}
impl<T: ComponentManager> DerefMut for DataHelper<T>
{
fn deref_mut(&mut self) -> &mut T
{
&mut self.components
}
}
impl<T: ComponentManager> DataHelper<T>
{
pub fn with_entity_data<F, R>(&mut self, entity: &Entity, mut call: F) -> Option<R>
where F: FnMut(EntityData, &mut T) -> R
{
if self.entities.is_valid(entity) {
Some(call(EntityData(entity), self))
} else {
None
}
}
pub fn create_entity(&mut self, builder: Box<EntityBuilder<T>+'static>) -> Entity
{
let entity = self.entities.create();
self.event_queue.push(Event::BuildEntity(entity, builder));
entity
}
pub fn modify_entity(&mut self, entity: Entity, modifier: Box<EntityModifier<T>+'static>)
{
self.event_queue.push(Event::ModifyEntity(entity, modifier));
}
pub fn remove_entity(&mut self, entity: Entity)
{
self.event_queue.push(Event::RemoveEntity(entity));
}
}
impl<T: ComponentManager, U: SystemManager<Components=T>> World<T, U>
{
pub fn new() -> World<T, U>
{
World {
systems: unsafe { <U as SystemManager>::new() },
data: DataHelper {
components: unsafe { <T as ComponentManager>::new() },
entities: EntityManager::new(),
event_queue: Vec::new(),
},
}
}
pub fn create_entity<'a>(&mut self, mut builder: Box<EntityBuilder<T>+'a>) -> Entity
{
let entity = self.data.entities.create();
builder.build(BuildData(&entity), &mut self.data.components);
unsafe { self.systems.activated(EntityData(&entity), &self.data.components); }
entity
}
pub fn with_entity_data<F, R>(&mut self, entity: &Entity, mut call: F) -> Option<R>
where F: FnMut(EntityData, &mut T) -> R
{
if self.data.entities.is_valid(entity) {
Some(call(EntityData(entity), &mut self.data))
} else {
None
}
}
pub fn entities(&self) -> EntityIter<T>
{
self.data.entities.iter()
}
pub fn modify_entity(&mut self, entity: Entity, modifier: Box<EntityModifier<T>+'static>)
{
self.process_event(Event::ModifyEntity(entity, modifier));
}
pub fn remove_entity(&mut self, entity: Entity)
{
self.process_event(Event::RemoveEntity(entity));
}
fn process_event(&mut self, event: Event<T>)
{
process_event(&mut self.data.components, &mut self.systems, &mut self.data.entities, event);
}
fn flush_queue(&mut self)
{
for event in self.data.event_queue.drain()
{
process_event(&mut self.data.components, &mut self.systems, &mut self.data.entities, event);
}
}
pub fn update(&mut self)
{
self.flush_queue();
unsafe { self.systems.update(&mut self.data); }
}
}
fn process_event<T: ComponentManager, U: SystemManager<Components=T>>(components: &mut T, systems: &mut U, entities: &mut EntityManager, event: Event<T>)
{
match event
{
Event::BuildEntity(entity, mut builder) => {
builder.build(BuildData(&entity), components);
unsafe { systems.activated(EntityData(&entity), components); }
},
Event::ModifyEntity(entity, mut modifier) => {
modifier.modify(ModifyData(&entity), components);
unsafe { systems.reactivated(EntityData(&entity), components); }
},
Event::RemoveEntity(entity) => {
unsafe {
systems.deactivated(EntityData(&entity), components);
components.remove_all(&entity);
}
entities.remove(&entity);
}
}
}