diff options
Diffstat (limited to 'ecs')
-rw-r--r-- | ecs/src/actions.rs | 16 | ||||
-rw-r--r-- | ecs/src/component/storage.rs | 30 | ||||
-rw-r--r-- | ecs/src/lib.rs | 13 |
3 files changed, 58 insertions, 1 deletions
diff --git a/ecs/src/actions.rs b/ecs/src/actions.rs index 038f617..7698b45 100644 --- a/ecs/src/actions.rs +++ b/ecs/src/actions.rs @@ -2,7 +2,11 @@ use std::any::Any; use std::marker::PhantomData; use std::sync::{Arc, Weak}; -use crate::component::{Component, Sequence as ComponentSequence}; +use crate::component::{ + Component, + Metadata as ComponentMetadata, + Sequence as ComponentSequence, +}; use crate::entity::Uid as EntityUid; use crate::lock::{Lock, WriteGuard}; use crate::system::{NoInitParamFlag, Param as SystemParam, System}; @@ -33,6 +37,15 @@ impl<'world> Actions<'world> .push(Action::AddComponents(entity_uid, components.into_vec())); } + /// Removes component(s) from a entity. + pub fn remove_components<Comps>(&mut self, entity_uid: EntityUid) + where + Comps: ComponentSequence, + { + self.action_queue + .push(Action::RemoveComponents(entity_uid, Comps::metadata())); + } + /// Adds stopping the loop in [`Engine::event_loop`] at the next opportune time to the /// action queue. pub fn stop(&mut self) @@ -140,6 +153,7 @@ pub(crate) enum Action { Spawn(Vec<Box<dyn Component>>), AddComponents(EntityUid, Vec<Box<dyn Component>>), + RemoveComponents(EntityUid, Vec<ComponentMetadata>), Stop, } diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs index 76e1a7e..05ede9b 100644 --- a/ecs/src/component/storage.rs +++ b/ecs/src/component/storage.rs @@ -174,6 +174,36 @@ impl Storage Some(()) } + pub fn remove_components_from_entity( + &mut self, + entity_uid: EntityUid, + component_ids: impl IntoIterator<Item = ComponentId>, + ) -> Option<()> + { + let archetype_id = self.entity_archetype_lookup.get(&entity_uid)?; + + let archetype_index = + self.find_archetype_index_with_entity(*archetype_id, entity_uid)?; + + let archetype = self.archetypes.get_mut(archetype_index)?; + + let entity = archetype.take_entity(entity_uid)?; + + let component_ids_set = component_ids.into_iter().collect::<HashSet<_>>(); + + self.push_entity( + entity_uid, + entity + .components + .into_iter() + .map(|component| component.component.into_inner()) + .filter(|component| !component_ids_set.contains(&component.id())) + .collect(), + ); + + Some(()) + } + fn populate_matching_archetype_lookup_entries( &mut self, comp_ids_set: &HashSet<ComponentId>, diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index df65cb3..04c9b9f 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -170,6 +170,19 @@ impl World component_storage_lock .add_components_to_entity(entity_uid, components); } + Action::RemoveComponents(entity_uid, component_ids) => { + let mut component_storage_lock = + self.data.component_storage.write_nonblock().expect( + "Failed to acquire read-write component storage lock", + ); + + component_storage_lock.remove_components_from_entity( + entity_uid, + component_ids + .iter() + .map(|component_metadata| component_metadata.id), + ); + } Action::Stop => { self.stop.store(true, Ordering::Relaxed); } |