ecs 0.23.1

An Entity Component System (ECS) Framework
Documentation

#[cfg(feature="serialisation")] use cereal::{CerealData, CerealResult};
#[cfg(feature="serialisation")] use std::io::{Read, Write};

use std::ops::{Deref, DerefMut};

use {EntityData, ModifyData};
use {Entity, IndexedEntity, EntityIter};
use {EntityBuilder, EntityModifier};
use entity::EntityManager;

pub struct World<S> where S: SystemManager
{
    pub systems: S,
    pub data: DataHelper<S::Components, S::Services>,
}

pub struct DataHelper<C, M> where C: ComponentManager, M: ServiceManager
{
    pub components: C,
    pub services: M,
    entities: EntityManager<C>,
}

pub trait ComponentManager: 'static+Sized
{
    #[doc(hidden)]
    fn __new() -> Self;
    #[doc(hidden)]
    fn __remove_all(&mut self, &IndexedEntity<Self>);
}

pub trait ServiceManager: 'static {}

impl ServiceManager for () {}

pub trait SystemManager
{
    type Components: ComponentManager;
    type Services: ServiceManager;
    #[doc(hidden)]
    fn __new() -> Self;
    #[doc(hidden)]
    fn __activated(&mut self, EntityData<Self::Components>, &Self::Components, &mut Self::Services);
    #[doc(hidden)]
    fn __reactivated(&mut self, EntityData<Self::Components>, &Self::Components, &mut Self::Services);
    #[doc(hidden)]
    fn __deactivated(&mut self, EntityData<Self::Components>, &Self::Components, &mut Self::Services);
    #[doc(hidden)]
    fn __update(&mut self, &mut DataHelper<Self::Components, Self::Services>);
}

impl<S: SystemManager> Deref for World<S>
{
    type Target = DataHelper<S::Components, S::Services>;
    fn deref(&self) -> &DataHelper<S::Components, S::Services>
    {
        &self.data
    }
}

impl<S: SystemManager> DerefMut for World<S>
{
    fn deref_mut(&mut self) -> &mut DataHelper<S::Components, S::Services>
    {
        &mut self.data
    }
}

impl<C: ComponentManager, M: ServiceManager> Deref for DataHelper<C, M>
{
    type Target = C;
    fn deref(&self) -> &C
    {
        &self.components
    }
}

impl<C: ComponentManager, M: ServiceManager> DerefMut for DataHelper<C, M>
{
    fn deref_mut(&mut self) -> &mut C
    {
        &mut self.components
    }
}

impl<C: ComponentManager, M: ServiceManager> DataHelper<C, M>
{
    pub fn with_entity_data<F, R>(&mut self, entity: &Entity, mut call: F) -> Option<R>
        where F: FnMut(EntityData<C>, &mut C) -> R
    {
        if self.entities.is_valid(entity) {
            Some(call(EntityData(&self.entities.indexed(&entity).__clone()), self))
        } else {
            None
        }
    }

    pub fn create_entity<B>(&mut self, builder: B) -> Entity where B: EntityBuilder<C>
    {
        self.entities.create_entity(builder, &mut self.components)
    }

    pub fn remove_entity(&mut self, entity: Entity)
    {
        self.entities.remove_entity(entity);
    }
}

#[cfg(feature="serialisation")]
unsafe impl<C: ComponentManager, M: ServiceManager> CerealData for DataHelper<C, M> where C: CerealData, M: CerealData {
    fn write(&self, w: &mut Write) -> CerealResult<()> {
        try!(self.services.write(w));
        try!(self.entities.write(w));
        self.components.write(w)
    }

    fn read(r: &mut Read) -> CerealResult<Self> {
        let services = try!(CerealData::read(r));
        let entities = try!(CerealData::read(r));
        let components = try!(CerealData::read(r));
        Ok(DataHelper {
            components: components,
            services: services,
            entities: entities,
        })
    }
}

#[cfg(feature="serialisation")]
impl<S: SystemManager> World<S> where DataHelper<S::Components, S::Services>: CerealData {
    pub fn load(reader: &mut Read) -> CerealResult<World<S>> {
        let mut world = World {
            systems: S::__new(),
            data: try!(CerealData::read(reader)),
        };
        world.refresh();
        Ok(world)
    }

    pub fn save(&mut self, writer: &mut Write) -> CerealResult<()> {
        self.flush_queue();
        self.data.write(writer)
    }
}

impl<S: SystemManager> World<S>
{
    pub fn new() -> World<S> where S::Services: Default
    {
        World {
            systems: S::__new(),
            data: DataHelper {
                components: S::Components::__new(),
                services: S::Services::default(),
                entities: EntityManager::new(),
            },
        }
    }

    pub fn with_services(services: S::Services) -> World<S>
    {
        World {
            systems: S::__new(),
            data: DataHelper {
                components: S::Components::__new(),
                services: services,
                entities: EntityManager::new(),
            },
        }
    }

    pub fn entities(&self) -> EntityIter<S::Components>
    {
        self.data.entities.iter()
    }

    pub fn modify_entity<M>(&mut self, entity: Entity, modifier: M) where M: EntityModifier<S::Components>
    {
        let indexed = self.data.entities.indexed(&entity);
        modifier.modify(ModifyData(indexed), &mut self.data.components);
        self.systems.__reactivated(
            EntityData(indexed), &self.data.components, &mut self.data.services
        );
    }

    pub fn refresh(&mut self)
    {
        self.flush_queue();
        for entity in self.data.entities.iter() {
            self.systems.__reactivated(entity, &self.data.components, &mut self.data.services);
        }
    }

    pub fn flush_queue(&mut self)
    {
        self.data.entities.flush_queue(
            &mut self.data.components,
            &mut self.data.services,
            &mut self.systems
        );
    }

    pub fn update(&mut self)
    {
        self.flush_queue();
        self.systems.__update(&mut self.data);
        self.flush_queue();
    }
}