diff options
Diffstat (limited to 'ecs/src')
-rw-r--r-- | ecs/src/actions.rs | 4 | ||||
-rw-r--r-- | ecs/src/component.rs | 37 | ||||
-rw-r--r-- | ecs/src/component/storage/archetype.rs | 1 | ||||
-rw-r--r-- | ecs/src/entity.rs | 5 | ||||
-rw-r--r-- | ecs/src/event/component.rs | 6 | ||||
-rw-r--r-- | ecs/src/lib.rs | 140 |
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, |