diff --git a/crates/comet_ecs/src/archetypes.rs b/crates/comet_ecs/src/archetypes.rs index 98e1dae..62c023f 100644 --- a/crates/comet_ecs/src/archetypes.rs +++ b/crates/comet_ecs/src/archetypes.rs @@ -48,4 +48,12 @@ impl Archetypes { pub fn contains_archetype(&self, components: &ComponentSet) -> bool { self.archetypes.contains_key(components) } + + pub fn archetype_contains_entity(&self, entity_id: u32, components: &ComponentSet) -> bool { + if self.contains_archetype(components) { + let archetype = self.get_archetype(components).unwrap(); + return archetype.contains(&entity_id); + } + false + } } \ No newline at end of file diff --git a/crates/comet_ecs/src/entity.rs b/crates/comet_ecs/src/entity.rs index e23d357..e906d90 100644 --- a/crates/comet_ecs/src/entity.rs +++ b/crates/comet_ecs/src/entity.rs @@ -8,11 +8,9 @@ pub struct Entity { impl Entity { pub(crate) fn new(id: u32) -> Self { - let mut components = BitSet::new(); - components.insert(0); Self { id, - components + components: BitSet::new() } } @@ -31,4 +29,4 @@ impl Entity { pub(crate) fn get_components(&self) -> &BitSet { &self.components } -} \ No newline at end of file +} diff --git a/crates/comet_ecs/src/scene.rs b/crates/comet_ecs/src/scene.rs index 83e63ca..45eafdc 100644 --- a/crates/comet_ecs/src/scene.rs +++ b/crates/comet_ecs/src/scene.rs @@ -1,8 +1,6 @@ use std::any::TypeId; use crate::{ - Entity, - Component, - IdQueue, + entity, Component, Entity, IdQueue }; use comet_log::*; use comet_structs::*; @@ -153,18 +151,27 @@ impl Scene { /// Registers a new component in the scene. pub fn register_component(&mut self) { - self.components.register_component::(self.entities.len()); - self.create_archetype(ComponentSet::from_ids(vec![C::type_id()])); - info!("Registered component: {}", C::type_name()); + if !self.components.contains(&C::type_id()) { + self.components.register_component::(self.entities.len()); + self.create_archetype(ComponentSet::from_ids(vec![C::type_id()])); + info!("Registered component: {}", C::type_name()); + return; + } + warn!("Component {} is already registered!", C::type_name()); } /// Deregisters a component from the scene. pub fn deregister_component(&mut self) { - self.components.deregister_component::(); - info!("Deregistered component: {}", C::type_name()); + if self.components.contains(&C::type_id()) { + self.components.deregister_component::(); + info!("Deregistered component: {}", C::type_name()); + return; + } + warn!("Component {} was not registered!", C::type_name()); } /// Adds a component to an entity by its ID and an instance of the component. + /// Overwrites the previous component if another component of the same type is added. pub fn add_component(&mut self, entity_id: usize, component: C) { self.components.set_component(entity_id, component); let component_index = self.components.keys().iter_mut().position(|x| *x == C::type_id()).unwrap(); @@ -173,11 +180,23 @@ impl Scene { if !self.archetypes.contains_archetype(&self.get_component_set(entity_id)) { self.create_archetype(self.get_component_set(entity_id)); + let powerset = ComponentSet::powerset(self.get_component_set(entity_id).to_vec()); + for set in powerset { + let component_set = ComponentSet::from_ids(set.iter().cloned().collect()); + if !self.archetypes.contains_archetype(&component_set) { + self.create_archetype(component_set.clone()); + self.add_entity_to_archetype(entity_id as u32, component_set); + } + else if !self.archetypes.archetype_contains_entity(entity_id as u32, &component_set) { + self.add_entity_to_archetype(entity_id as u32, component_set); + } + } } self.add_entity_to_archetype(entity_id as u32, ComponentSet::from_ids(vec![C::type_id()])); if self.get_component_set(entity_id) != ComponentSet::from_ids(vec![C::type_id()]) { self.add_entity_to_archetype(entity_id as u32, self.get_component_set(entity_id)); } + debug!("{:?}", self.archetypes); info!("Added component {} to entity {}!", C::type_name(), entity_id); } diff --git a/crates/comet_structs/src/componet_set.rs b/crates/comet_structs/src/componet_set.rs index c30889d..55b4552 100644 --- a/crates/comet_structs/src/componet_set.rs +++ b/crates/comet_structs/src/componet_set.rs @@ -20,6 +20,24 @@ impl ComponentSet { } } + pub fn powerset(ids: Vec) -> Vec> { + let n = ids.len(); + let mut subsets: Vec> = Vec::with_capacity(1 << n); + + for mask in 0..(1 << n) { + let mut subset = HashSet::new(); + for i in 0..n { + if (mask & (1 << i)) != 0 { + subset.insert(ids[i].clone()); + } + } + subsets.push(subset); + } + subsets.remove(0); + + subsets + } + pub fn is_subset(&self, other: &ComponentSet) -> bool { self.set.is_subset(&other.set) }