bevy_ecs/observer/
mod.rs

1//! Observers are a push-based tool for responding to [`Event`]s. The [`Observer`] component holds a [`System`] that runs whenever a matching [`Event`]
2//! is triggered.
3//!
4//! See [`Event`] and [`Observer`] for in-depth documentation and usage examples.
5
6mod centralized_storage;
7mod distributed_storage;
8mod entity_cloning;
9mod runner;
10mod system_param;
11
12pub use centralized_storage::*;
13pub use distributed_storage::*;
14pub use runner::*;
15pub use system_param::*;
16
17use crate::{
18    change_detection::MaybeLocation,
19    event::Event,
20    prelude::*,
21    system::IntoObserverSystem,
22    world::{DeferredWorld, *},
23};
24
25impl World {
26    /// Spawns a "global" [`Observer`] which will watch for the given event.
27    /// Returns its [`Entity`] as a [`EntityWorldMut`].
28    ///
29    /// `system` can be any system whose first parameter is [`On`].
30    ///
31    /// # Example
32    ///
33    /// ```
34    /// # use bevy_ecs::prelude::*;
35    /// #[derive(Component)]
36    /// struct A;
37    ///
38    /// # let mut world = World::new();
39    /// world.add_observer(|_: On<Add, A>| {
40    ///     // ...
41    /// });
42    /// world.add_observer(|_: On<Remove, A>| {
43    ///     // ...
44    /// });
45    /// ```
46    ///
47    /// **Calling [`observe`](EntityWorldMut::observe) on the returned
48    /// [`EntityWorldMut`] will observe the observer itself, which you very
49    /// likely do not want.**
50    ///
51    /// # Panics
52    ///
53    /// Panics if the given system is an exclusive system.
54    pub fn add_observer<E: Event, B: Bundle, M>(
55        &mut self,
56        system: impl IntoObserverSystem<E, B, M>,
57    ) -> EntityWorldMut<'_> {
58        self.spawn(Observer::new(system))
59    }
60
61    /// Triggers the given [`Event`], which will run any [`Observer`]s watching for it.
62    ///
63    /// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
64    #[track_caller]
65    pub fn trigger<'a, E: Event<Trigger<'a>: Default>>(&mut self, mut event: E) {
66        self.trigger_ref_with_caller(
67            &mut event,
68            &mut <E::Trigger<'a> as Default>::default(),
69            MaybeLocation::caller(),
70        );
71    }
72
73    /// Triggers the given [`Event`] using the given [`Trigger`](crate::event::Trigger), which will run any [`Observer`]s watching for it.
74    ///
75    /// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
76    #[track_caller]
77    pub fn trigger_with<'a, E: Event>(&mut self, mut event: E, mut trigger: E::Trigger<'a>) {
78        self.trigger_ref_with_caller(&mut event, &mut trigger, MaybeLocation::caller());
79    }
80
81    /// Triggers the given mutable [`Event`] reference, which will run any [`Observer`]s watching for it.
82    ///
83    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
84    /// or use the event after it has been modified by observers.
85    #[track_caller]
86    pub fn trigger_ref<'a, E: Event<Trigger<'a>: Default>>(&mut self, event: &mut E) {
87        self.trigger_ref_with_caller(
88            event,
89            &mut <E::Trigger<'a> as Default>::default(),
90            MaybeLocation::caller(),
91        );
92    }
93
94    /// Triggers the given mutable [`Event`] reference using the given mutable [`Trigger`](crate::event::Trigger) reference, which
95    /// will run any [`Observer`]s watching for it.
96    ///
97    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
98    /// or use the event after it has been modified by observers.
99    pub fn trigger_ref_with<'a, E: Event>(&mut self, event: &mut E, trigger: &mut E::Trigger<'a>) {
100        self.trigger_ref_with_caller(event, trigger, MaybeLocation::caller());
101    }
102
103    pub(crate) fn trigger_ref_with_caller<'a, E: Event>(
104        &mut self,
105        event: &mut E,
106        trigger: &mut E::Trigger<'a>,
107        caller: MaybeLocation,
108    ) {
109        let event_key = self.register_event_key::<E>();
110        // SAFETY: event_key was just registered and matches `event`
111        unsafe {
112            DeferredWorld::from(self).trigger_raw(event_key, event, trigger, caller);
113        }
114    }
115
116    /// Register an observer to the cache, called when an observer is created
117    pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
118        // SAFETY: References do not alias.
119        let (observer_state, archetypes, observers) = unsafe {
120            let observer_state: *const Observer = self.get::<Observer>(observer_entity).unwrap();
121            // Populate ObservedBy for each observed entity.
122            for watched_entity in (*observer_state).descriptor.entities.iter().copied() {
123                let mut entity_mut = self.entity_mut(watched_entity);
124                let mut observed_by = entity_mut.entry::<ObservedBy>().or_default().into_mut();
125                observed_by.0.push(observer_entity);
126            }
127            (&*observer_state, &mut self.archetypes, &mut self.observers)
128        };
129        let descriptor = &observer_state.descriptor;
130
131        for &event_key in &descriptor.event_keys {
132            let cache = observers.get_observers_mut(event_key);
133
134            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
135                cache
136                    .global_observers
137                    .insert(observer_entity, observer_state.runner);
138            } else if descriptor.components.is_empty() {
139                // Observer is not targeting any components so register it as an entity observer
140                for &watched_entity in &observer_state.descriptor.entities {
141                    let map = cache.entity_observers.entry(watched_entity).or_default();
142                    map.insert(observer_entity, observer_state.runner);
143                }
144            } else {
145                // Register observer for each watched component
146                for &component in &descriptor.components {
147                    let observers =
148                        cache
149                            .component_observers
150                            .entry(component)
151                            .or_insert_with(|| {
152                                if let Some(flag) = Observers::is_archetype_cached(event_key) {
153                                    archetypes.update_flags(component, flag, true);
154                                }
155                                CachedComponentObservers::default()
156                            });
157                    if descriptor.entities.is_empty() {
158                        // Register for all triggers targeting the component
159                        observers
160                            .global_observers
161                            .insert(observer_entity, observer_state.runner);
162                    } else {
163                        // Register for each watched entity
164                        for &watched_entity in &descriptor.entities {
165                            let map = observers
166                                .entity_component_observers
167                                .entry(watched_entity)
168                                .or_default();
169                            map.insert(observer_entity, observer_state.runner);
170                        }
171                    }
172                }
173            }
174        }
175    }
176
177    /// Remove the observer from the cache, called when an observer gets despawned
178    pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
179        let archetypes = &mut self.archetypes;
180        let observers = &mut self.observers;
181
182        for &event_key in &descriptor.event_keys {
183            let cache = observers.get_observers_mut(event_key);
184            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
185                cache.global_observers.remove(&entity);
186            } else if descriptor.components.is_empty() {
187                for watched_entity in &descriptor.entities {
188                    // This check should be unnecessary since this observer hasn't been unregistered yet
189                    let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
190                        continue;
191                    };
192                    observers.remove(&entity);
193                    if observers.is_empty() {
194                        cache.entity_observers.remove(watched_entity);
195                    }
196                }
197            } else {
198                for component in &descriptor.components {
199                    let Some(observers) = cache.component_observers.get_mut(component) else {
200                        continue;
201                    };
202                    if descriptor.entities.is_empty() {
203                        observers.global_observers.remove(&entity);
204                    } else {
205                        for watched_entity in &descriptor.entities {
206                            let Some(map) =
207                                observers.entity_component_observers.get_mut(watched_entity)
208                            else {
209                                continue;
210                            };
211                            map.remove(&entity);
212                            if map.is_empty() {
213                                observers.entity_component_observers.remove(watched_entity);
214                            }
215                        }
216                    }
217
218                    if observers.global_observers.is_empty()
219                        && observers.entity_component_observers.is_empty()
220                    {
221                        cache.component_observers.remove(component);
222                        if let Some(flag) = Observers::is_archetype_cached(event_key)
223                            && let Some(by_component) = archetypes.by_component.get(component)
224                        {
225                            for archetype in by_component.keys() {
226                                let archetype = &mut archetypes.archetypes[archetype.index()];
227                                if archetype.contains(*component) {
228                                    let no_longer_observed = archetype
229                                        .iter_components()
230                                        .all(|id| !cache.component_observers.contains_key(&id));
231
232                                    if no_longer_observed {
233                                        archetype.flags.set(flag, false);
234                                    }
235                                }
236                            }
237                        }
238                    }
239                }
240            }
241        }
242    }
243}
244
245#[cfg(test)]
246mod tests {
247    use alloc::{vec, vec::Vec};
248
249    use bevy_ptr::OwningPtr;
250
251    use crate::{
252        change_detection::MaybeLocation,
253        event::{EntityComponentsTrigger, Event, GlobalTrigger},
254        hierarchy::ChildOf,
255        observer::{Observer, Replace},
256        prelude::*,
257        world::DeferredWorld,
258    };
259
260    #[derive(Component)]
261    struct A;
262
263    #[derive(Component)]
264    struct B;
265
266    #[derive(Component)]
267    #[component(storage = "SparseSet")]
268    struct S;
269
270    #[derive(Event)]
271    struct EventA;
272
273    #[derive(EntityEvent)]
274    struct EntityEventA(Entity);
275
276    #[derive(EntityEvent)]
277    #[entity_event(trigger = EntityComponentsTrigger<'a>)]
278    struct EntityComponentsEvent(Entity);
279
280    #[derive(Event)]
281    struct EventWithData {
282        counter: usize,
283    }
284
285    #[derive(Resource, Default)]
286    struct Order(Vec<&'static str>);
287
288    impl Order {
289        #[track_caller]
290        fn observed(&mut self, name: &'static str) {
291            self.0.push(name);
292        }
293    }
294
295    #[derive(Component, EntityEvent)]
296    #[entity_event(propagate, auto_propagate)]
297    struct EventPropagating(Entity);
298
299    #[test]
300    fn observer_order_spawn_despawn() {
301        let mut world = World::new();
302        world.init_resource::<Order>();
303
304        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
305        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
306        world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
307            res.observed("replace");
308        });
309        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
310
311        let entity = world.spawn(A).id();
312        world.despawn(entity);
313        assert_eq!(
314            vec!["add", "insert", "replace", "remove"],
315            world.resource::<Order>().0
316        );
317    }
318
319    #[test]
320    fn observer_order_insert_remove() {
321        let mut world = World::new();
322        world.init_resource::<Order>();
323
324        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
325        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
326        world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
327            res.observed("replace");
328        });
329        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
330
331        let mut entity = world.spawn_empty();
332        entity.insert(A);
333        entity.remove::<A>();
334        entity.flush();
335        assert_eq!(
336            vec!["add", "insert", "replace", "remove"],
337            world.resource::<Order>().0
338        );
339    }
340
341    #[test]
342    fn observer_order_insert_remove_sparse() {
343        let mut world = World::new();
344        world.init_resource::<Order>();
345
346        world.add_observer(|_: On<Add, S>, mut res: ResMut<Order>| res.observed("add"));
347        world.add_observer(|_: On<Insert, S>, mut res: ResMut<Order>| res.observed("insert"));
348        world.add_observer(|_: On<Replace, S>, mut res: ResMut<Order>| {
349            res.observed("replace");
350        });
351        world.add_observer(|_: On<Remove, S>, mut res: ResMut<Order>| res.observed("remove"));
352
353        let mut entity = world.spawn_empty();
354        entity.insert(S);
355        entity.remove::<S>();
356        entity.flush();
357        assert_eq!(
358            vec!["add", "insert", "replace", "remove"],
359            world.resource::<Order>().0
360        );
361    }
362
363    #[test]
364    fn observer_order_replace() {
365        let mut world = World::new();
366        world.init_resource::<Order>();
367
368        let entity = world.spawn(A).id();
369
370        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
371        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
372        world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
373            res.observed("replace");
374        });
375        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
376
377        let mut entity = world.entity_mut(entity);
378        entity.insert(A);
379        entity.flush();
380        assert_eq!(vec!["replace", "insert"], world.resource::<Order>().0);
381    }
382
383    #[test]
384    fn observer_order_recursive() {
385        let mut world = World::new();
386        world.init_resource::<Order>();
387        world.add_observer(
388            |add: On<Add, A>, mut res: ResMut<Order>, mut commands: Commands| {
389                res.observed("add_a");
390                commands.entity(add.entity).insert(B);
391            },
392        );
393        world.add_observer(
394            |remove: On<Remove, A>, mut res: ResMut<Order>, mut commands: Commands| {
395                res.observed("remove_a");
396                commands.entity(remove.entity).remove::<B>();
397            },
398        );
399
400        world.add_observer(
401            |add: On<Add, B>, mut res: ResMut<Order>, mut commands: Commands| {
402                res.observed("add_b");
403                commands.entity(add.entity).remove::<A>();
404            },
405        );
406        world.add_observer(|_: On<Remove, B>, mut res: ResMut<Order>| {
407            res.observed("remove_b");
408        });
409
410        let entity = world.spawn(A).flush();
411        let entity = world.get_entity(entity).unwrap();
412        assert!(!entity.contains::<A>());
413        assert!(!entity.contains::<B>());
414        assert_eq!(
415            vec!["add_a", "add_b", "remove_a", "remove_b"],
416            world.resource::<Order>().0
417        );
418    }
419
420    #[test]
421    fn observer_trigger_ref() {
422        let mut world = World::new();
423
424        world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
425        world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
426        world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
427
428        let mut event = EventWithData { counter: 0 };
429        world.trigger_ref(&mut event);
430        assert_eq!(7, event.counter);
431    }
432
433    #[test]
434    fn observer_multiple_listeners() {
435        let mut world = World::new();
436        world.init_resource::<Order>();
437
438        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
439        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));
440
441        world.spawn(A).flush();
442        assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
443        // we have one A entity and two observers
444        assert_eq!(world.query::<&A>().query(&world).count(), 1);
445        assert_eq!(world.query::<&Observer>().query(&world).count(), 2);
446    }
447
448    #[test]
449    fn observer_multiple_events() {
450        let mut world = World::new();
451        world.init_resource::<Order>();
452        let on_remove = world.register_event_key::<Remove>();
453        world.spawn(
454            // SAFETY: Add and Remove are both unit types, so this is safe
455            unsafe {
456                Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
457                    res.observed("add/remove");
458                })
459                .with_event_key(on_remove)
460            },
461        );
462
463        let entity = world.spawn(A).id();
464        world.despawn(entity);
465        assert_eq!(
466            vec!["add/remove", "add/remove"],
467            world.resource::<Order>().0
468        );
469    }
470
471    #[test]
472    fn observer_multiple_components() {
473        let mut world = World::new();
474        world.init_resource::<Order>();
475        world.register_component::<A>();
476        world.register_component::<B>();
477
478        world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
479            res.observed("add_ab");
480        });
481
482        let entity = world.spawn(A).id();
483        world.entity_mut(entity).insert(B);
484        assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
485    }
486
487    #[test]
488    fn observer_despawn() {
489        let mut world = World::new();
490
491        let system: fn(On<Add, A>) = |_| {
492            panic!("Observer triggered after being despawned.");
493        };
494        let observer = world.add_observer(system).id();
495        world.despawn(observer);
496        world.spawn(A).flush();
497    }
498
499    // Regression test for https://github.com/bevyengine/bevy/issues/14961
500    #[test]
501    fn observer_despawn_archetype_flags() {
502        let mut world = World::new();
503        world.init_resource::<Order>();
504
505        let entity = world.spawn((A, B)).flush();
506
507        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| {
508            res.observed("remove_a");
509        });
510
511        let system: fn(On<Remove, B>) = |_: On<Remove, B>| {
512            panic!("Observer triggered after being despawned.");
513        };
514
515        let observer = world.add_observer(system).flush();
516        world.despawn(observer);
517
518        world.despawn(entity);
519
520        assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
521    }
522
523    #[test]
524    fn observer_multiple_matches() {
525        let mut world = World::new();
526        world.init_resource::<Order>();
527
528        world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
529            res.observed("add_ab");
530        });
531
532        world.spawn((A, B)).flush();
533        assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
534    }
535
536    #[test]
537    fn observer_entity_routing() {
538        let mut world = World::new();
539        world.init_resource::<Order>();
540
541        let system: fn(On<EntityEventA>) = |_| {
542            panic!("Trigger routed to non-targeted entity.");
543        };
544
545        world.spawn_empty().observe(system);
546        let entity = world
547            .spawn_empty()
548            .observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
549            .id();
550        world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
551            assert_eq!(event.event_target(), entity);
552            res.observed("a_2");
553        });
554
555        world.trigger(EntityEventA(entity));
556        assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
557    }
558
559    #[test]
560    fn observer_multiple_targets() {
561        #[derive(Resource, Default)]
562        struct R(i32);
563
564        let mut world = World::new();
565        let component_a = world.register_component::<A>();
566        let component_b = world.register_component::<B>();
567        world.init_resource::<R>();
568
569        // targets (entity_1, A)
570        let entity_1 = world
571            .spawn_empty()
572            .observe(|_: On<EntityComponentsEvent, A>, mut res: ResMut<R>| res.0 += 1)
573            .id();
574        // targets (entity_2, B)
575        let entity_2 = world
576            .spawn_empty()
577            .observe(|_: On<EntityComponentsEvent, B>, mut res: ResMut<R>| res.0 += 10)
578            .id();
579        // targets any entity or component
580        world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
581        // targets any entity, and components A or B
582        world
583            .add_observer(|_: On<EntityComponentsEvent, (A, B)>, mut res: ResMut<R>| res.0 += 1000);
584        // test all tuples
585        world.add_observer(
586            |_: On<EntityComponentsEvent, (A, B, (A, B))>, mut res: ResMut<R>| res.0 += 10000,
587        );
588        world.add_observer(
589            |_: On<EntityComponentsEvent, (A, B, (A, B), ((A, B), (A, B)))>, mut res: ResMut<R>| {
590                res.0 += 100000;
591            },
592        );
593        world.add_observer(
594            |_: On<EntityComponentsEvent, (A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>,
595             mut res: ResMut<R>| res.0 += 1000000,
596        );
597
598        // trigger for an entity and a component
599        world.trigger_with(
600            EntityComponentsEvent(entity_1),
601            EntityComponentsTrigger {
602                components: &[component_a],
603            },
604        );
605        // only observer that doesn't trigger is the one only watching entity_2
606        assert_eq!(1111101, world.resource::<R>().0);
607        world.resource_mut::<R>().0 = 0;
608
609        // trigger for both entities, but no components: trigger once per entity target
610        world.trigger_with(
611            EntityComponentsEvent(entity_1),
612            EntityComponentsTrigger { components: &[] },
613        );
614        world.trigger_with(
615            EntityComponentsEvent(entity_2),
616            EntityComponentsTrigger { components: &[] },
617        );
618
619        // only the observer that doesn't require components triggers - once per entity
620        assert_eq!(200, world.resource::<R>().0);
621        world.resource_mut::<R>().0 = 0;
622
623        // trigger for both entities and both components: trigger once per entity target
624        // we only get 2222211 because a given observer can trigger only once per entity target
625        world.trigger_with(
626            EntityComponentsEvent(entity_1),
627            EntityComponentsTrigger {
628                components: &[component_a, component_b],
629            },
630        );
631        world.trigger_with(
632            EntityComponentsEvent(entity_2),
633            EntityComponentsTrigger {
634                components: &[component_a, component_b],
635            },
636        );
637        assert_eq!(2222211, world.resource::<R>().0);
638        world.resource_mut::<R>().0 = 0;
639    }
640
641    #[test]
642    fn observer_dynamic_component() {
643        let mut world = World::new();
644        world.init_resource::<Order>();
645
646        let component_id = world.register_component::<A>();
647        world.spawn(
648            Observer::new(|_: On<Add>, mut res: ResMut<Order>| res.observed("event_a"))
649                .with_component(component_id),
650        );
651
652        let mut entity = world.spawn_empty();
653        OwningPtr::make(A, |ptr| {
654            // SAFETY: we registered `component_id` above.
655            unsafe { entity.insert_by_id(component_id, ptr) };
656        });
657
658        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
659    }
660
661    #[test]
662    fn observer_dynamic_trigger() {
663        let mut world = World::new();
664        world.init_resource::<Order>();
665        let event_a = world.register_event_key::<EventA>();
666
667        // SAFETY: we registered `event_a` above and it matches the type of EventA
668        let observe = unsafe {
669            Observer::with_dynamic_runner(
670                |mut world, _observer, _trigger_context, _event, _trigger| {
671                    world.resource_mut::<Order>().observed("event_a");
672                },
673            )
674            .with_event_key(event_a)
675        };
676        world.spawn(observe);
677
678        world.commands().queue(move |world: &mut World| {
679            // SAFETY: we registered `event_a` above and it matches the type of EventA
680            unsafe {
681                DeferredWorld::from(world).trigger_raw(
682                    event_a,
683                    &mut EventA,
684                    &mut GlobalTrigger,
685                    MaybeLocation::caller(),
686                );
687            }
688        });
689        world.flush();
690        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
691    }
692
693    #[test]
694    fn observer_propagating() {
695        let mut world = World::new();
696        world.init_resource::<Order>();
697
698        let parent = world.spawn_empty().id();
699        let child = world.spawn(ChildOf(parent)).id();
700
701        world.entity_mut(parent).observe(
702            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
703                res.observed("parent");
704
705                assert_eq!(event.event_target(), parent);
706                assert_eq!(event.original_event_target(), child);
707            },
708        );
709
710        world.entity_mut(child).observe(
711            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
712                res.observed("child");
713                assert_eq!(event.event_target(), child);
714                assert_eq!(event.original_event_target(), child);
715            },
716        );
717
718        world.trigger(EventPropagating(child));
719
720        assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
721    }
722
723    #[test]
724    fn observer_propagating_redundant_dispatch_same_entity() {
725        let mut world = World::new();
726        world.init_resource::<Order>();
727
728        let parent = world
729            .spawn_empty()
730            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
731                res.observed("parent");
732            })
733            .id();
734
735        let child = world
736            .spawn(ChildOf(parent))
737            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
738                res.observed("child");
739            })
740            .id();
741
742        world.trigger(EventPropagating(child));
743        world.trigger(EventPropagating(child));
744
745        assert_eq!(
746            vec!["child", "parent", "child", "parent"],
747            world.resource::<Order>().0
748        );
749    }
750
751    #[test]
752    fn observer_propagating_redundant_dispatch_parent_child() {
753        let mut world = World::new();
754        world.init_resource::<Order>();
755
756        let parent = world
757            .spawn_empty()
758            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
759                res.observed("parent");
760            })
761            .id();
762
763        let child = world
764            .spawn(ChildOf(parent))
765            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
766                res.observed("child");
767            })
768            .id();
769
770        world.trigger(EventPropagating(child));
771        world.trigger(EventPropagating(parent));
772
773        assert_eq!(
774            vec!["child", "parent", "parent"],
775            world.resource::<Order>().0
776        );
777    }
778
779    #[test]
780    fn observer_propagating_halt() {
781        let mut world = World::new();
782        world.init_resource::<Order>();
783
784        let parent = world
785            .spawn_empty()
786            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
787                res.observed("parent");
788            })
789            .id();
790
791        let child = world
792            .spawn(ChildOf(parent))
793            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
794                res.observed("child");
795                event.propagate(false);
796            })
797            .id();
798
799        world.trigger(EventPropagating(child));
800
801        assert_eq!(vec!["child"], world.resource::<Order>().0);
802    }
803
804    #[test]
805    fn observer_propagating_join() {
806        let mut world = World::new();
807        world.init_resource::<Order>();
808
809        let parent = world
810            .spawn_empty()
811            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
812                res.observed("parent");
813            })
814            .id();
815
816        let child_a = world
817            .spawn(ChildOf(parent))
818            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
819                res.observed("child_a");
820            })
821            .id();
822
823        let child_b = world
824            .spawn(ChildOf(parent))
825            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
826                res.observed("child_b");
827            })
828            .id();
829
830        world.trigger(EventPropagating(child_a));
831        world.trigger(EventPropagating(child_b));
832
833        assert_eq!(
834            vec!["child_a", "parent", "child_b", "parent"],
835            world.resource::<Order>().0
836        );
837    }
838
839    #[test]
840    fn observer_propagating_no_next() {
841        let mut world = World::new();
842        world.init_resource::<Order>();
843
844        let entity = world
845            .spawn_empty()
846            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
847                res.observed("event");
848            })
849            .id();
850
851        world.trigger(EventPropagating(entity));
852        assert_eq!(vec!["event"], world.resource::<Order>().0);
853    }
854
855    #[test]
856    fn observer_propagating_parallel_propagation() {
857        let mut world = World::new();
858        world.init_resource::<Order>();
859
860        let parent_a = world
861            .spawn_empty()
862            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
863                res.observed("parent_a");
864            })
865            .id();
866
867        let child_a = world
868            .spawn(ChildOf(parent_a))
869            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
870                res.observed("child_a");
871                event.propagate(false);
872            })
873            .id();
874
875        let parent_b = world
876            .spawn_empty()
877            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
878                res.observed("parent_b");
879            })
880            .id();
881
882        let child_b = world
883            .spawn(ChildOf(parent_b))
884            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
885                res.observed("child_b");
886            })
887            .id();
888
889        world.trigger(EventPropagating(child_a));
890        world.trigger(EventPropagating(child_b));
891
892        assert_eq!(
893            vec!["child_a", "child_b", "parent_b"],
894            world.resource::<Order>().0
895        );
896    }
897
898    #[test]
899    fn observer_propagating_world() {
900        let mut world = World::new();
901        world.init_resource::<Order>();
902
903        world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
904            res.observed("event");
905        });
906
907        let grandparent = world.spawn_empty().id();
908        let parent = world.spawn(ChildOf(grandparent)).id();
909        let child = world.spawn(ChildOf(parent)).id();
910
911        world.trigger(EventPropagating(child));
912
913        assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
914    }
915
916    #[test]
917    fn observer_propagating_world_skipping() {
918        let mut world = World::new();
919        world.init_resource::<Order>();
920
921        world.add_observer(
922            |event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
923                if query.get(event.event_target()).is_ok() {
924                    res.observed("event");
925                }
926            },
927        );
928
929        let grandparent = world.spawn(A).id();
930        let parent = world.spawn(ChildOf(grandparent)).id();
931        let child = world.spawn((A, ChildOf(parent))).id();
932
933        world.trigger(EventPropagating(child));
934
935        assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
936    }
937
938    // Originally for https://github.com/bevyengine/bevy/issues/18452
939    #[test]
940    fn observer_modifies_relationship() {
941        fn on_add(add: On<Add, A>, mut commands: Commands) {
942            commands
943                .entity(add.entity)
944                .with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
945                    rsc.spawn_empty();
946                });
947        }
948
949        let mut world = World::new();
950        world.add_observer(on_add);
951        world.spawn(A);
952    }
953
954    // Regression test for https://github.com/bevyengine/bevy/issues/14467
955    // Fails prior to https://github.com/bevyengine/bevy/pull/15398
956    #[test]
957    fn observer_on_remove_during_despawn_spawn_empty() {
958        let mut world = World::new();
959
960        // Observe the removal of A - this will run during despawn
961        world.add_observer(|_: On<Remove, A>, mut cmd: Commands| {
962            // Spawn a new entity - this reserves a new ID and requires a flush
963            // afterward before Entities::free can be called.
964            cmd.spawn_empty();
965        });
966
967        let ent = world.spawn(A).id();
968
969        // Despawn our entity, which runs the Remove observer and allocates a
970        // new Entity.
971        // Should not panic - if it does, then Entities was not flushed properly
972        // after the observer's spawn_empty.
973        world.despawn(ent);
974    }
975
976    #[test]
977    #[should_panic]
978    fn observer_invalid_params() {
979        #[derive(Resource)]
980        struct ResA;
981
982        #[derive(Resource)]
983        struct ResB;
984
985        let mut world = World::new();
986        // This fails because `ResA` is not present in the world
987        world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
988            commands.insert_resource(ResB);
989        });
990        world.trigger(EventA);
991    }
992
993    #[test]
994    fn observer_apply_deferred_from_param_set() {
995        #[derive(Resource)]
996        struct ResA;
997
998        let mut world = World::new();
999        world.add_observer(
1000            |_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1001                params.p1().insert_resource(ResA);
1002            },
1003        );
1004
1005        world.trigger(EventA);
1006        world.flush();
1007
1008        assert!(world.get_resource::<ResA>().is_some());
1009    }
1010
1011    #[test]
1012    #[track_caller]
1013    fn observer_caller_location_event() {
1014        #[derive(Event)]
1015        struct EventA;
1016
1017        let caller = MaybeLocation::caller();
1018        let mut world = World::new();
1019        world.add_observer(move |event: On<EventA>| {
1020            assert_eq!(event.caller(), caller);
1021        });
1022        world.trigger(EventA);
1023    }
1024
1025    #[test]
1026    #[track_caller]
1027    fn observer_caller_location_command_archetype_move() {
1028        #[derive(Component)]
1029        struct Component;
1030
1031        let caller = MaybeLocation::caller();
1032        let mut world = World::new();
1033        world.add_observer(move |event: On<Add, Component>| {
1034            assert_eq!(event.caller(), caller);
1035        });
1036        world.add_observer(move |event: On<Remove, Component>| {
1037            assert_eq!(event.caller(), caller);
1038        });
1039        world.commands().spawn(Component).clear();
1040    }
1041
1042    #[test]
1043    fn observer_watch_entities() {
1044        let mut world = World::new();
1045        world.init_resource::<Order>();
1046        let entities = world
1047            .spawn_batch(core::iter::repeat_n((), 4))
1048            .collect::<Vec<_>>();
1049        let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1050            order.observed("a");
1051        });
1052        world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1053
1054        world.trigger(EntityEventA(entities[0]));
1055        world.trigger(EntityEventA(entities[1]));
1056        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1057        world.trigger(EntityEventA(entities[2]));
1058        world.trigger(EntityEventA(entities[3]));
1059        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1060    }
1061
1062    #[test]
1063    fn unregister_global_observer() {
1064        let mut world = World::new();
1065        let mut observer = world.add_observer(|_: On<EventA>| {});
1066        observer.remove::<Observer>();
1067        let id = observer.id();
1068        let event_key = world.event_key::<EventA>().unwrap();
1069        assert!(!world
1070            .observers
1071            .get_observers_mut(event_key)
1072            .global_observers
1073            .contains_key(&id));
1074    }
1075
1076    #[test]
1077    fn unregister_entity_observer() {
1078        let mut world = World::new();
1079        let entity = world.spawn_empty().id();
1080        let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1081        let mut observer = world.spawn(observer);
1082        observer.remove::<Observer>();
1083        let event_key = world.event_key::<EventA>().unwrap();
1084        assert!(!world
1085            .observers
1086            .get_observers_mut(event_key)
1087            .entity_observers
1088            .contains_key(&entity));
1089    }
1090
1091    #[test]
1092    fn unregister_component_observer() {
1093        let mut world = World::new();
1094        let a = world.register_component::<A>();
1095        let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1096        let mut observer = world.spawn(observer);
1097        observer.remove::<Observer>();
1098        let event_key = world.event_key::<EventA>().unwrap();
1099        assert!(!world
1100            .observers
1101            .get_observers_mut(event_key)
1102            .component_observers()
1103            .contains_key(&a));
1104    }
1105}