diff options
Diffstat (limited to 'ecs/src/component')
-rw-r--r-- | ecs/src/component/storage.rs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs new file mode 100644 index 0000000..cdff09e --- /dev/null +++ b/ecs/src/component/storage.rs @@ -0,0 +1,81 @@ +use std::any::{type_name, TypeId}; +use std::collections::HashSet; + +use crate::component::{Component, IsOptional as ComponentIsOptional}; +use crate::lock::Lock; +use crate::type_name::TypeName; +use crate::EntityComponent; + +#[derive(Debug, Default)] +pub struct ComponentStorage +{ + entities: Vec<Entity>, +} + +impl ComponentStorage +{ + pub fn find_entity_with_components( + &self, + start_index: usize, + component_type_ids: &[(TypeId, ComponentIsOptional)], + ) -> Option<(usize, &[EntityComponent])> + { + // TODO: This is a really dumb and slow way to do this. Refactor the world + // to store components in archetypes + self.entities + .iter() + .enumerate() + .skip(start_index) + .find(move |(_index, entity)| { + let entity_components = entity + .components + .iter() + .map(|component| component.id) + .collect::<HashSet<_>>(); + + if component_type_ids + .iter() + .filter(|(_, is_optional)| *is_optional == ComponentIsOptional::No) + .all(|(component_type_id, _)| { + entity_components.contains(component_type_id) + }) + { + return true; + } + + false + }) + .map(|(index, entity)| (index, &*entity.components)) + } + + pub fn push_entity( + &mut self, + components: impl IntoIterator<Item = Box<dyn Component>>, + ) + { + self.entities.push(Entity { + components: components + .into_iter() + .map(|component| EntityComponent { + id: (*component).type_id(), + name: component.type_name(), + component: Lock::new(component), + }) + .collect(), + }); + } +} + +impl TypeName for ComponentStorage +{ + fn type_name(&self) -> &'static str + { + type_name::<Self>() + } +} + +#[derive(Debug, Default)] +struct Entity +{ + components: Vec<EntityComponent>, +} |