diff options
author | HampusM <hampus@hampusmat.com> | 2025-09-13 19:24:29 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-09-13 19:24:29 +0200 |
commit | 6e7abf273d758bf15c1ba3e331e370b2bea3f8e2 (patch) | |
tree | d13ad55858583e0546632aeeb0b7336677378621 /ecs | |
parent | 1bf48462393099d971b7a8613bd945d863d97273 (diff) |
Diffstat (limited to 'ecs')
-rw-r--r-- | ecs/examples/component_removed_event.rs | 39 | ||||
-rw-r--r-- | ecs/src/entity.rs | 6 | ||||
-rw-r--r-- | ecs/src/event.rs | 5 | ||||
-rw-r--r-- | ecs/src/event/component.rs | 22 | ||||
-rw-r--r-- | ecs/src/lib.rs | 54 |
5 files changed, 96 insertions, 30 deletions
diff --git a/ecs/examples/component_removed_event.rs b/ecs/examples/component_removed_event.rs new file mode 100644 index 0000000..ffa37f4 --- /dev/null +++ b/ecs/examples/component_removed_event.rs @@ -0,0 +1,39 @@ +use ecs::actions::Actions; +use ecs::component::Component; +use ecs::event::component::Removed; +use ecs::pair::Pair; +use ecs::phase::UPDATE; +use ecs::system::observer::Observe; +use ecs::{Component, Query, World}; + +#[derive(Debug, Component)] +struct Cheese; + +fn eat_cheese(query: Query<(&Cheese,)>, mut actions: Actions) +{ + for (cheese_ent_id, (_,)) in query.iter_with_euids() { + println!("Eating cheese!"); + + actions.remove_components(cheese_ent_id, [Cheese::id()]); + } +} + +fn on_cheese_removed(observe: Observe<Pair<Removed, Cheese>>) +{ + for cheese_ent in &observe { + println!("Cheese entity {} was eaten", cheese_ent.uid()); + } +} + +fn main() +{ + let mut world = World::new(); + + world.register_system(*UPDATE, eat_cheese); + world.register_observer(on_cheese_removed); + + world.create_entity((Cheese,)); + + world.step(); + world.step(); +} diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs index bec50cd..6ee5ad8 100644 --- a/ecs/src/entity.rs +++ b/ecs/src/entity.rs @@ -173,6 +173,12 @@ impl<'a> Handle<'a> .contains_component_with_exact_id(component_uid) } + /// Returns the `Uids`s of the components this entity has. + pub fn component_ids(&self) -> impl Iterator<Item = Uid> + '_ + { + self.archetype.component_ids_sorted() + } + pub(crate) fn new( archetype: &'a Archetype, entity: &'a ArchetypeEntity, diff --git a/ecs/src/event.rs b/ecs/src/event.rs index 2934b82..a0b2487 100644 --- a/ecs/src/event.rs +++ b/ecs/src/event.rs @@ -2,7 +2,6 @@ use crate::lock::Lock; use crate::pair::Pair; use crate::uid::{Kind as UidKind, Uid}; use crate::util::VecExt; -use crate::World; pub mod component; @@ -36,9 +35,9 @@ impl<'world> Submitter<'world> new_events_lock.push_event_match(event, match_id); } - pub(crate) fn new(world: &'world World) -> Self + pub(crate) fn new(new_events: &'world Lock<NewEvents>) -> Self { - Self { new_events: &world.data.new_events } + Self { new_events } } } diff --git a/ecs/src/event/component.rs b/ecs/src/event/component.rs index 421c369..e8b9559 100644 --- a/ecs/src/event/component.rs +++ b/ecs/src/event/component.rs @@ -4,19 +4,17 @@ use std::convert::Infallible; use crate::Component; -// TODO: Implement -// /// Pair relation for events emitted when: -// /// a) A entity with the target component is spawned. -// /// b) The target component is added to a entity. -// #[derive(Debug, Component)] -// pub struct Added(Infallible); +/// Pair relation for events emitted when: +/// a) A entity with the target component is spawned. +/// b) The target component is added to a entity. +#[derive(Debug, Component)] +pub struct Added(Infallible); -// TODO: Implement -// /// 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); +/// 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); #[derive(Debug, Component)] pub struct Changed(Infallible); diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index e9494a7..0c2197c 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -19,6 +19,7 @@ use crate::component::{ Sequence as ComponentSequence, }; use crate::entity::{Declaration as EntityDeclaration, Handle as EntityHandle}; +use crate::event::component::{Added, Removed}; use crate::event::{Emitted as EmittedEvent, NewEvents, Submitter as EventSubmitter}; use crate::extension::{Collector as ExtensionCollector, Extension}; use crate::lock::Lock; @@ -115,6 +116,7 @@ impl World entity_id, [component_parts], &mut self.data.component_storage, + &EventSubmitter::new(&self.data.new_events), ); } @@ -219,7 +221,7 @@ impl World pub fn event_submitter(&self) -> EventSubmitter<'_> { - EventSubmitter::new(self) + EventSubmitter::new(&self.data.new_events) } /// Performs a single tick. @@ -331,6 +333,7 @@ impl World entity_uid, components, &mut self.data.component_storage, + &EventSubmitter::new(&self.data.new_events), ); } @@ -436,13 +439,32 @@ impl World new_entity_uid, components, &mut self.data.component_storage, + &EventSubmitter::new(&self.data.new_events), ); } Action::Despawn(entity_uid) => { + let component_ids = self + .get_entity(entity_uid) + .expect("Not possible") + .component_ids() + .collect::<Vec<_>>(); + if let Err(err) = self.data.component_storage.remove_entity(entity_uid) { tracing::error!("Failed to despawn entity: {err}"); + continue; + } + + let event_submitter = EventSubmitter::new(&self.data.new_events); + + for comp_id in component_ids { + if comp_id.kind() == UidKind::Pair { + continue; + } + + event_submitter + .submit_event(&Pair::new::<Removed>(comp_id), entity_uid); } } Action::AddComponents(entity_uid, components) => { @@ -450,6 +472,7 @@ impl World entity_uid, components, &mut self.data.component_storage, + &EventSubmitter::new(&self.data.new_events), ); } Action::RemoveComponents(entity_uid, component_ids) => { @@ -457,6 +480,7 @@ impl World entity_uid, component_ids, &mut self.data.component_storage, + &EventSubmitter::new(&self.data.new_events), ); } Action::Stop => { @@ -470,13 +494,11 @@ impl World entity_uid: Uid, components: impl IntoIterator<Item = ComponentParts>, component_storage: &mut ComponentStorage, - ) -> Vec<Uid> + event_submitter: &EventSubmitter<'_>, + ) { let component_iter = components.into_iter(); - let mut added_component_ids = - Vec::<Uid>::with_capacity(component_iter.size_hint().0); - for component_parts in component_iter { let comp_id = component_parts.id(); @@ -488,23 +510,23 @@ impl World continue; } - added_component_ids.push(comp_id); - } + if comp_id.kind() == UidKind::Pair { + continue; + } - added_component_ids + event_submitter.submit_event(&Pair::new::<Added>(comp_id), entity_uid); + } } fn remove_entity_components( entity_uid: Uid, component_ids: impl IntoIterator<Item = Uid>, component_storage: &mut ComponentStorage, - ) -> Vec<Uid> + event_submitter: &EventSubmitter<'_>, + ) { let component_id_iter = component_ids.into_iter(); - let mut removed_component_ids = - Vec::<Uid>::with_capacity(component_id_iter.size_hint().0); - for component_id in component_id_iter { if let Err(err) = component_storage.remove_entity_component(entity_uid, component_id) @@ -513,10 +535,12 @@ impl World continue; } - removed_component_ids.push(component_id); - } + if component_id.kind() == UidKind::Pair { + continue; + } - removed_component_ids + event_submitter.submit_event(&Pair::new::<Removed>(component_id), entity_uid); + } } fn emit_event_observers(&self, event_id: Uid, emitted_event: &EmittedEvent<'_>) |