Skip to main content

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 condition;
8mod distributed_storage;
9mod entity_cloning;
10mod runner;
11mod system_param;
12
13pub use centralized_storage::*;
14pub use condition::*;
15pub use distributed_storage::*;
16pub use runner::*;
17pub use system_param::*;
18
19use crate::{
20    change_detection::MaybeLocation,
21    event::Event,
22    prelude::*,
23    world::{DeferredWorld, *},
24};
25
26impl World {
27    /// Spawns a "global" [`Observer`] which will watch for the given event.
28    /// Returns its [`Entity`] as a [`EntityWorldMut`].
29    ///
30    /// `system` can be any system whose first parameter is [`On`].
31    ///
32    /// # Example
33    ///
34    /// ```
35    /// # use bevy_ecs::prelude::*;
36    /// #[derive(Component)]
37    /// struct A;
38    ///
39    /// # let mut world = World::new();
40    /// world.add_observer(|_: On<Add, A>| {
41    ///     // ...
42    /// });
43    /// world.add_observer(|_: On<Remove, A>| {
44    ///     // ...
45    /// });
46    /// ```
47    ///
48    /// **Calling [`observe`](EntityWorldMut::observe) on the returned
49    /// [`EntityWorldMut`] will observe the observer itself, which you very
50    /// likely do not want.**
51    ///
52    /// # Panics
53    ///
54    /// Panics if the given system is an exclusive system.
55    pub fn add_observer<M>(&mut self, observer: impl IntoObserver<M>) -> EntityWorldMut<'_> {
56        self.spawn(observer.into_observer())
57    }
58
59    /// Triggers the given [`Event`], which will run any [`Observer`]s watching for it.
60    ///
61    /// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
62    #[track_caller]
63    pub fn trigger<'a, E: Event<Trigger<'a>: Default>>(&mut self, mut event: E) {
64        self.trigger_ref_with_caller(
65            &mut event,
66            &mut <E::Trigger<'a> as Default>::default(),
67            MaybeLocation::caller(),
68        );
69    }
70
71    /// Triggers the given [`Event`] using the given [`Trigger`](crate::event::Trigger), which will run any [`Observer`]s watching for it.
72    ///
73    /// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
74    #[track_caller]
75    pub fn trigger_with<'a, E: Event>(&mut self, mut event: E, mut trigger: E::Trigger<'a>) {
76        self.trigger_ref_with_caller(&mut event, &mut trigger, MaybeLocation::caller());
77    }
78
79    /// Triggers the given mutable [`Event`] reference, which will run any [`Observer`]s watching for it.
80    ///
81    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
82    /// or use the event after it has been modified by observers.
83    #[track_caller]
84    pub fn trigger_ref<'a, E: Event<Trigger<'a>: Default>>(&mut self, event: &mut E) {
85        self.trigger_ref_with_caller(
86            event,
87            &mut <E::Trigger<'a> as Default>::default(),
88            MaybeLocation::caller(),
89        );
90    }
91
92    /// Triggers the given mutable [`Event`] reference using the given mutable [`Trigger`](crate::event::Trigger) reference, which
93    /// will run any [`Observer`]s watching for it.
94    ///
95    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
96    /// or use the event after it has been modified by observers.
97    pub fn trigger_ref_with<'a, E: Event>(&mut self, event: &mut E, trigger: &mut E::Trigger<'a>) {
98        self.trigger_ref_with_caller(event, trigger, MaybeLocation::caller());
99    }
100
101    pub(crate) fn trigger_ref_with_caller<'a, E: Event>(
102        &mut self,
103        event: &mut E,
104        trigger: &mut E::Trigger<'a>,
105        caller: MaybeLocation,
106    ) {
107        let event_key = self.register_event_key::<E>();
108        // SAFETY: event_key was just registered and matches `event`
109        unsafe {
110            DeferredWorld::from(self).trigger_raw(event_key, event, trigger, caller);
111        }
112    }
113
114    /// Splits `&mut self` into a [`DeferredWorld`] and the [`CachedObservers`]
115    /// registered for `event_key`, or returns `None` if no observers exist.
116    ///
117    /// # Safety
118    ///
119    /// Caller must not use the returned [`DeferredWorld`] to access observer
120    /// storage, as it aliases with the returned [`CachedObservers`] reference.
121    unsafe fn split_for_event(
122        &mut self,
123        event_key: crate::event::EventKey,
124    ) -> Option<(DeferredWorld<'_>, &CachedObservers)> {
125        let world_cell = self.as_unsafe_world_cell();
126        let observers = world_cell.observers();
127        let observers = observers.try_get_observers(event_key)?;
128        // SAFETY: The caller guarantees the returned `DeferredWorld` will not
129        // be used to access observer storage (which `observers` borrows).
130        Some((unsafe { world_cell.into_deferred() }, observers))
131    }
132
133    /// Triggers global [`Observer`]s for `event_key` with untyped event and
134    /// trigger data.
135    ///
136    /// Dynamic equivalent of [`World::trigger`]. Only fires global observers,
137    /// not entity- or component-scoped ones.
138    ///
139    /// Use [`World::trigger_dynamic_targets`] to also fire entity-scoped
140    /// observers.
141    ///
142    /// # Safety
143    ///
144    /// - `event_data` must point to a valid, aligned value whose layout matches
145    ///   what observers registered for this `event_key` expect.
146    /// - `trigger_data` must point to a valid, aligned value whose layout
147    ///   matches what observers registered for this `event_key` expect.
148    #[track_caller]
149    pub unsafe fn trigger_dynamic(
150        &mut self,
151        event_key: crate::event::EventKey,
152        mut event_data: bevy_ptr::PtrMut,
153        mut trigger_data: bevy_ptr::PtrMut,
154    ) {
155        // SAFETY: We have exclusive access via `&mut self` and will not
156        // access observer storage through the returned `DeferredWorld`.
157        let Some((mut world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
158            return;
159        };
160
161        let context = TriggerContext {
162            event_key,
163            caller: MaybeLocation::caller(),
164        };
165
166        // SAFETY: no outstanding world references besides `observers`
167        unsafe {
168            world.as_unsafe_world_cell().increment_trigger_id();
169        }
170
171        for (observer, runner) in observers.global_observers() {
172            // SAFETY:
173            // - `observers` come from `world` and correspond to `event_key`
174            // - caller guarantees `event_data` and `trigger_data` are valid
175            unsafe {
176                (runner)(
177                    world.reborrow(),
178                    *observer,
179                    &context,
180                    event_data.reborrow(),
181                    trigger_data.reborrow(),
182                );
183            }
184        }
185    }
186
187    /// Triggers [`Observer`]s for `event_key` targeting `entity`, with untyped
188    /// event and trigger data.
189    ///
190    /// Fires global and entity-scoped observers. Dynamic equivalent of
191    /// [`EntityWorldMut::trigger`].
192    ///
193    /// # Safety
194    ///
195    /// - `event_data` must point to a valid, aligned value whose layout matches
196    ///   what observers registered for this `event_key` expect.
197    /// - `trigger_data` must point to a valid, aligned value whose layout
198    ///   matches what observers registered for this `event_key` expect.
199    #[track_caller]
200    pub unsafe fn trigger_dynamic_targets(
201        &mut self,
202        event_key: crate::event::EventKey,
203        entity: Entity,
204        event_data: bevy_ptr::PtrMut,
205        trigger_data: bevy_ptr::PtrMut,
206    ) {
207        // SAFETY: We have exclusive access via `&mut self` and will not
208        // access observer storage through the returned `DeferredWorld`.
209        let Some((world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
210            return;
211        };
212
213        let context = TriggerContext {
214            event_key,
215            caller: MaybeLocation::caller(),
216        };
217
218        // SAFETY:
219        // - `observers` come from `world` and correspond to `event_key`
220        // - caller guarantees `event_data` and `trigger_data` are valid
221        // - `trigger_entity_internal` increments the trigger id
222        unsafe {
223            crate::event::trigger_entity_internal(
224                world,
225                observers,
226                event_data,
227                trigger_data,
228                entity,
229                &context,
230            );
231        }
232    }
233
234    /// Triggers [`Observer`]s for `event_key` targeting `entity` and
235    /// `components`, with untyped event and trigger data.
236    ///
237    /// Fires global, entity-scoped, and component-scoped observers.
238    /// Dynamic equivalent of [`EntityComponentsTrigger`].
239    ///
240    /// [`EntityComponentsTrigger`]: crate::event::EntityComponentsTrigger
241    ///
242    /// # Safety
243    ///
244    /// - `event_data` must point to a valid, aligned value whose layout matches
245    ///   what observers registered for this `event_key` expect.
246    /// - `trigger_data` must point to a valid, aligned value whose layout
247    ///   matches what observers registered for this `event_key` expect.
248    #[track_caller]
249    pub unsafe fn trigger_dynamic_targets_components(
250        &mut self,
251        event_key: crate::event::EventKey,
252        entity: Entity,
253        components: &[crate::component::ComponentId],
254        mut event_data: bevy_ptr::PtrMut,
255        mut trigger_data: bevy_ptr::PtrMut,
256    ) {
257        // SAFETY: We have exclusive access via `&mut self` and will not
258        // access observer storage through the returned `DeferredWorld`.
259        let Some((mut world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
260            return;
261        };
262
263        let context = TriggerContext {
264            event_key,
265            caller: MaybeLocation::caller(),
266        };
267
268        // SAFETY:
269        // - `observers` come from `world` and correspond to `event_key`
270        // - caller guarantees `event_data` and `trigger_data` are valid
271        // - `trigger_entity_internal` increments the trigger id
272        unsafe {
273            crate::event::trigger_entity_internal(
274                world.reborrow(),
275                observers,
276                event_data.reborrow(),
277                trigger_data.reborrow(),
278                entity,
279                &context,
280            );
281        }
282
283        // Trigger observers watching for specific components.
284        for id in components {
285            if let Some(component_observers) = observers.component_observers().get(id) {
286                for (observer, runner) in component_observers.global_observers() {
287                    // SAFETY: same as above, caller guarantees data validity
288                    unsafe {
289                        (runner)(
290                            world.reborrow(),
291                            *observer,
292                            &context,
293                            event_data.reborrow(),
294                            trigger_data.reborrow(),
295                        );
296                    }
297                }
298
299                if let Some(map) = component_observers
300                    .entity_component_observers()
301                    .get(&entity)
302                {
303                    for (observer, runner) in map {
304                        // SAFETY: same as above, caller guarantees data validity
305                        unsafe {
306                            (runner)(
307                                world.reborrow(),
308                                *observer,
309                                &context,
310                                event_data.reborrow(),
311                                trigger_data.reborrow(),
312                            );
313                        }
314                    }
315                }
316            }
317        }
318    }
319
320    /// Register an observer to the cache, called when an observer is created
321    pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
322        // SAFETY: References do not alias.
323        let (observer_state, archetypes, observers) = unsafe {
324            let observer_state: *const Observer = self.get::<Observer>(observer_entity).unwrap();
325            // Populate ObservedBy for each observed entity.
326            for watched_entity in (*observer_state).descriptor.entities.iter().copied() {
327                let mut entity_mut = self.entity_mut(watched_entity);
328                let mut observed_by = entity_mut.entry::<ObservedBy>().or_default().into_mut();
329                observed_by.0.push(observer_entity);
330            }
331            (&*observer_state, &mut self.archetypes, &mut self.observers)
332        };
333        let descriptor = &observer_state.descriptor;
334
335        for &event_key in &descriptor.event_keys {
336            let cache = observers.get_observers_mut(event_key);
337
338            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
339                cache
340                    .global_observers
341                    .insert(observer_entity, observer_state.runner);
342            } else if descriptor.components.is_empty() {
343                // Observer is not targeting any components so register it as an entity observer
344                for &watched_entity in &observer_state.descriptor.entities {
345                    let map = cache.entity_observers.entry(watched_entity).or_default();
346                    map.insert(observer_entity, observer_state.runner);
347                }
348            } else {
349                // Register observer for each watched component
350                for &component in &descriptor.components {
351                    let observers =
352                        cache
353                            .component_observers
354                            .entry(component)
355                            .or_insert_with(|| {
356                                if let Some(flag) = Observers::is_archetype_cached(event_key) {
357                                    archetypes.update_flags(component, flag, true);
358                                }
359                                CachedComponentObservers::default()
360                            });
361                    if descriptor.entities.is_empty() {
362                        // Register for all triggers targeting the component
363                        observers
364                            .global_observers
365                            .insert(observer_entity, observer_state.runner);
366                    } else {
367                        // Register for each watched entity
368                        for &watched_entity in &descriptor.entities {
369                            let map = observers
370                                .entity_component_observers
371                                .entry(watched_entity)
372                                .or_default();
373                            map.insert(observer_entity, observer_state.runner);
374                        }
375                    }
376                }
377            }
378        }
379    }
380
381    /// Remove the observer from the cache, called when an observer gets despawned
382    pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
383        let archetypes = &mut self.archetypes;
384        let observers = &mut self.observers;
385
386        for &event_key in &descriptor.event_keys {
387            let cache = observers.get_observers_mut(event_key);
388            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
389                cache.global_observers.remove(&entity);
390            } else if descriptor.components.is_empty() {
391                for watched_entity in &descriptor.entities {
392                    // This check should be unnecessary since this observer hasn't been unregistered yet
393                    let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
394                        continue;
395                    };
396                    observers.remove(&entity);
397                    if observers.is_empty() {
398                        cache.entity_observers.remove(watched_entity);
399                    }
400                }
401            } else {
402                for component in &descriptor.components {
403                    let Some(observers) = cache.component_observers.get_mut(component) else {
404                        continue;
405                    };
406                    if descriptor.entities.is_empty() {
407                        observers.global_observers.remove(&entity);
408                    } else {
409                        for watched_entity in &descriptor.entities {
410                            let Some(map) =
411                                observers.entity_component_observers.get_mut(watched_entity)
412                            else {
413                                continue;
414                            };
415                            map.remove(&entity);
416                            if map.is_empty() {
417                                observers.entity_component_observers.remove(watched_entity);
418                            }
419                        }
420                    }
421
422                    if observers.global_observers.is_empty()
423                        && observers.entity_component_observers.is_empty()
424                    {
425                        cache.component_observers.remove(component);
426                        if let Some(flag) = Observers::is_archetype_cached(event_key)
427                            && let Some(by_component) = archetypes.by_component.get(component)
428                        {
429                            for archetype in by_component.keys() {
430                                let archetype = &mut archetypes.archetypes[archetype.index()];
431                                if archetype.contains(*component) {
432                                    let no_longer_observed = archetype
433                                        .iter_components()
434                                        .all(|id| !cache.component_observers.contains_key(&id));
435
436                                    if no_longer_observed {
437                                        archetype.flags.set(flag, false);
438                                    }
439                                }
440                            }
441                        }
442                    }
443                }
444            }
445        }
446    }
447}
448
449#[cfg(test)]
450mod tests {
451    use alloc::{vec, vec::Vec};
452    use core::any::type_name;
453
454    use bevy_ptr::OwningPtr;
455
456    use crate::{
457        archetype::{Archetype, ArchetypeId},
458        change_detection::MaybeLocation,
459        error::Result,
460        event::{EntityComponentsTrigger, Event, GlobalTrigger},
461        hierarchy::ChildOf,
462        observer::{Discard, Observer},
463        prelude::*,
464        world::DeferredWorld,
465    };
466
467    #[derive(Component)]
468    struct A;
469
470    #[derive(Component)]
471    struct B;
472
473    #[derive(Component)]
474    #[component(storage = "SparseSet")]
475    struct S;
476
477    #[derive(Event)]
478    struct EventA;
479
480    #[derive(EntityEvent)]
481    struct EntityEventA(Entity);
482
483    #[derive(EntityEvent)]
484    #[entity_event(trigger = EntityComponentsTrigger<'a>)]
485    struct EntityComponentsEvent(Entity);
486
487    #[derive(Event)]
488    struct EventWithData {
489        counter: usize,
490    }
491
492    #[derive(Resource, Default)]
493    struct Order(Vec<&'static str>);
494
495    impl Order {
496        #[track_caller]
497        fn observed(&mut self, name: &'static str) {
498            self.0.push(name);
499        }
500    }
501
502    #[derive(Component, EntityEvent)]
503    #[entity_event(propagate, auto_propagate)]
504    struct EventPropagating(Entity);
505
506    #[test]
507    fn observer_order_spawn_despawn() {
508        let mut world = World::new();
509        world.init_resource::<Order>();
510
511        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
512        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
513        world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
514            res.observed("discard");
515        });
516        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
517
518        let entity = world.spawn(A).id();
519        world.despawn(entity);
520        assert_eq!(
521            vec!["add", "insert", "discard", "remove"],
522            world.resource::<Order>().0
523        );
524    }
525
526    #[test]
527    fn observer_order_insert_remove() {
528        let mut world = World::new();
529        world.init_resource::<Order>();
530
531        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
532        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
533        world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
534            res.observed("discard");
535        });
536        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
537
538        let mut entity = world.spawn_empty();
539        entity.insert(A);
540        entity.remove::<A>();
541        entity.flush();
542        assert_eq!(
543            vec!["add", "insert", "discard", "remove"],
544            world.resource::<Order>().0
545        );
546    }
547
548    #[test]
549    fn observer_order_insert_remove_sparse() {
550        let mut world = World::new();
551        world.init_resource::<Order>();
552
553        world.add_observer(|_: On<Add, S>, mut res: ResMut<Order>| res.observed("add"));
554        world.add_observer(|_: On<Insert, S>, mut res: ResMut<Order>| res.observed("insert"));
555        world.add_observer(|_: On<Discard, S>, mut res: ResMut<Order>| {
556            res.observed("discard");
557        });
558        world.add_observer(|_: On<Remove, S>, mut res: ResMut<Order>| res.observed("remove"));
559
560        let mut entity = world.spawn_empty();
561        entity.insert(S);
562        entity.remove::<S>();
563        entity.flush();
564        assert_eq!(
565            vec!["add", "insert", "discard", "remove"],
566            world.resource::<Order>().0
567        );
568    }
569
570    #[test]
571    fn observer_order_replace() {
572        let mut world = World::new();
573        world.init_resource::<Order>();
574
575        let entity = world.spawn(A).id();
576
577        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
578        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
579        world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
580            res.observed("discard");
581        });
582        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
583
584        let mut entity = world.entity_mut(entity);
585        entity.insert(A);
586        entity.flush();
587        assert_eq!(vec!["discard", "insert"], world.resource::<Order>().0);
588    }
589
590    #[test]
591    fn observer_order_recursive() {
592        let mut world = World::new();
593        world.init_resource::<Order>();
594        world.add_observer(
595            |add: On<Add, A>, mut res: ResMut<Order>, mut commands: Commands| {
596                res.observed("add_a");
597                commands.entity(add.entity).insert(B);
598            },
599        );
600        world.add_observer(
601            |remove: On<Remove, A>, mut res: ResMut<Order>, mut commands: Commands| {
602                res.observed("remove_a");
603                commands.entity(remove.entity).remove::<B>();
604            },
605        );
606
607        world.add_observer(
608            |add: On<Add, B>, mut res: ResMut<Order>, mut commands: Commands| {
609                res.observed("add_b");
610                commands.entity(add.entity).remove::<A>();
611            },
612        );
613        world.add_observer(|_: On<Remove, B>, mut res: ResMut<Order>| {
614            res.observed("remove_b");
615        });
616
617        let entity = world.spawn(A).flush();
618        let entity = world.get_entity(entity).unwrap();
619        assert!(!entity.contains::<A>());
620        assert!(!entity.contains::<B>());
621        assert_eq!(
622            vec!["add_a", "add_b", "remove_a", "remove_b"],
623            world.resource::<Order>().0
624        );
625    }
626
627    #[test]
628    fn observer_trigger_ref() {
629        let mut world = World::new();
630
631        world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
632        world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
633        world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
634
635        let mut event = EventWithData { counter: 0 };
636        world.trigger_ref(&mut event);
637        assert_eq!(7, event.counter);
638    }
639
640    #[test]
641    fn observer_multiple_listeners() {
642        let mut world = World::new();
643        world.init_resource::<Order>();
644
645        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
646        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));
647
648        world.spawn(A).flush();
649        assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
650        // we have one A entity and two observers
651        assert_eq!(world.query::<&A>().query(&world).count(), 1);
652        assert_eq!(world.query::<&Observer>().query(&world).count(), 2);
653    }
654
655    #[test]
656    fn observer_multiple_events() {
657        let mut world = World::new();
658        world.init_resource::<Order>();
659        let on_remove = world.register_event_key::<Remove>();
660        world.spawn(
661            // SAFETY: Add and Remove are both unit types, so this is safe
662            unsafe {
663                Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
664                    res.observed("add/remove");
665                })
666                .with_event_key(on_remove)
667            },
668        );
669
670        let entity = world.spawn(A).id();
671        world.despawn(entity);
672        assert_eq!(
673            vec!["add/remove", "add/remove"],
674            world.resource::<Order>().0
675        );
676    }
677
678    #[test]
679    fn observer_multiple_components() {
680        let mut world = World::new();
681        world.init_resource::<Order>();
682        world.register_component::<A>();
683        world.register_component::<B>();
684
685        world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
686            res.observed("add_ab");
687        });
688
689        let entity = world.spawn(A).id();
690        world.entity_mut(entity).insert(B);
691        assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
692    }
693
694    #[test]
695    fn observer_despawn() {
696        let mut world = World::new();
697
698        let system: fn(On<Add, A>) = |_| {
699            panic!("Observer triggered after being despawned.");
700        };
701        let observer = world.add_observer(system).id();
702        world.despawn(observer);
703        world.spawn(A).flush();
704    }
705
706    // Regression test for https://github.com/bevyengine/bevy/issues/14961
707    #[test]
708    fn observer_despawn_archetype_flags() {
709        let mut world = World::new();
710        world.init_resource::<Order>();
711
712        let entity = world.spawn((A, B)).flush();
713
714        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| {
715            res.observed("remove_a");
716        });
717
718        let system: fn(On<Remove, B>) = |_: On<Remove, B>| {
719            panic!("Observer triggered after being despawned.");
720        };
721
722        let observer = world.add_observer(system).flush();
723        world.despawn(observer);
724
725        world.despawn(entity);
726
727        assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
728    }
729
730    #[test]
731    fn observer_multiple_matches() {
732        let mut world = World::new();
733        world.init_resource::<Order>();
734
735        world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
736            res.observed("add_ab");
737        });
738
739        world.spawn((A, B)).flush();
740        assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
741    }
742
743    #[test]
744    fn observer_entity_routing() {
745        let mut world = World::new();
746        world.init_resource::<Order>();
747
748        let system: fn(On<EntityEventA>) = |_| {
749            panic!("Trigger routed to non-targeted entity.");
750        };
751
752        world.spawn_empty().observe(system);
753        let entity = world
754            .spawn_empty()
755            .observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
756            .id();
757        world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
758            assert_eq!(event.event_target(), entity);
759            res.observed("a_2");
760        });
761
762        world.trigger(EntityEventA(entity));
763        assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
764    }
765
766    #[test]
767    fn observer_multiple_targets() {
768        #[derive(Resource, Default)]
769        struct R(i32);
770
771        let mut world = World::new();
772        let component_a = world.register_component::<A>();
773        let component_b = world.register_component::<B>();
774        world.init_resource::<R>();
775
776        // targets (entity_1, A)
777        let entity_1 = world
778            .spawn_empty()
779            .observe(|_: On<EntityComponentsEvent, A>, mut res: ResMut<R>| res.0 += 1)
780            .id();
781        // targets (entity_2, B)
782        let entity_2 = world
783            .spawn_empty()
784            .observe(|_: On<EntityComponentsEvent, B>, mut res: ResMut<R>| res.0 += 10)
785            .id();
786        // targets any entity or component
787        world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
788        // targets any entity, and components A or B
789        world
790            .add_observer(|_: On<EntityComponentsEvent, (A, B)>, mut res: ResMut<R>| res.0 += 1000);
791        // test all tuples
792        world.add_observer(
793            |_: On<EntityComponentsEvent, (A, B, (A, B))>, mut res: ResMut<R>| res.0 += 10000,
794        );
795        world.add_observer(
796            |_: On<EntityComponentsEvent, (A, B, (A, B), ((A, B), (A, B)))>, mut res: ResMut<R>| {
797                res.0 += 100000;
798            },
799        );
800        world.add_observer(
801            |_: On<EntityComponentsEvent, (A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>,
802             mut res: ResMut<R>| res.0 += 1000000,
803        );
804
805        // trigger for an entity and a component
806        world.trigger_with(
807            EntityComponentsEvent(entity_1),
808            EntityComponentsTrigger {
809                components: &[component_a],
810                old_archetype: None,
811                new_archetype: None,
812            },
813        );
814        // only observer that doesn't trigger is the one only watching entity_2
815        assert_eq!(1111101, world.resource::<R>().0);
816        world.resource_mut::<R>().0 = 0;
817
818        // trigger for both entities, but no components: trigger once per entity target
819        world.trigger_with(
820            EntityComponentsEvent(entity_1),
821            EntityComponentsTrigger {
822                components: &[],
823                old_archetype: None,
824                new_archetype: None,
825            },
826        );
827        world.trigger_with(
828            EntityComponentsEvent(entity_2),
829            EntityComponentsTrigger {
830                components: &[],
831                old_archetype: None,
832                new_archetype: None,
833            },
834        );
835
836        // only the observer that doesn't require components triggers - once per entity
837        assert_eq!(200, world.resource::<R>().0);
838        world.resource_mut::<R>().0 = 0;
839
840        // trigger for both entities and both components: trigger once per entity target
841        // we only get 2222211 because a given observer can trigger only once per entity target
842        world.trigger_with(
843            EntityComponentsEvent(entity_1),
844            EntityComponentsTrigger {
845                components: &[component_a, component_b],
846                old_archetype: None,
847                new_archetype: None,
848            },
849        );
850        world.trigger_with(
851            EntityComponentsEvent(entity_2),
852            EntityComponentsTrigger {
853                components: &[component_a, component_b],
854                old_archetype: None,
855                new_archetype: None,
856            },
857        );
858        assert_eq!(2222211, world.resource::<R>().0);
859        world.resource_mut::<R>().0 = 0;
860    }
861
862    #[test]
863    fn observer_dynamic_component() {
864        let mut world = World::new();
865        world.init_resource::<Order>();
866
867        let component_id = world.register_component::<A>();
868        world.spawn(
869            Observer::new(|_: On<Add>, mut res: ResMut<Order>| res.observed("event_a"))
870                .with_component(component_id),
871        );
872
873        let mut entity = world.spawn_empty();
874        OwningPtr::make(A, |ptr| {
875            // SAFETY: we registered `component_id` above.
876            unsafe { entity.insert_by_id(component_id, ptr) };
877        });
878
879        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
880    }
881
882    #[test]
883    fn observer_dynamic_trigger() {
884        let mut world = World::new();
885        world.init_resource::<Order>();
886        let event_a = world.register_event_key::<EventA>();
887
888        // SAFETY: we registered `event_a` above and it matches the type of EventA
889        let observe = unsafe {
890            Observer::with_dynamic_runner(
891                |mut world, _observer, _trigger_context, _event, _trigger| {
892                    world.resource_mut::<Order>().observed("event_a");
893                },
894            )
895            .with_event_key(event_a)
896        };
897        world.spawn(observe);
898
899        world.commands().queue(move |world: &mut World| {
900            // SAFETY: we registered `event_a` above and it matches the type of EventA
901            unsafe {
902                DeferredWorld::from(world).trigger_raw(
903                    event_a,
904                    &mut EventA,
905                    &mut GlobalTrigger,
906                    MaybeLocation::caller(),
907                );
908            }
909        });
910        world.flush();
911        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
912    }
913
914    /// Collects `u32` values read by dynamic observers through `PtrMut`.
915    #[derive(Resource, Default)]
916    struct DynamicValues(Vec<u32>);
917
918    #[test]
919    fn observer_fully_dynamic_trigger() {
920        use core::alloc::Layout;
921
922        let mut world = World::new();
923        world.init_resource::<Order>();
924        world.init_resource::<DynamicValues>();
925
926        // Register a dynamic event whose data is a u32.
927        let event_id = world.register_component_with_descriptor(
928            // SAFETY: u32 layout with no drop
929            unsafe {
930                crate::component::ComponentDescriptor::new_with_layout(
931                    "DynamicEvent",
932                    crate::component::StorageType::Table,
933                    Layout::new::<u32>(),
934                    None,
935                    false,
936                    crate::component::ComponentCloneBehavior::Ignore,
937                    None,
938                )
939            },
940        );
941        // SAFETY: event_id was just registered for use as an event
942        let event_key = unsafe { crate::event::EventKey::new(event_id) };
943
944        // SAFETY: event_key was just created, observer reads event_data as u32
945        let observe = unsafe {
946            Observer::with_dynamic_runner(
947                |mut world, _observer, _trigger_context, event, _trigger| {
948                    // SAFETY: caller passes a valid u32 pointer as event data
949                    let value = *event.as_ref().deref::<u32>();
950                    world.resource_mut::<Order>().observed("dynamic_event");
951                    world.resource_mut::<DynamicValues>().0.push(value);
952                },
953            )
954            .with_event_key(event_key)
955        };
956        world.spawn(observe);
957
958        let mut event_data: u32 = 42;
959        let mut trigger_data: u32 = 0;
960        // SAFETY: pointers are valid u32s matching the registered layout
961        unsafe {
962            world.trigger_dynamic(
963                event_key,
964                bevy_ptr::PtrMut::from(&mut event_data),
965                bevy_ptr::PtrMut::from(&mut trigger_data),
966            );
967        }
968
969        assert_eq!(vec!["dynamic_event"], world.resource::<Order>().0);
970        assert_eq!(vec![42], world.resource::<DynamicValues>().0);
971    }
972
973    #[test]
974    fn observer_fully_dynamic_trigger_targets() {
975        use core::alloc::Layout;
976
977        let mut world = World::new();
978        world.init_resource::<Order>();
979        world.init_resource::<DynamicValues>();
980
981        let event_id = world.register_component_with_descriptor(
982            // SAFETY: u32 layout with no drop
983            unsafe {
984                crate::component::ComponentDescriptor::new_with_layout(
985                    "DynamicEntityEvent",
986                    crate::component::StorageType::Table,
987                    Layout::new::<u32>(),
988                    None,
989                    false,
990                    crate::component::ComponentCloneBehavior::Ignore,
991                    None,
992                )
993            },
994        );
995        // SAFETY: event_id was just registered for use as an event
996        let event_key = unsafe { crate::event::EventKey::new(event_id) };
997
998        let target = world.spawn_empty().id();
999        let other = world.spawn_empty().id();
1000
1001        // SAFETY: event_key was just created, observer reads event_data as u32
1002        let global = unsafe {
1003            Observer::with_dynamic_runner(
1004                |mut world, _observer, _trigger_context, event, _trigger| {
1005                    let value = *event.as_ref().deref::<u32>();
1006                    world.resource_mut::<Order>().observed("global");
1007                    world.resource_mut::<DynamicValues>().0.push(value);
1008                },
1009            )
1010            .with_event_key(event_key)
1011        };
1012        world.spawn(global);
1013
1014        // SAFETY: event_key was just created, observer reads event_data as u32
1015        let entity_scoped = unsafe {
1016            Observer::with_dynamic_runner(
1017                |mut world, _observer, _trigger_context, event, _trigger| {
1018                    let value = *event.as_ref().deref::<u32>();
1019                    world.resource_mut::<Order>().observed("entity_scoped");
1020                    world.resource_mut::<DynamicValues>().0.push(value);
1021                },
1022            )
1023            .with_event_key(event_key)
1024            .with_entity(target)
1025        };
1026        world.spawn(entity_scoped);
1027
1028        // Trigger targeting `target`: both global and entity-scoped should fire.
1029        let mut event_data: u32 = 7;
1030        let mut trigger_data: u32 = 0;
1031        // SAFETY: pointers are valid u32s matching the registered layout
1032        unsafe {
1033            world.trigger_dynamic_targets(
1034                event_key,
1035                target,
1036                bevy_ptr::PtrMut::from(&mut event_data),
1037                bevy_ptr::PtrMut::from(&mut trigger_data),
1038            );
1039        }
1040
1041        assert_eq!(vec!["global", "entity_scoped"], world.resource::<Order>().0);
1042        assert_eq!(vec![7, 7], world.resource::<DynamicValues>().0);
1043
1044        // Trigger targeting `other`: only global should fire.
1045        world.resource_mut::<Order>().0.clear();
1046        world.resource_mut::<DynamicValues>().0.clear();
1047        let mut event_data: u32 = 99;
1048        let mut trigger_data: u32 = 0;
1049        // SAFETY: pointers are valid u32s matching the registered layout
1050        unsafe {
1051            world.trigger_dynamic_targets(
1052                event_key,
1053                other,
1054                bevy_ptr::PtrMut::from(&mut event_data),
1055                bevy_ptr::PtrMut::from(&mut trigger_data),
1056            );
1057        }
1058
1059        assert_eq!(vec!["global"], world.resource::<Order>().0);
1060        assert_eq!(vec![99], world.resource::<DynamicValues>().0);
1061    }
1062
1063    #[test]
1064    fn observer_fully_dynamic_trigger_targets_components() {
1065        use core::alloc::Layout;
1066
1067        let mut world = World::new();
1068        world.init_resource::<Order>();
1069        world.init_resource::<DynamicValues>();
1070
1071        let event_id = world.register_component_with_descriptor(
1072            // SAFETY: u32 layout with no drop
1073            unsafe {
1074                crate::component::ComponentDescriptor::new_with_layout(
1075                    "DynamicComponentEvent",
1076                    crate::component::StorageType::Table,
1077                    Layout::new::<u32>(),
1078                    None,
1079                    false,
1080                    crate::component::ComponentCloneBehavior::Ignore,
1081                    None,
1082                )
1083            },
1084        );
1085        // SAFETY: event_id was just registered for use as an event
1086        let event_key = unsafe { crate::event::EventKey::new(event_id) };
1087
1088        // Register a dynamic component to scope an observer to.
1089        let comp_id = world.register_component_with_descriptor(
1090            // SAFETY: ZST layout with no drop
1091            unsafe {
1092                crate::component::ComponentDescriptor::new_with_layout(
1093                    "DynamicComp",
1094                    crate::component::StorageType::Table,
1095                    Layout::new::<()>(),
1096                    None,
1097                    false,
1098                    crate::component::ComponentCloneBehavior::Ignore,
1099                    None,
1100                )
1101            },
1102        );
1103
1104        let target = world.spawn_empty().id();
1105
1106        // SAFETY: event_key was just created, observer reads event_data as u32
1107        let global = unsafe {
1108            Observer::with_dynamic_runner(
1109                |mut world, _observer, _trigger_context, event, _trigger| {
1110                    let value = *event.as_ref().deref::<u32>();
1111                    world.resource_mut::<Order>().observed("global");
1112                    world.resource_mut::<DynamicValues>().0.push(value);
1113                },
1114            )
1115            .with_event_key(event_key)
1116        };
1117        world.spawn(global);
1118
1119        // SAFETY: event_key was just created, observer reads event_data as u32
1120        let comp_scoped = unsafe {
1121            Observer::with_dynamic_runner(
1122                |mut world, _observer, _trigger_context, event, _trigger| {
1123                    let value = *event.as_ref().deref::<u32>();
1124                    world.resource_mut::<Order>().observed("comp_scoped");
1125                    world.resource_mut::<DynamicValues>().0.push(value);
1126                },
1127            )
1128            .with_event_key(event_key)
1129            .with_component(comp_id)
1130        };
1131        world.spawn(comp_scoped);
1132
1133        // Trigger with `comp_id` in the components list: both should fire.
1134        let mut event_data: u32 = 5;
1135        let mut trigger_data: u32 = 0;
1136        // SAFETY: pointers are valid u32s matching the registered layout
1137        unsafe {
1138            world.trigger_dynamic_targets_components(
1139                event_key,
1140                target,
1141                &[comp_id],
1142                bevy_ptr::PtrMut::from(&mut event_data),
1143                bevy_ptr::PtrMut::from(&mut trigger_data),
1144            );
1145        }
1146
1147        assert_eq!(vec!["global", "comp_scoped"], world.resource::<Order>().0);
1148        assert_eq!(vec![5, 5], world.resource::<DynamicValues>().0);
1149
1150        // Trigger without components: only global should fire.
1151        world.resource_mut::<Order>().0.clear();
1152        world.resource_mut::<DynamicValues>().0.clear();
1153        let mut event_data: u32 = 10;
1154        let mut trigger_data: u32 = 0;
1155        // SAFETY: pointers are valid u32s matching the registered layout
1156        unsafe {
1157            world.trigger_dynamic_targets_components(
1158                event_key,
1159                target,
1160                &[],
1161                bevy_ptr::PtrMut::from(&mut event_data),
1162                bevy_ptr::PtrMut::from(&mut trigger_data),
1163            );
1164        }
1165
1166        assert_eq!(vec!["global"], world.resource::<Order>().0);
1167        assert_eq!(vec![10], world.resource::<DynamicValues>().0);
1168    }
1169
1170    #[test]
1171    fn observer_propagating() {
1172        let mut world = World::new();
1173        world.init_resource::<Order>();
1174
1175        let parent = world.spawn_empty().id();
1176        let child = world.spawn(ChildOf(parent)).id();
1177
1178        world.entity_mut(parent).observe(
1179            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1180                res.observed("parent");
1181
1182                assert_eq!(event.event_target(), parent);
1183                assert_eq!(event.original_event_target(), child);
1184            },
1185        );
1186
1187        world.entity_mut(child).observe(
1188            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1189                res.observed("child");
1190                assert_eq!(event.event_target(), child);
1191                assert_eq!(event.original_event_target(), child);
1192            },
1193        );
1194
1195        world.trigger(EventPropagating(child));
1196
1197        assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
1198    }
1199
1200    #[test]
1201    fn observer_propagating_redundant_dispatch_same_entity() {
1202        let mut world = World::new();
1203        world.init_resource::<Order>();
1204
1205        let parent = world
1206            .spawn_empty()
1207            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1208                res.observed("parent");
1209            })
1210            .id();
1211
1212        let child = world
1213            .spawn(ChildOf(parent))
1214            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1215                res.observed("child");
1216            })
1217            .id();
1218
1219        world.trigger(EventPropagating(child));
1220        world.trigger(EventPropagating(child));
1221
1222        assert_eq!(
1223            vec!["child", "parent", "child", "parent"],
1224            world.resource::<Order>().0
1225        );
1226    }
1227
1228    #[test]
1229    fn observer_propagating_redundant_dispatch_parent_child() {
1230        let mut world = World::new();
1231        world.init_resource::<Order>();
1232
1233        let parent = world
1234            .spawn_empty()
1235            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1236                res.observed("parent");
1237            })
1238            .id();
1239
1240        let child = world
1241            .spawn(ChildOf(parent))
1242            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1243                res.observed("child");
1244            })
1245            .id();
1246
1247        world.trigger(EventPropagating(child));
1248        world.trigger(EventPropagating(parent));
1249
1250        assert_eq!(
1251            vec!["child", "parent", "parent"],
1252            world.resource::<Order>().0
1253        );
1254    }
1255
1256    #[test]
1257    fn observer_propagating_halt() {
1258        let mut world = World::new();
1259        world.init_resource::<Order>();
1260
1261        let parent = world
1262            .spawn_empty()
1263            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1264                res.observed("parent");
1265            })
1266            .id();
1267
1268        let child = world
1269            .spawn(ChildOf(parent))
1270            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1271                res.observed("child");
1272                event.propagate(false);
1273            })
1274            .id();
1275
1276        world.trigger(EventPropagating(child));
1277
1278        assert_eq!(vec!["child"], world.resource::<Order>().0);
1279    }
1280
1281    #[test]
1282    fn observer_propagating_join() {
1283        let mut world = World::new();
1284        world.init_resource::<Order>();
1285
1286        let parent = world
1287            .spawn_empty()
1288            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1289                res.observed("parent");
1290            })
1291            .id();
1292
1293        let child_a = world
1294            .spawn(ChildOf(parent))
1295            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1296                res.observed("child_a");
1297            })
1298            .id();
1299
1300        let child_b = world
1301            .spawn(ChildOf(parent))
1302            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1303                res.observed("child_b");
1304            })
1305            .id();
1306
1307        world.trigger(EventPropagating(child_a));
1308        world.trigger(EventPropagating(child_b));
1309
1310        assert_eq!(
1311            vec!["child_a", "parent", "child_b", "parent"],
1312            world.resource::<Order>().0
1313        );
1314    }
1315
1316    #[test]
1317    fn observer_propagating_no_next() {
1318        let mut world = World::new();
1319        world.init_resource::<Order>();
1320
1321        let entity = world
1322            .spawn_empty()
1323            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1324                res.observed("event");
1325            })
1326            .id();
1327
1328        world.trigger(EventPropagating(entity));
1329        assert_eq!(vec!["event"], world.resource::<Order>().0);
1330    }
1331
1332    #[test]
1333    fn observer_propagating_parallel_propagation() {
1334        let mut world = World::new();
1335        world.init_resource::<Order>();
1336
1337        let parent_a = world
1338            .spawn_empty()
1339            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1340                res.observed("parent_a");
1341            })
1342            .id();
1343
1344        let child_a = world
1345            .spawn(ChildOf(parent_a))
1346            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1347                res.observed("child_a");
1348                event.propagate(false);
1349            })
1350            .id();
1351
1352        let parent_b = world
1353            .spawn_empty()
1354            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1355                res.observed("parent_b");
1356            })
1357            .id();
1358
1359        let child_b = world
1360            .spawn(ChildOf(parent_b))
1361            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1362                res.observed("child_b");
1363            })
1364            .id();
1365
1366        world.trigger(EventPropagating(child_a));
1367        world.trigger(EventPropagating(child_b));
1368
1369        assert_eq!(
1370            vec!["child_a", "child_b", "parent_b"],
1371            world.resource::<Order>().0
1372        );
1373    }
1374
1375    #[test]
1376    fn observer_propagating_world() {
1377        let mut world = World::new();
1378        world.init_resource::<Order>();
1379
1380        world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1381            res.observed("event");
1382        });
1383
1384        let grandparent = world.spawn_empty().id();
1385        let parent = world.spawn(ChildOf(grandparent)).id();
1386        let child = world.spawn(ChildOf(parent)).id();
1387
1388        world.trigger(EventPropagating(child));
1389
1390        assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
1391    }
1392
1393    #[test]
1394    fn observer_propagating_world_skipping() {
1395        let mut world = World::new();
1396        world.init_resource::<Order>();
1397
1398        world.add_observer(
1399            |event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
1400                if query.get(event.event_target()).is_ok() {
1401                    res.observed("event");
1402                }
1403            },
1404        );
1405
1406        let grandparent = world.spawn(A).id();
1407        let parent = world.spawn(ChildOf(grandparent)).id();
1408        let child = world.spawn((A, ChildOf(parent))).id();
1409
1410        world.trigger(EventPropagating(child));
1411
1412        assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
1413    }
1414
1415    // Originally for https://github.com/bevyengine/bevy/issues/18452
1416    #[test]
1417    fn observer_modifies_relationship() {
1418        fn on_add(add: On<Add, A>, mut commands: Commands) {
1419            commands
1420                .entity(add.entity)
1421                .with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
1422                    rsc.spawn_empty();
1423                });
1424        }
1425
1426        let mut world = World::new();
1427        world.add_observer(on_add);
1428        world.spawn(A);
1429    }
1430
1431    // Regression test for https://github.com/bevyengine/bevy/issues/14467
1432    // Fails prior to https://github.com/bevyengine/bevy/pull/15398
1433    #[test]
1434    fn observer_on_remove_during_despawn_spawn_empty() {
1435        let mut world = World::new();
1436
1437        // Observe the removal of A - this will run during despawn
1438        world.add_observer(|_: On<Remove, A>, mut cmd: Commands| {
1439            // Spawn a new entity - this reserves a new ID and requires a flush
1440            // afterward before Entities::free can be called.
1441            cmd.spawn_empty();
1442        });
1443
1444        let ent = world.spawn(A).id();
1445
1446        // Despawn our entity, which runs the Remove observer and allocates a
1447        // new Entity.
1448        // Should not panic - if it does, then Entities was not flushed properly
1449        // after the observer's spawn_empty.
1450        world.despawn(ent);
1451    }
1452
1453    #[test]
1454    #[should_panic]
1455    fn observer_invalid_params() {
1456        #[derive(Resource)]
1457        struct ResA;
1458
1459        #[derive(Resource)]
1460        struct ResB;
1461
1462        let mut world = World::new();
1463        // This fails because `ResA` is not present in the world
1464        world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
1465            commands.insert_resource(ResB);
1466        });
1467        world.trigger(EventA);
1468    }
1469
1470    #[test]
1471    fn observer_apply_deferred_from_param_set() {
1472        #[derive(Resource)]
1473        struct ResA;
1474
1475        let mut world = World::new();
1476        world.add_observer(
1477            |_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1478                params.p1().insert_resource(ResA);
1479            },
1480        );
1481
1482        world.trigger(EventA);
1483        world.flush();
1484
1485        assert!(world.get_resource::<ResA>().is_some());
1486    }
1487
1488    #[test]
1489    #[track_caller]
1490    fn observer_caller_location_event() {
1491        #[derive(Event)]
1492        struct EventA;
1493
1494        let caller = MaybeLocation::caller();
1495        let mut world = World::new();
1496        world.add_observer(move |event: On<EventA>| {
1497            assert_eq!(event.caller(), caller);
1498        });
1499        world.trigger(EventA);
1500    }
1501
1502    #[test]
1503    #[track_caller]
1504    fn observer_caller_location_command_archetype_move() {
1505        #[derive(Component)]
1506        struct Component;
1507
1508        let caller = MaybeLocation::caller();
1509        let mut world = World::new();
1510        world.add_observer(move |event: On<Add, Component>| {
1511            assert_eq!(event.caller(), caller);
1512        });
1513        world.add_observer(move |event: On<Remove, Component>| {
1514            assert_eq!(event.caller(), caller);
1515        });
1516        world.commands().spawn(Component).clear();
1517    }
1518
1519    #[test]
1520    fn observer_watch_entities() {
1521        let mut world = World::new();
1522        world.init_resource::<Order>();
1523        let entities = world
1524            .spawn_batch(core::iter::repeat_n((), 4))
1525            .collect::<Vec<_>>();
1526        let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1527            order.observed("a");
1528        });
1529        world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1530
1531        world.trigger(EntityEventA(entities[0]));
1532        world.trigger(EntityEventA(entities[1]));
1533        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1534        world.trigger(EntityEventA(entities[2]));
1535        world.trigger(EntityEventA(entities[3]));
1536        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1537    }
1538
1539    #[test]
1540    fn unregister_global_observer() {
1541        let mut world = World::new();
1542        let mut observer = world.add_observer(|_: On<EventA>| {});
1543        observer.remove::<Observer>();
1544        let id = observer.id();
1545        let event_key = world.event_key::<EventA>().unwrap();
1546        assert!(!world
1547            .observers
1548            .get_observers_mut(event_key)
1549            .global_observers
1550            .contains_key(&id));
1551    }
1552
1553    #[test]
1554    fn unregister_entity_observer() {
1555        let mut world = World::new();
1556        let entity = world.spawn_empty().id();
1557        let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1558        let mut observer = world.spawn(observer);
1559        observer.remove::<Observer>();
1560        let event_key = world.event_key::<EventA>().unwrap();
1561        assert!(!world
1562            .observers
1563            .get_observers_mut(event_key)
1564            .entity_observers
1565            .contains_key(&entity));
1566    }
1567
1568    #[test]
1569    fn unregister_component_observer() {
1570        let mut world = World::new();
1571        let a = world.register_component::<A>();
1572        let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1573        let mut observer = world.spawn(observer);
1574        observer.remove::<Observer>();
1575        let event_key = world.event_key::<EventA>().unwrap();
1576        assert!(!world
1577            .observers
1578            .get_observers_mut(event_key)
1579            .component_observers()
1580            .contains_key(&a));
1581    }
1582
1583    #[derive(Resource)]
1584    struct RunConditionFlag(bool);
1585
1586    #[test]
1587    fn observer_run_condition_true() {
1588        let mut world = World::new();
1589        world.insert_resource(RunConditionFlag(true));
1590        world.init_resource::<Order>();
1591
1592        world.add_observer(
1593            (|_: On<EventA>, mut order: ResMut<Order>| {
1594                order.observed("event");
1595            })
1596            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1597        );
1598
1599        world.trigger(EventA);
1600        assert_eq!(vec!["event"], world.resource::<Order>().0);
1601    }
1602
1603    #[test]
1604    fn observer_run_condition_false() {
1605        let mut world = World::new();
1606        world.insert_resource(RunConditionFlag(false));
1607        world.init_resource::<Order>();
1608
1609        world.add_observer(
1610            (|_: On<EventA>, mut order: ResMut<Order>| {
1611                order.observed("event");
1612            })
1613            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1614        );
1615
1616        world.trigger(EventA);
1617        assert!(world.resource::<Order>().0.is_empty());
1618    }
1619
1620    #[test]
1621    fn observer_run_condition_chained() {
1622        let mut world = World::new();
1623        world.insert_resource(RunConditionFlag(true));
1624        world.init_resource::<Order>();
1625
1626        #[derive(Resource)]
1627        struct SecondFlag(bool);
1628        world.insert_resource(SecondFlag(true));
1629
1630        world.add_observer(
1631            (|_: On<EventA>, mut order: ResMut<Order>| {
1632                order.observed("event");
1633            })
1634            .run_if(|flag: Res<RunConditionFlag>| flag.0)
1635            .run_if(|flag: Res<SecondFlag>| flag.0),
1636        );
1637
1638        world.trigger(EventA);
1639        assert_eq!(vec!["event"], world.resource::<Order>().0);
1640
1641        world.resource_mut::<Order>().0.clear();
1642        world.resource_mut::<SecondFlag>().0 = false;
1643        world.trigger(EventA);
1644        assert!(world.resource::<Order>().0.is_empty());
1645    }
1646
1647    #[test]
1648    fn observer_run_condition_re_evaluated() {
1649        let mut world = World::new();
1650        world.insert_resource(RunConditionFlag(false));
1651        world.init_resource::<Order>();
1652
1653        world.add_observer(
1654            (|_: On<EventA>, mut order: ResMut<Order>| {
1655                order.observed("event");
1656            })
1657            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1658        );
1659
1660        world.trigger(EventA);
1661        assert!(world.resource::<Order>().0.is_empty());
1662
1663        world.resource_mut::<RunConditionFlag>().0 = true;
1664        world.trigger(EventA);
1665        assert_eq!(vec!["event"], world.resource::<Order>().0);
1666    }
1667
1668    #[test]
1669    fn observer_run_condition_result_bool() {
1670        let mut world = World::new();
1671        world.init_resource::<Order>();
1672
1673        world.add_observer(
1674            (|_: On<EventA>, mut order: ResMut<Order>| {
1675                order.observed("err");
1676            })
1677            .run_if(|| -> Result<bool> { Err(core::fmt::Error.into()) }),
1678        );
1679        world.add_observer(
1680            (|_: On<EventA>, mut order: ResMut<Order>| {
1681                order.observed("false");
1682            })
1683            .run_if(|| -> Result<bool> { Ok(false) }),
1684        );
1685        world.add_observer(
1686            (|_: On<EventA>, mut order: ResMut<Order>| {
1687                order.observed("true");
1688            })
1689            .run_if(|| -> Result<bool> { Ok(true) }),
1690        );
1691
1692        world.trigger(EventA);
1693        assert_eq!(vec!["true"], world.resource::<Order>().0);
1694    }
1695
1696    #[test]
1697    fn observer_conditions_and_change_detection() {
1698        #[derive(Resource, Default)]
1699        struct Bool2(pub bool);
1700
1701        let mut world = World::new();
1702        world.init_resource::<Order>();
1703        world.insert_resource(RunConditionFlag(false));
1704        world.insert_resource(Bool2(false));
1705
1706        world.add_observer(
1707            (|_: On<EventA>, mut order: ResMut<Order>| {
1708                order.observed("event");
1709            })
1710            .run_if(|res1: Res<RunConditionFlag>| res1.is_changed())
1711            .run_if(|res2: Res<Bool2>| res2.is_changed()),
1712        );
1713
1714        // both resources were just added.
1715        world.trigger(EventA);
1716        assert_eq!(vec!["event"], world.resource::<Order>().0);
1717
1718        // nothing has changed
1719        world.resource_mut::<Order>().0.clear();
1720        world.trigger(EventA);
1721        assert!(world.resource::<Order>().0.is_empty());
1722
1723        // RunConditionFlag has changed, but observer did not run
1724        world.resource_mut::<RunConditionFlag>().0 = true;
1725        world.trigger(EventA);
1726        assert!(world.resource::<Order>().0.is_empty());
1727
1728        // internal state for the Bool2 condition was updated in the
1729        // previous run, so observer still does not run
1730        world.resource_mut::<Bool2>().0 = true;
1731        world.trigger(EventA);
1732        assert!(world.resource::<Order>().0.is_empty());
1733
1734        // internal state for Bool2 was updated, so observer still does not run
1735        world.resource_mut::<RunConditionFlag>().0 = false;
1736        world.trigger(EventA);
1737        assert!(world.resource::<Order>().0.is_empty());
1738
1739        // now check that it works correctly changing Bool2 first and then RunConditionFlag
1740        world.resource_mut::<Bool2>().0 = false;
1741        world.resource_mut::<RunConditionFlag>().0 = true;
1742        world.trigger(EventA);
1743        assert_eq!(vec!["event"], world.resource::<Order>().0);
1744    }
1745
1746    #[test]
1747    fn entity_observer_with_run_condition() {
1748        let mut world = World::new();
1749        world.insert_resource(RunConditionFlag(true));
1750        world.init_resource::<Order>();
1751
1752        let entity = world
1753            .spawn_empty()
1754            .observe(
1755                (|_: On<EntityEventA>, mut order: ResMut<Order>| {
1756                    order.observed("entity_event");
1757                })
1758                .run_if(|flag: Res<RunConditionFlag>| flag.0),
1759            )
1760            .id();
1761
1762        world.trigger(EntityEventA(entity));
1763        assert_eq!(vec!["entity_event"], world.resource::<Order>().0);
1764
1765        world.resource_mut::<Order>().0.clear();
1766        world.resource_mut::<RunConditionFlag>().0 = false;
1767        world.trigger(EntityEventA(entity));
1768        assert!(world.resource::<Order>().0.is_empty());
1769    }
1770
1771    #[test]
1772    fn observer_builder_run_if() {
1773        let mut world = World::new();
1774        world.insert_resource(RunConditionFlag(true));
1775        world.init_resource::<Order>();
1776
1777        let observer = Observer::new(|_: On<EventA>, mut order: ResMut<Order>| {
1778            order.observed("event");
1779        })
1780        .run_if(|flag: Res<RunConditionFlag>| flag.0);
1781
1782        world.spawn(observer);
1783
1784        world.trigger(EventA);
1785        assert_eq!(vec!["event"], world.resource::<Order>().0);
1786
1787        world.resource_mut::<Order>().0.clear();
1788        world.resource_mut::<RunConditionFlag>().0 = false;
1789        world.trigger(EventA);
1790        assert!(world.resource::<Order>().0.is_empty());
1791    }
1792
1793    #[test]
1794    fn observer_new_old_archetypes() {
1795        #[derive(Resource, Default)]
1796        struct Changes(Vec<(&'static str, Option<ArchetypeId>, Option<ArchetypeId>)>);
1797
1798        let mut world = World::new();
1799        world.init_resource::<Changes>();
1800
1801        fn observer<E: for<'a> Event<Trigger<'a> = EntityComponentsTrigger<'a>>>(
1802            e: On<E, A>,
1803            mut c: ResMut<Changes>,
1804        ) {
1805            c.0.push((
1806                type_name::<E>(),
1807                e.trigger().old_archetype.map(Archetype::id),
1808                e.trigger().new_archetype.map(Archetype::id),
1809            ));
1810        }
1811
1812        let empty = world.spawn(()).archetype().id();
1813        let a = world.spawn(A).archetype().id();
1814        let ab = world.spawn((A, B)).archetype().id();
1815
1816        world.add_observer(observer::<Add>);
1817        world.add_observer(observer::<Insert>);
1818        world.add_observer(observer::<Discard>);
1819        world.add_observer(observer::<Remove>);
1820        world.add_observer(observer::<Despawn>);
1821
1822        let mut entity = world.spawn((A, B));
1823        entity.remove::<(A, B)>();
1824        entity.insert(A);
1825        entity.insert(A);
1826        entity.despawn();
1827
1828        assert_eq!(
1829            &world.resource_mut::<Changes>().0,
1830            &[
1831                ("bevy_ecs::lifecycle::Add", None, Some(ab)),
1832                ("bevy_ecs::lifecycle::Insert", None, Some(ab)),
1833                ("bevy_ecs::lifecycle::Discard", Some(ab), Some(empty)),
1834                ("bevy_ecs::lifecycle::Remove", Some(ab), Some(empty)),
1835                ("bevy_ecs::lifecycle::Add", Some(empty), Some(a)),
1836                ("bevy_ecs::lifecycle::Insert", Some(empty), Some(a)),
1837                ("bevy_ecs::lifecycle::Discard", Some(a), Some(a)),
1838                ("bevy_ecs::lifecycle::Insert", Some(a), Some(a)),
1839                ("bevy_ecs::lifecycle::Despawn", Some(a), None),
1840                ("bevy_ecs::lifecycle::Discard", Some(a), None),
1841                ("bevy_ecs::lifecycle::Remove", Some(a), None),
1842            ],
1843        );
1844    }
1845}