diff options
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<'_>)  | 
