summaryrefslogtreecommitdiff
path: root/ecs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs')
-rw-r--r--ecs/src/actions.rs4
-rw-r--r--ecs/src/component.rs37
-rw-r--r--ecs/src/component/storage/archetype.rs1
-rw-r--r--ecs/src/entity.rs5
-rw-r--r--ecs/src/event/component.rs6
-rw-r--r--ecs/src/lib.rs140
6 files changed, 43 insertions, 150 deletions
diff --git a/ecs/src/actions.rs b/ecs/src/actions.rs
index 3dd8755..e0efeda 100644
--- a/ecs/src/actions.rs
+++ b/ecs/src/actions.rs
@@ -23,7 +23,7 @@ impl<'world> Actions<'world>
.push(Action::Spawn(components.into_parts_array().into()));
}
- /// Queues up despawning a entity at the end of the **next** tick.
+ /// Queues up despawning a entity at the end of the current tick.
pub fn despawn(&mut self, entity_uid: Uid)
{
debug_assert_eq!(entity_uid.kind(), UidKind::Entity);
@@ -48,7 +48,7 @@ impl<'world> Actions<'world>
));
}
- /// Queues up removing component(s) from a entity at the end of the **next** tick.
+ /// Queues up removing component(s) from a entity at the end of the current tick.
pub fn remove_components(
&mut self,
entity_uid: Uid,
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index 5a8cd0b..6fb1230 100644
--- a/ecs/src/component.rs
+++ b/ecs/src/component.rs
@@ -2,8 +2,6 @@ use std::any::{type_name, Any};
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
-use ecs_macros::Component;
-use hashbrown::HashSet;
use seq_macro::seq;
use crate::lock::{
@@ -313,38 +311,3 @@ impl Default for PartsBuilder
Self { name: "(unspecified)" }
}
}
-
-/// Pending component removals for a entity.
-#[derive(Debug, Clone, Component)]
-pub struct Removals
-{
- component_ids: HashSet<Uid>,
-}
-
-impl Removals
-{
- pub fn contains<ComponentT: Component>(&self) -> bool
- {
- self.contains_id(ComponentT::id())
- }
-
- pub fn contains_id(&self, component_id: Uid) -> bool
- {
- self.component_ids.contains(&component_id)
- }
-
- pub(crate) fn add_ids(&mut self, ids: impl IntoIterator<Item = Uid>)
- {
- self.component_ids.extend(ids)
- }
-}
-
-impl FromIterator<Uid> for Removals
-{
- fn from_iter<T: IntoIterator<Item = Uid>>(iter: T) -> Self
- {
- Self {
- component_ids: iter.into_iter().collect(),
- }
- }
-}
diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs
index bb29701..a88e0e8 100644
--- a/ecs/src/component/storage/archetype.rs
+++ b/ecs/src/component/storage/archetype.rs
@@ -332,7 +332,6 @@ impl EntityComponent
}
}
- #[allow(dead_code)]
pub fn id(&self) -> Uid
{
self.id
diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs
index bab3d61..4496a2b 100644
--- a/ecs/src/entity.rs
+++ b/ecs/src/entity.rs
@@ -96,11 +96,6 @@ impl<'a> Handle<'a>
}
}
- pub fn component_ids(&self) -> impl Iterator<Item = Uid> + '_
- {
- self.archetype.component_ids_sorted()
- }
-
pub(crate) fn new(archetype: &'a Archetype, entity: &'a ArchetypeEntity) -> Self
{
Self { archetype, entity }
diff --git a/ecs/src/event/component.rs b/ecs/src/event/component.rs
index 72a78a3..ef09480 100644
--- a/ecs/src/event/component.rs
+++ b/ecs/src/event/component.rs
@@ -10,3 +10,9 @@ use crate::Component;
/// b) The target component is added to a entity.
#[derive(Debug, Component)]
pub struct Added(Infallible);
+
+/// Pair relation for events emitted when:
+/// a) The target component is removed from a entity.
+/// b) A entity with the target component is despawned.
+#[derive(Debug, Component)]
+pub struct Removed(Infallible);
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index 07b1cba..53abc6b 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -15,13 +15,14 @@ use crate::component::storage::archetype::EntityComponent as ArchetypeEntityComp
use crate::component::storage::Storage as ComponentStorage;
use crate::component::{
Component,
- IntoParts,
Parts as ComponentParts,
- Removals as ComponentRemovals,
Sequence as ComponentSequence,
};
-use crate::entity::{Handle as EntityHandle, CREATE_STATIC_ENTITIES};
-use crate::event::component::Added as ComponentAddedEvent;
+use crate::entity::CREATE_STATIC_ENTITIES;
+use crate::event::component::{
+ Added as ComponentAddedEvent,
+ Removed as ComponentRemovedEvent,
+};
use crate::extension::{Collector as ExtensionCollector, Extension};
use crate::lock::Lock;
use crate::pair::{ChildOf, DependsOn, Pair};
@@ -208,12 +209,8 @@ impl World
self.data.component_storage.create_imaginary_archetypes();
- let prev_pending_removals = std::mem::take(&mut self.data.pending_removals);
-
self.perform_queued_actions();
- self.perform_removals(prev_pending_removals);
-
if self.stop.load(Ordering::Relaxed) {
return StepResult::Stop;
}
@@ -358,8 +355,6 @@ impl World
let mut has_swapped_active_queue = false;
- // TODO: Figure out a good way to handle situations where there are multiple
- // AddComponents/RemoveComponents actions that affect the same entity.
for action in active_action_queue.drain(..) {
match action {
Action::Spawn(components) => {
@@ -387,12 +382,24 @@ impl World
}
}
Action::Despawn(entity_uid) => {
- Self::schedule_removal(
- &mut self.data.component_storage,
- &mut self.data.pending_removals,
- entity_uid,
- PendingRemoval::Entity,
- );
+ let removed_entity =
+ match self.data.component_storage.remove_entity(entity_uid) {
+ Ok(components) => components,
+ Err(err) => {
+ tracing::error!("Failed to despawn entity: {err}");
+ return;
+ }
+ };
+
+ if !has_swapped_active_queue {
+ self.swap_event_queue(&mut has_swapped_active_queue);
+ }
+
+ for removed_ent_comp in removed_entity.components() {
+ self.emit_event_by_id::<ComponentRemovedEvent>(
+ removed_ent_comp.id(),
+ );
+ }
}
Action::AddComponents(entity_uid, components) => {
let added_component_ids = Self::add_entity_components(
@@ -410,12 +417,19 @@ impl World
}
}
Action::RemoveComponents(entity_uid, component_ids) => {
- Self::schedule_removal(
- &mut self.data.component_storage,
- &mut self.data.pending_removals,
+ let removed_component_ids = Self::remove_entity_components(
entity_uid,
- PendingRemoval::Components(component_ids),
+ component_ids,
+ &mut self.data.component_storage,
);
+
+ if !has_swapped_active_queue {
+ self.swap_event_queue(&mut has_swapped_active_queue);
+ }
+
+ for comp_id in removed_component_ids {
+ self.emit_event_by_id::<ComponentRemovedEvent>(comp_id);
+ }
}
Action::Stop => {
self.stop.store(true, Ordering::Relaxed);
@@ -424,66 +438,6 @@ impl World
}
}
- fn perform_removals(&mut self, removals: Vec<(Uid, PendingRemoval)>)
- {
- for (entity_id, removal) in removals {
- match removal {
- PendingRemoval::Components(component_ids) => {
- Self::remove_entity_components(
- entity_id,
- component_ids.into_iter().chain([ComponentRemovals::id()]),
- &mut self.data.component_storage,
- );
- }
- PendingRemoval::Entity => {
- if let Err(err) = self.data.component_storage.remove_entity(entity_id)
- {
- tracing::error!("Failed to remove entity {entity_id}: {err}");
- }
- }
- }
- }
- }
-
- #[tracing::instrument(skip(component_storage, pending_removals))]
- fn schedule_removal(
- component_storage: &mut ComponentStorage,
- pending_removals: &mut Vec<(Uid, PendingRemoval)>,
- entity_uid: Uid,
- removal: PendingRemoval,
- )
- {
- let Some(ent_handle) = Self::get_entity(component_storage, entity_uid) else {
- tracing::warn!("Cannot schedule removal. Entity does not exist");
- return;
- };
-
- let component_ids = match removal {
- PendingRemoval::Components(ref component_ids) => component_ids,
- PendingRemoval::Entity => &ent_handle.component_ids().collect::<Vec<_>>(),
- };
-
- let Some(mut component_removals) = ent_handle.get_mut::<ComponentRemovals>()
- else {
- Self::add_entity_components(
- entity_uid,
- [ComponentRemovals::from_iter(component_ids.iter().copied())
- .into_parts()],
- component_storage,
- );
-
- pending_removals.push((entity_uid, removal));
-
- return;
- };
-
- component_removals.add_ids(component_ids.iter().copied());
-
- drop(component_removals);
-
- pending_removals.push((entity_uid, removal));
- }
-
fn add_entity_components(
entity_uid: Uid,
components: impl IntoIterator<Item = ComponentParts>,
@@ -567,21 +521,6 @@ impl World
*has_swapped_active_queue = true;
}
-
- fn get_entity(
- component_storage: &mut ComponentStorage,
- entity_uid: Uid,
- ) -> Option<EntityHandle<'_>>
- {
- let archetype = component_storage.get_entity_archetype(entity_uid)?;
-
- Some(EntityHandle::new(
- archetype,
- archetype
- .get_entity_by_id(entity_uid)
- .expect("Not possible"),
- ))
- }
}
impl Default for World
@@ -603,12 +542,11 @@ pub enum StepResult
}
#[derive(Debug)]
-struct WorldData
+pub struct WorldData
{
component_storage: ComponentStorage,
sole_storage: SoleStorage,
action_queue: Rc<ActionQueue>,
- pending_removals: Vec<(Uid, PendingRemoval)>,
}
impl Default for WorldData
@@ -619,19 +557,11 @@ impl Default for WorldData
component_storage: ComponentStorage::default(),
sole_storage: SoleStorage::default(),
action_queue: Rc::new(ActionQueue::default()),
- pending_removals: Vec::new(),
}
}
}
#[derive(Debug)]
-enum PendingRemoval
-{
- Components(Vec<Uid>),
- Entity,
-}
-
-#[derive(Debug)]
pub struct EntityComponentRef<'a>
{
component_id: Uid,