summaryrefslogtreecommitdiff
path: root/ecs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs')
-rw-r--r--ecs/src/actions.rs16
-rw-r--r--ecs/src/component/storage.rs30
-rw-r--r--ecs/src/lib.rs13
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);
}