1mod entity_observer;
4mod runner;
5mod trigger_event;
6
7pub use runner::*;
8pub use trigger_event::*;
9
10use crate::observer::entity_observer::ObservedBy;
11use crate::{archetype::ArchetypeFlags, system::IntoObserverSystem, world::*};
12use crate::{component::ComponentId, prelude::*, world::DeferredWorld};
13use bevy_ptr::Ptr;
14use bevy_utils::{EntityHashMap, HashMap};
15use std::marker::PhantomData;
16
17pub struct Trigger<'w, E, B: Bundle = ()> {
20 event: &'w mut E,
21 trigger: ObserverTrigger,
22 _marker: PhantomData<B>,
23}
24
25impl<'w, E, B: Bundle> Trigger<'w, E, B> {
26 pub fn new(event: &'w mut E, trigger: ObserverTrigger) -> Self {
28 Self {
29 event,
30 trigger,
31 _marker: PhantomData,
32 }
33 }
34
35 pub fn event_type(&self) -> ComponentId {
37 self.trigger.event_type
38 }
39
40 pub fn event(&self) -> &E {
42 self.event
43 }
44
45 pub fn event_mut(&mut self) -> &mut E {
47 self.event
48 }
49
50 pub fn event_ptr(&self) -> Ptr {
52 Ptr::from(&self.event)
53 }
54
55 pub fn entity(&self) -> Entity {
57 self.trigger.entity
58 }
59}
60
61#[derive(Default, Clone)]
63pub struct ObserverDescriptor {
64 events: Vec<ComponentId>,
66
67 components: Vec<ComponentId>,
69
70 entities: Vec<Entity>,
72}
73
74impl ObserverDescriptor {
75 pub unsafe fn with_events(mut self, events: Vec<ComponentId>) -> Self {
80 self.events = events;
81 self
82 }
83
84 pub fn with_components(mut self, components: Vec<ComponentId>) -> Self {
86 self.components = components;
87 self
88 }
89
90 pub fn with_entities(mut self, entities: Vec<Entity>) -> Self {
92 self.entities = entities;
93 self
94 }
95
96 pub(crate) fn merge(&mut self, descriptor: &ObserverDescriptor) {
97 self.events.extend(descriptor.events.iter().copied());
98 self.components
99 .extend(descriptor.components.iter().copied());
100 self.entities.extend(descriptor.entities.iter().copied());
101 }
102}
103
104#[derive(Debug)]
106pub struct ObserverTrigger {
107 pub observer: Entity,
109
110 pub event_type: ComponentId,
112
113 pub entity: Entity,
115}
116
117type ObserverMap = EntityHashMap<Entity, ObserverRunner>;
119
120#[derive(Default, Debug)]
122pub struct CachedComponentObservers {
123 map: ObserverMap,
125 entity_map: EntityHashMap<Entity, ObserverMap>,
127}
128
129#[derive(Default, Debug)]
131pub struct CachedObservers {
132 map: ObserverMap,
134 component_observers: HashMap<ComponentId, CachedComponentObservers>,
136 entity_observers: EntityHashMap<Entity, ObserverMap>,
138}
139
140#[derive(Default, Debug)]
142pub struct Observers {
143 on_add: CachedObservers,
145 on_insert: CachedObservers,
146 on_remove: CachedObservers,
147 cache: HashMap<ComponentId, CachedObservers>,
149}
150
151impl Observers {
152 pub(crate) fn get_observers(&mut self, event_type: ComponentId) -> &mut CachedObservers {
153 match event_type {
154 ON_ADD => &mut self.on_add,
155 ON_INSERT => &mut self.on_insert,
156 ON_REMOVE => &mut self.on_remove,
157 _ => self.cache.entry(event_type).or_default(),
158 }
159 }
160
161 pub(crate) fn try_get_observers(&self, event_type: ComponentId) -> Option<&CachedObservers> {
162 match event_type {
163 ON_ADD => Some(&self.on_add),
164 ON_INSERT => Some(&self.on_insert),
165 ON_REMOVE => Some(&self.on_remove),
166 _ => self.cache.get(&event_type),
167 }
168 }
169
170 pub(crate) fn invoke<T>(
172 mut world: DeferredWorld,
173 event_type: ComponentId,
174 entity: Entity,
175 components: impl Iterator<Item = ComponentId>,
176 data: &mut T,
177 ) {
178 let (mut world, observers) = unsafe {
180 let world = world.as_unsafe_world_cell();
181 world.increment_trigger_id();
183 let observers = world.observers();
184 let Some(observers) = observers.try_get_observers(event_type) else {
185 return;
186 };
187 (world.into_deferred(), observers)
189 };
190
191 let mut trigger_observer = |(&observer, runner): (&Entity, &ObserverRunner)| {
192 (runner)(
193 world.reborrow(),
194 ObserverTrigger {
195 observer,
196 event_type,
197 entity,
198 },
199 data.into(),
200 );
201 };
202
203 observers.map.iter().for_each(&mut trigger_observer);
205
206 if entity != Entity::PLACEHOLDER {
208 if let Some(map) = observers.entity_observers.get(&entity) {
209 map.iter().for_each(&mut trigger_observer);
210 }
211 }
212
213 components.for_each(|id| {
215 if let Some(component_observers) = observers.component_observers.get(&id) {
216 component_observers
217 .map
218 .iter()
219 .for_each(&mut trigger_observer);
220
221 if entity != Entity::PLACEHOLDER {
222 if let Some(map) = component_observers.entity_map.get(&entity) {
223 map.iter().for_each(&mut trigger_observer);
224 }
225 }
226 }
227 });
228 }
229
230 pub(crate) fn is_archetype_cached(event_type: ComponentId) -> Option<ArchetypeFlags> {
231 match event_type {
232 ON_ADD => Some(ArchetypeFlags::ON_ADD_OBSERVER),
233 ON_INSERT => Some(ArchetypeFlags::ON_INSERT_OBSERVER),
234 ON_REMOVE => Some(ArchetypeFlags::ON_REMOVE_OBSERVER),
235 _ => None,
236 }
237 }
238
239 pub(crate) fn update_archetype_flags(
240 &self,
241 component_id: ComponentId,
242 flags: &mut ArchetypeFlags,
243 ) {
244 if self.on_add.component_observers.contains_key(&component_id) {
245 flags.insert(ArchetypeFlags::ON_ADD_OBSERVER);
246 }
247 if self
248 .on_insert
249 .component_observers
250 .contains_key(&component_id)
251 {
252 flags.insert(ArchetypeFlags::ON_INSERT_OBSERVER);
253 }
254 if self
255 .on_remove
256 .component_observers
257 .contains_key(&component_id)
258 {
259 flags.insert(ArchetypeFlags::ON_REMOVE_OBSERVER);
260 }
261 }
262}
263
264impl World {
265 pub fn observe<E: Event, B: Bundle, M>(
267 &mut self,
268 system: impl IntoObserverSystem<E, B, M>,
269 ) -> EntityWorldMut {
270 self.spawn(Observer::new(system))
271 }
272
273 pub fn trigger(&mut self, event: impl Event) {
275 TriggerEvent { event, targets: () }.apply(self);
276 }
277
278 pub fn trigger_targets(&mut self, event: impl Event, targets: impl TriggerTargets) {
280 TriggerEvent { event, targets }.apply(self);
281 }
282
283 pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
285 let (observer_state, archetypes, observers) = unsafe {
287 let observer_state: *const ObserverState =
288 self.get::<ObserverState>(observer_entity).unwrap();
289 for watched_entity in &(*observer_state).descriptor.entities {
291 let mut entity_mut = self.entity_mut(*watched_entity);
292 let mut observed_by = entity_mut.entry::<ObservedBy>().or_default();
293 observed_by.0.push(observer_entity);
294 }
295 (&*observer_state, &mut self.archetypes, &mut self.observers)
296 };
297 let descriptor = &observer_state.descriptor;
298
299 for &event_type in &descriptor.events {
300 let cache = observers.get_observers(event_type);
301
302 if descriptor.components.is_empty() && descriptor.entities.is_empty() {
303 cache.map.insert(observer_entity, observer_state.runner);
304 } else if descriptor.components.is_empty() {
305 for &watched_entity in &observer_state.descriptor.entities {
307 let map = cache.entity_observers.entry(watched_entity).or_default();
308 map.insert(observer_entity, observer_state.runner);
309 }
310 } else {
311 for &component in &descriptor.components {
313 let observers =
314 cache
315 .component_observers
316 .entry(component)
317 .or_insert_with(|| {
318 if let Some(flag) = Observers::is_archetype_cached(event_type) {
319 archetypes.update_flags(component, flag, true);
320 }
321 CachedComponentObservers::default()
322 });
323 if descriptor.entities.is_empty() {
324 observers.map.insert(observer_entity, observer_state.runner);
326 } else {
327 for &watched_entity in &descriptor.entities {
329 let map = observers.entity_map.entry(watched_entity).or_default();
330 map.insert(observer_entity, observer_state.runner);
331 }
332 }
333 }
334 }
335 }
336 }
337
338 pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
340 let archetypes = &mut self.archetypes;
341 let observers = &mut self.observers;
342
343 for &event_type in &descriptor.events {
344 let cache = observers.get_observers(event_type);
345 if descriptor.components.is_empty() && descriptor.entities.is_empty() {
346 cache.map.remove(&entity);
347 } else if descriptor.components.is_empty() {
348 for watched_entity in &descriptor.entities {
349 let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
351 continue;
352 };
353 observers.remove(&entity);
354 if observers.is_empty() {
355 cache.entity_observers.remove(watched_entity);
356 }
357 }
358 } else {
359 for component in &descriptor.components {
360 let Some(observers) = cache.component_observers.get_mut(component) else {
361 continue;
362 };
363 if descriptor.entities.is_empty() {
364 observers.map.remove(&entity);
365 } else {
366 for watched_entity in &descriptor.entities {
367 let Some(map) = observers.entity_map.get_mut(watched_entity) else {
368 continue;
369 };
370 map.remove(&entity);
371 if map.is_empty() {
372 observers.entity_map.remove(watched_entity);
373 }
374 }
375 }
376
377 if observers.map.is_empty() && observers.entity_map.is_empty() {
378 cache.component_observers.remove(component);
379 if let Some(flag) = Observers::is_archetype_cached(event_type) {
380 archetypes.update_flags(*component, flag, false);
381 }
382 }
383 }
384 }
385 }
386 }
387}
388
389#[cfg(test)]
390mod tests {
391 use bevy_ptr::OwningPtr;
392
393 use crate as bevy_ecs;
394 use crate::observer::{EmitDynamicTrigger, Observer, ObserverDescriptor, ObserverState};
395 use crate::prelude::*;
396
397 #[derive(Component)]
398 struct A;
399
400 #[derive(Component)]
401 struct B;
402
403 #[derive(Component)]
404 struct C;
405
406 #[derive(Component)]
407 #[component(storage = "SparseSet")]
408 struct S;
409
410 #[derive(Event)]
411 struct EventA;
412
413 #[derive(Resource, Default)]
414 struct R(usize);
415
416 impl R {
417 #[track_caller]
418 fn assert_order(&mut self, count: usize) {
419 assert_eq!(count, self.0);
420 self.0 += 1;
421 }
422 }
423
424 #[test]
425 fn observer_order_spawn_despawn() {
426 let mut world = World::new();
427 world.init_resource::<R>();
428
429 world.observe(|_: Trigger<OnAdd, A>, mut res: ResMut<R>| res.assert_order(0));
430 world.observe(|_: Trigger<OnInsert, A>, mut res: ResMut<R>| res.assert_order(1));
431 world.observe(|_: Trigger<OnRemove, A>, mut res: ResMut<R>| res.assert_order(2));
432
433 let entity = world.spawn(A).id();
434 world.despawn(entity);
435 assert_eq!(3, world.resource::<R>().0);
436 }
437
438 #[test]
439 fn observer_order_insert_remove() {
440 let mut world = World::new();
441 world.init_resource::<R>();
442
443 world.observe(|_: Trigger<OnAdd, A>, mut res: ResMut<R>| res.assert_order(0));
444 world.observe(|_: Trigger<OnInsert, A>, mut res: ResMut<R>| res.assert_order(1));
445 world.observe(|_: Trigger<OnRemove, A>, mut res: ResMut<R>| res.assert_order(2));
446
447 let mut entity = world.spawn_empty();
448 entity.insert(A);
449 entity.remove::<A>();
450 entity.flush();
451 assert_eq!(3, world.resource::<R>().0);
452 }
453
454 #[test]
455 fn observer_order_insert_remove_sparse() {
456 let mut world = World::new();
457 world.init_resource::<R>();
458
459 world.observe(|_: Trigger<OnAdd, S>, mut res: ResMut<R>| res.assert_order(0));
460 world.observe(|_: Trigger<OnInsert, S>, mut res: ResMut<R>| res.assert_order(1));
461 world.observe(|_: Trigger<OnRemove, S>, mut res: ResMut<R>| res.assert_order(2));
462
463 let mut entity = world.spawn_empty();
464 entity.insert(S);
465 entity.remove::<S>();
466 entity.flush();
467 assert_eq!(3, world.resource::<R>().0);
468 }
469
470 #[test]
471 fn observer_order_recursive() {
472 let mut world = World::new();
473 world.init_resource::<R>();
474 world.observe(
475 |obs: Trigger<OnAdd, A>, mut res: ResMut<R>, mut commands: Commands| {
476 res.assert_order(0);
477 commands.entity(obs.entity()).insert(B);
478 },
479 );
480 world.observe(
481 |obs: Trigger<OnRemove, A>, mut res: ResMut<R>, mut commands: Commands| {
482 res.assert_order(2);
483 commands.entity(obs.entity()).remove::<B>();
484 },
485 );
486
487 world.observe(
488 |obs: Trigger<OnAdd, B>, mut res: ResMut<R>, mut commands: Commands| {
489 res.assert_order(1);
490 commands.entity(obs.entity()).remove::<A>();
491 },
492 );
493 world.observe(|_: Trigger<OnRemove, B>, mut res: ResMut<R>| {
494 res.assert_order(3);
495 });
496
497 let entity = world.spawn(A).flush();
498 let entity = world.get_entity(entity).unwrap();
499 assert!(!entity.contains::<A>());
500 assert!(!entity.contains::<B>());
501 assert_eq!(4, world.resource::<R>().0);
502 }
503
504 #[test]
505 fn observer_multiple_listeners() {
506 let mut world = World::new();
507 world.init_resource::<R>();
508
509 world.observe(|_: Trigger<OnAdd, A>, mut res: ResMut<R>| res.0 += 1);
510 world.observe(|_: Trigger<OnAdd, A>, mut res: ResMut<R>| res.0 += 1);
511
512 world.spawn(A).flush();
513 assert_eq!(2, world.resource::<R>().0);
514 assert_eq!(world.entities().len(), 3);
516 }
517
518 #[test]
519 fn observer_multiple_events() {
520 let mut world = World::new();
521 world.init_resource::<R>();
522 let on_remove = world.init_component::<OnRemove>();
523 world.spawn(
524 unsafe {
526 Observer::new(|_: Trigger<OnAdd, A>, mut res: ResMut<R>| res.0 += 1)
527 .with_event(on_remove)
528 },
529 );
530
531 let entity = world.spawn(A).id();
532 world.despawn(entity);
533 assert_eq!(2, world.resource::<R>().0);
534 }
535
536 #[test]
537 fn observer_multiple_components() {
538 let mut world = World::new();
539 world.init_resource::<R>();
540 world.init_component::<A>();
541 world.init_component::<B>();
542
543 world.observe(|_: Trigger<OnAdd, (A, B)>, mut res: ResMut<R>| res.0 += 1);
544
545 let entity = world.spawn(A).id();
546 world.entity_mut(entity).insert(B);
547 world.flush();
548 assert_eq!(2, world.resource::<R>().0);
549 }
550
551 #[test]
552 fn observer_despawn() {
553 let mut world = World::new();
554 world.init_resource::<R>();
555
556 let observer = world
557 .observe(|_: Trigger<OnAdd, A>| panic!("Observer triggered after being despawned."))
558 .id();
559 world.despawn(observer);
560 world.spawn(A).flush();
561 }
562
563 #[test]
564 fn observer_multiple_matches() {
565 let mut world = World::new();
566 world.init_resource::<R>();
567
568 world.observe(|_: Trigger<OnAdd, (A, B)>, mut res: ResMut<R>| res.0 += 1);
569
570 world.spawn((A, B)).flush();
571 assert_eq!(1, world.resource::<R>().0);
572 }
573
574 #[test]
575 fn observer_no_target() {
576 let mut world = World::new();
577 world.init_resource::<R>();
578
579 world
580 .spawn_empty()
581 .observe(|_: Trigger<EventA>| panic!("Trigger routed to non-targeted entity."));
582 world.observe(move |obs: Trigger<EventA>, mut res: ResMut<R>| {
583 assert_eq!(obs.entity(), Entity::PLACEHOLDER);
584 res.0 += 1;
585 });
586
587 world.flush();
590 world.trigger(EventA);
591 world.flush();
592 assert_eq!(1, world.resource::<R>().0);
593 }
594
595 #[test]
596 fn observer_entity_routing() {
597 let mut world = World::new();
598 world.init_resource::<R>();
599
600 world
601 .spawn_empty()
602 .observe(|_: Trigger<EventA>| panic!("Trigger routed to non-targeted entity."));
603 let entity = world
604 .spawn_empty()
605 .observe(|_: Trigger<EventA>, mut res: ResMut<R>| res.0 += 1)
606 .id();
607 world.observe(move |obs: Trigger<EventA>, mut res: ResMut<R>| {
608 assert_eq!(obs.entity(), entity);
609 res.0 += 1;
610 });
611
612 world.flush();
615 world.trigger_targets(EventA, entity);
616 world.flush();
617 assert_eq!(2, world.resource::<R>().0);
618 }
619
620 #[test]
621 fn observer_dynamic_component() {
622 let mut world = World::new();
623 world.init_resource::<R>();
624
625 let component_id = world.init_component::<A>();
626 world.spawn(
627 Observer::new(|_: Trigger<OnAdd>, mut res: ResMut<R>| res.0 += 1)
628 .with_component(component_id),
629 );
630
631 let mut entity = world.spawn_empty();
632 OwningPtr::make(A, |ptr| {
633 unsafe { entity.insert_by_id(component_id, ptr) };
635 });
636 let entity = entity.flush();
637
638 world.trigger_targets(EventA, entity);
639 world.flush();
640 assert_eq!(1, world.resource::<R>().0);
641 }
642
643 #[test]
644 fn observer_dynamic_trigger() {
645 let mut world = World::new();
646 world.init_resource::<R>();
647 let event_a = world.init_component::<EventA>();
648
649 world.spawn(ObserverState {
650 descriptor: unsafe { ObserverDescriptor::default().with_events(vec![event_a]) },
652 runner: |mut world, _trigger, _ptr| {
653 world.resource_mut::<R>().0 += 1;
654 },
655 ..Default::default()
656 });
657
658 world.commands().add(
659 unsafe { EmitDynamicTrigger::new_with_id(event_a, EventA, ()) },
661 );
662 world.flush();
663 assert_eq!(1, world.resource::<R>().0);
664 }
665}