summaryrefslogtreecommitdiff
path: root/ecs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-09-13 19:24:29 +0200
committerHampusM <hampus@hampusmat.com>2025-09-13 19:24:29 +0200
commit6e7abf273d758bf15c1ba3e331e370b2bea3f8e2 (patch)
treed13ad55858583e0546632aeeb0b7336677378621 /ecs
parent1bf48462393099d971b7a8613bd945d863d97273 (diff)
feat(ecs): re-implement component added & removed eventsHEADmaster
Diffstat (limited to 'ecs')
-rw-r--r--ecs/examples/component_removed_event.rs39
-rw-r--r--ecs/src/entity.rs6
-rw-r--r--ecs/src/event.rs5
-rw-r--r--ecs/src/event/component.rs22
-rw-r--r--ecs/src/lib.rs54
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<'_>)