secsy_ecs 0.0.2

Deprecated, don't use this
Documentation
use super::entities::*;
use std::cell::{RefCell, RefMut};

trait ComponentVec {
    fn as_any(&self) -> &dyn std::any::Any;
    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
    fn push_none(&mut self);
}

impl<C: 'static + Clone> ComponentVec for RefCell<Vec<Option<RefCell<C>>>> {
    fn as_any(&self) -> &dyn std::any::Any {
        self as &dyn std::any::Any
    }

    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
        self as &mut dyn std::any::Any
    }

    fn push_none(&mut self) {
        self.get_mut().push(None)
    }
}

#[derive(Default)]
pub struct World {
    count: usize,
    component_vectors: Vec<Box<dyn ComponentVec>>,
}

/// Holds the component data for a collection of entities.
/// Can retreive an entity's data via its ID, and then once the data has been
/// modified, it can be pushed back into the entity, again using its ID.
impl World {
    /// Creates a whole new `World`.
    pub fn new() -> Self {
        Self {
            count: 0,
            component_vectors: Vec::new(),
        }
    }

    /// Spawns a new entity in a `World`, and returns its ID.
    pub fn spawn(&mut self) -> EntityId {
        let entity_id = self.count;
        for component_vector in self.component_vectors.iter_mut() {
            component_vector.push_none();
        }
        self.count += 1;
        entity_id
    }

    /// Adds a component to an entity,
    /// but cannot replace it if it already exists.
    ///
    /// Example:
    /// ```
    /// use secsy_ecs::world::World;
    /// let mut w = World::new();
    /// let e = w.spawn();
    ///
    /// w.add_to(e, 621i32).unwrap();
    /// w.add_to(e, 621.0f64).unwrap();
    ///
    /// assert_eq!(w.get::<i32>(e).unwrap(), 621);
    /// assert_eq!(w.get::<f64>(e).unwrap(), 621.0);
    /// ```
    pub fn add_to<C: 'static + Clone>(
        &mut self,
        entity: EntityId,
        component: C,
    ) -> Result<ComponentAddSuccess, ComponentAddError> {
        // Search for any existing ComponentVecs that match
        // the type of the component being added.
        for component_vector in self.component_vectors.iter_mut() {
            if let Some(component_vector) = component_vector
                .as_any_mut()
                .downcast_mut::<RefCell<Vec<Option<RefCell<C>>>>>()
            {
                let slot = &mut component_vector.borrow_mut()[entity];

                if slot.is_some() {
                    return Err(ComponentAddError::ComponentExistsOnEntity);
                }

                *slot = Some(RefCell::new(component));

                return Ok(ComponentAddSuccess::ExistingType);
            }
        }

        // No matching component storage exists yet, so we have to make one.
        let mut new_component_vec = Vec::with_capacity(self.count);

        // All existing entities don't have this component, so we assign `None`
        for _ in 0..self.count {
            new_component_vec.push(None);
        }

        // Give this Entity the Component.
        new_component_vec[entity] = Some(RefCell::new(component));
        self.component_vectors
            .push(Box::new(RefCell::new(new_component_vec)));

        Ok(ComponentAddSuccess::NewType)
    }

    /// Replaces the data in an entity's component,
    /// but cannot add it if it doesn't already exist.
    ///
    /// Example:
    /// ```
    /// use secsy_ecs::world::World;
    ///
    /// let mut w = World::new();
    /// let e = w.spawn();
    ///
    /// w.add_to(e, 621i32).unwrap();
    /// w.set_for(e, 1337i32).unwrap();
    ///
    /// assert_ne!(w.get::<i32>(e).unwrap(), 621);
    /// assert_eq!(w.get::<i32>(e).unwrap(), 1337);
    /// ```
    pub fn set_for<C: 'static>(
        &mut self,
        entity: EntityId,
        component: C,
    ) -> Result<(), ComponentSetError> {
        // Search for existing ComponentVecs
        // that match the type of the component being added.
        for component_vector in self.component_vectors.iter_mut() {
            if let Some(vec) = component_vector
                .as_any_mut()
                .downcast_mut::<RefCell<Vec<Option<RefCell<C>>>>>()
            {
                let slot = &mut vec.borrow_mut()[entity];
                if let Some(old_component) = slot {
                    *old_component.borrow_mut() = component;
                    return Ok(());
                }
            }
        }
        Err(ComponentSetError::ComponentDoesNotExistOnEntity)
    }

    fn borrow_component_vec_mut<C: 'static>(&self) -> Option<RefMut<Vec<Option<RefCell<C>>>>> {
        for component_vector in self.component_vectors.iter() {
            if let Some(component_vector) = component_vector
                .as_any()
                .downcast_ref::<RefCell<Vec<Option<RefCell<C>>>>>()
            {
                return Some(component_vector.borrow_mut());
            }
        }
        None
    }

    /// Clones data from an entity's component.
    ///
    /// Example:
    /// ```
    /// use secsy_ecs::world::World;
    ///
    /// let mut w = World::new();
    /// let e = w.spawn();
    ///
    /// w.add_to(e, 621);
    ///
    /// assert_eq!(w.get::<i32>(e).unwrap(), 621);
    /// ```
    pub fn get<C: 'static + Clone>(&self, entity_id: EntityId) -> Option<C> {
        Some(
            self.borrow_component_vec_mut::<C>().unwrap()[entity_id]
                .as_ref()?
                .borrow()
                .clone()
        )
    }

    /// Get a list of entity IDs for entities
    /// which contain the specified component.
    ///
    /// # Examples:
    /// ```
    /// use secsy_ecs::world::*;
    /// use secsy_ecs::entities::*;
    ///
    /// let mut w = World::new();
    ///
    /// let _e1 = secsy_ecs::spawn_entity_with!(w, 621, "621", '7').unwrap();
    /// let _e2 = secsy_ecs::spawn_entity_with!(w, 621.0, "621", '7').unwrap();
    /// let _e3 = secsy_ecs::spawn_entity_with!(w, 621, 621.0, '7').unwrap();
    /// let _e4 = secsy_ecs::spawn_entity_with!(w, 621, 621.0, "621").unwrap();
    ///
    /// let qchar = w.query::<char>();
    /// let qstr = w.query::<&str>();
    /// let qi = w.query::<i32>();
    /// let qf = w.query::<f64>();
    ///
    /// assert_eq!(qchar.unwrap(), vec![0, 1, 2]);
    /// assert_eq!(qstr.unwrap(), vec![0, 1, 3]);
    /// assert_eq!(qi.unwrap(), vec![0, 2, 3]);
    /// assert_eq!(qf.unwrap(), vec![1, 2, 3]);
    /// ```
    pub fn query<C: 'static>(&self) -> Result<Vec<EntityId>, QueryError> {
        if let Some(component_vector) = self.borrow_component_vec_mut::<C>() {
            let numbers: Vec<EntityId> = (0..component_vector.len()).collect();

            let filtered = numbers
                .iter()
                .filter(|i| component_vector[**i].is_some())
                .copied()
                .collect::<Vec<_>>();

            return Ok(filtered);
        }
        Err(QueryError::WorldDoesNotContainType)
    }
}

#[derive(Debug)]
pub enum GetComponentError {
    WorldDoesNotContainType,
    EntityDoesNotContainComponent,
}

#[derive(Debug)]
pub enum QueryError {
    WorldDoesNotContainType,
}

#[cfg(test)]
mod tests {
    use crate::world::*;

    #[test]
    fn spawn() {
        let mut w = World::new();
        let e = w.spawn();
        let f = w.spawn();

        assert_eq!(e, 0);
        assert_eq!(f, 1);
    }
}