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        // Remove this observer from all the corresponding ObservedBy components.
384        for &observing in descriptor.entities.iter() {
385            let Ok(mut observing) = self.get_entity_mut(observing) else {
386                // This can happen when ObservedBy is despawning and is despawning the related
387                // observers.
388                continue;
389            };
390            let Some(mut observed_by) = observing.get_mut::<ObservedBy>() else {
391                // In "normal" usage, this should be impossible, but there's nothing stopping a user
392                // from just removing the ObservedBy component themselves. While that's odd usage,
393                // there's no reason to panic if a user does so.
394                continue;
395            };
396
397            observed_by.0.retain(|e| *e != entity);
398            if observed_by.0.is_empty() {
399                observing.remove::<ObservedBy>();
400            }
401        }
402
403        let archetypes = &mut self.archetypes;
404        let observers = &mut self.observers;
405
406        for &event_key in &descriptor.event_keys {
407            let cache = observers.get_observers_mut(event_key);
408            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
409                cache.global_observers.remove(&entity);
410            } else if descriptor.components.is_empty() {
411                for watched_entity in &descriptor.entities {
412                    // This check should be unnecessary since this observer hasn't been unregistered yet
413                    let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
414                        continue;
415                    };
416                    observers.remove(&entity);
417                    if observers.is_empty() {
418                        cache.entity_observers.remove(watched_entity);
419                    }
420                }
421            } else {
422                for component in &descriptor.components {
423                    let Some(observers) = cache.component_observers.get_mut(component) else {
424                        continue;
425                    };
426                    if descriptor.entities.is_empty() {
427                        observers.global_observers.remove(&entity);
428                    } else {
429                        for watched_entity in &descriptor.entities {
430                            let Some(map) =
431                                observers.entity_component_observers.get_mut(watched_entity)
432                            else {
433                                continue;
434                            };
435                            map.remove(&entity);
436                            if map.is_empty() {
437                                observers.entity_component_observers.remove(watched_entity);
438                            }
439                        }
440                    }
441
442                    if observers.global_observers.is_empty()
443                        && observers.entity_component_observers.is_empty()
444                    {
445                        cache.component_observers.remove(component);
446                        if let Some(flag) = Observers::is_archetype_cached(event_key)
447                            && let Some(by_component) = archetypes.by_component.get(component)
448                        {
449                            for archetype in by_component.keys() {
450                                let archetype = &mut archetypes.archetypes[archetype.index()];
451                                if archetype.contains(*component) {
452                                    let no_longer_observed = archetype
453                                        .iter_components()
454                                        .all(|id| !cache.component_observers.contains_key(&id));
455
456                                    if no_longer_observed {
457                                        archetype.flags.set(flag, false);
458                                    }
459                                }
460                            }
461                        }
462                    }
463                }
464            }
465        }
466    }
467}
468
469#[cfg(test)]
470mod tests {
471    use alloc::{vec, vec::Vec};
472    use core::{any::type_name, marker::PhantomData};
473
474    use bevy_ptr::OwningPtr;
475
476    use crate::{
477        archetype::{Archetype, ArchetypeId},
478        change_detection::MaybeLocation,
479        error::Result,
480        event::{EntityComponentsTrigger, Event, EventPattern, GlobalTrigger},
481        hierarchy::ChildOf,
482        lifecycle::RemoveEvent,
483        observer::{Discard, ObservedBy, Observer},
484        prelude::*,
485        world::DeferredWorld,
486    };
487
488    #[derive(Component)]
489    struct A;
490
491    #[derive(Component)]
492    struct B;
493
494    #[derive(Component)]
495    #[component(storage = "SparseSet")]
496    struct S;
497
498    #[derive(Event)]
499    struct EventA;
500
501    #[derive(EntityEvent)]
502    struct EntityEventA(Entity);
503
504    #[derive(EntityEvent)]
505    #[entity_event(trigger = EntityComponentsTrigger<'a>)]
506    struct EntityComponentsEvent(Entity);
507
508    struct EntityComponents<B: Bundle>(PhantomData<B>);
509
510    impl<B: Bundle> EventPattern for EntityComponents<B> {
511        type Event = EntityComponentsEvent;
512        type Components = B;
513    }
514
515    #[derive(Event)]
516    struct EventWithData {
517        counter: usize,
518    }
519
520    #[derive(Resource, Default)]
521    struct Order(Vec<&'static str>);
522
523    impl Order {
524        #[track_caller]
525        fn observed(&mut self, name: &'static str) {
526            self.0.push(name);
527        }
528    }
529
530    #[derive(Component, EntityEvent)]
531    #[entity_event(propagate, auto_propagate)]
532    struct EventPropagating(Entity);
533
534    #[test]
535    fn observer_order_spawn_despawn() {
536        let mut world = World::new();
537        world.init_resource::<Order>();
538
539        world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add"));
540        world.add_observer(|_: On<Insert<A>>, mut res: ResMut<Order>| res.observed("insert"));
541        world.add_observer(|_: On<Discard<A>>, mut res: ResMut<Order>| {
542            res.observed("discard");
543        });
544        world.add_observer(|_: On<Remove<A>>, mut res: ResMut<Order>| res.observed("remove"));
545
546        let entity = world.spawn(A).id();
547        world.despawn(entity);
548        assert_eq!(
549            vec!["add", "insert", "discard", "remove"],
550            world.resource::<Order>().0
551        );
552    }
553
554    #[test]
555    fn observer_order_insert_remove() {
556        let mut world = World::new();
557        world.init_resource::<Order>();
558
559        world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add"));
560        world.add_observer(|_: On<Insert<A>>, mut res: ResMut<Order>| res.observed("insert"));
561        world.add_observer(|_: On<Discard<A>>, mut res: ResMut<Order>| {
562            res.observed("discard");
563        });
564        world.add_observer(|_: On<Remove<A>>, mut res: ResMut<Order>| res.observed("remove"));
565
566        let mut entity = world.spawn_empty();
567        entity.insert(A);
568        entity.remove::<A>();
569        entity.flush();
570        assert_eq!(
571            vec!["add", "insert", "discard", "remove"],
572            world.resource::<Order>().0
573        );
574    }
575
576    #[test]
577    fn observer_order_insert_remove_sparse() {
578        let mut world = World::new();
579        world.init_resource::<Order>();
580
581        world.add_observer(|_: On<Add<S>>, mut res: ResMut<Order>| res.observed("add"));
582        world.add_observer(|_: On<Insert<S>>, mut res: ResMut<Order>| res.observed("insert"));
583        world.add_observer(|_: On<Discard<S>>, mut res: ResMut<Order>| {
584            res.observed("discard");
585        });
586        world.add_observer(|_: On<Remove<S>>, mut res: ResMut<Order>| res.observed("remove"));
587
588        let mut entity = world.spawn_empty();
589        entity.insert(S);
590        entity.remove::<S>();
591        entity.flush();
592        assert_eq!(
593            vec!["add", "insert", "discard", "remove"],
594            world.resource::<Order>().0
595        );
596    }
597
598    #[test]
599    fn observer_order_replace() {
600        let mut world = World::new();
601        world.init_resource::<Order>();
602
603        let entity = world.spawn(A).id();
604
605        world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add"));
606        world.add_observer(|_: On<Insert<A>>, mut res: ResMut<Order>| res.observed("insert"));
607        world.add_observer(|_: On<Discard<A>>, mut res: ResMut<Order>| {
608            res.observed("discard");
609        });
610        world.add_observer(|_: On<Remove<A>>, mut res: ResMut<Order>| res.observed("remove"));
611
612        let mut entity = world.entity_mut(entity);
613        entity.insert(A);
614        entity.flush();
615        assert_eq!(vec!["discard", "insert"], world.resource::<Order>().0);
616    }
617
618    #[test]
619    fn observer_order_recursive() {
620        let mut world = World::new();
621        world.init_resource::<Order>();
622        world.add_observer(
623            |add: On<Add<A>>, mut res: ResMut<Order>, mut commands: Commands| {
624                res.observed("add_a");
625                commands.entity(add.entity).insert(B);
626            },
627        );
628        world.add_observer(
629            |remove: On<Remove<A>>, mut res: ResMut<Order>, mut commands: Commands| {
630                res.observed("remove_a");
631                commands.entity(remove.entity).remove::<B>();
632            },
633        );
634
635        world.add_observer(
636            |add: On<Add<B>>, mut res: ResMut<Order>, mut commands: Commands| {
637                res.observed("add_b");
638                commands.entity(add.entity).remove::<A>();
639            },
640        );
641        world.add_observer(|_: On<Remove<B>>, mut res: ResMut<Order>| {
642            res.observed("remove_b");
643        });
644
645        let entity = world.spawn(A).flush();
646        let entity = world.get_entity(entity).unwrap();
647        assert!(!entity.contains::<A>());
648        assert!(!entity.contains::<B>());
649        assert_eq!(
650            vec!["add_a", "add_b", "remove_a", "remove_b"],
651            world.resource::<Order>().0
652        );
653    }
654
655    #[test]
656    fn observer_trigger_ref() {
657        let mut world = World::new();
658
659        world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
660        world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
661        world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
662
663        let mut event = EventWithData { counter: 0 };
664        world.trigger_ref(&mut event);
665        assert_eq!(7, event.counter);
666    }
667
668    #[test]
669    fn observer_multiple_listeners() {
670        let mut world = World::new();
671        world.init_resource::<Order>();
672
673        world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add_1"));
674        world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add_2"));
675
676        world.spawn(A).flush();
677        assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
678        // we have one A entity and two observers
679        assert_eq!(world.query::<&A>().query(&world).count(), 1);
680        assert_eq!(world.query::<&Observer>().query(&world).count(), 2);
681    }
682
683    #[test]
684    fn observer_multiple_events() {
685        let mut world = World::new();
686        world.init_resource::<Order>();
687        let on_remove = world.register_event_key::<RemoveEvent>();
688        world.spawn(
689            // SAFETY: Add and Remove are both unit types, so this is safe
690            unsafe {
691                Observer::new(|_: On<Add<A>>, mut res: ResMut<Order>| {
692                    res.observed("add/remove");
693                })
694                .with_event_key(on_remove)
695            },
696        );
697
698        let entity = world.spawn(A).id();
699        world.despawn(entity);
700        assert_eq!(
701            vec!["add/remove", "add/remove"],
702            world.resource::<Order>().0
703        );
704    }
705
706    #[test]
707    fn observer_multiple_components() {
708        let mut world = World::new();
709        world.init_resource::<Order>();
710        world.register_component::<A>();
711        world.register_component::<B>();
712
713        world.add_observer(|_: On<Add<(A, B)>>, mut res: ResMut<Order>| {
714            res.observed("add_ab");
715        });
716
717        let entity = world.spawn(A).id();
718        world.entity_mut(entity).insert(B);
719        assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
720    }
721
722    #[test]
723    fn observer_despawn() {
724        let mut world = World::new();
725
726        let system: fn(On<Add<A>>) = |_| {
727            panic!("Observer triggered after being despawned.");
728        };
729        let observer = world.add_observer(system).id();
730        world.despawn(observer);
731        world.spawn(A).flush();
732    }
733
734    // Regression test for https://github.com/bevyengine/bevy/issues/14961
735    #[test]
736    fn observer_despawn_archetype_flags() {
737        let mut world = World::new();
738        world.init_resource::<Order>();
739
740        let entity = world.spawn((A, B)).flush();
741
742        world.add_observer(|_: On<Remove<A>>, mut res: ResMut<Order>| {
743            res.observed("remove_a");
744        });
745
746        let system: fn(On<Remove<B>>) = |_: On<Remove<B>>| {
747            panic!("Observer triggered after being despawned.");
748        };
749
750        let observer = world.add_observer(system).flush();
751        world.despawn(observer);
752
753        world.despawn(entity);
754
755        assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
756    }
757
758    #[test]
759    fn observer_multiple_matches() {
760        let mut world = World::new();
761        world.init_resource::<Order>();
762
763        world.add_observer(|_: On<Add<(A, B)>>, mut res: ResMut<Order>| {
764            res.observed("add_ab");
765        });
766
767        world.spawn((A, B)).flush();
768        assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
769    }
770
771    #[test]
772    fn observer_entity_routing() {
773        let mut world = World::new();
774        world.init_resource::<Order>();
775
776        let system: fn(On<EntityEventA>) = |_| {
777            panic!("Trigger routed to non-targeted entity.");
778        };
779
780        world.spawn_empty().observe(system);
781        let entity = world
782            .spawn_empty()
783            .observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
784            .id();
785        world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
786            assert_eq!(event.event_target(), entity);
787            res.observed("a_2");
788        });
789
790        world.trigger(EntityEventA(entity));
791        assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
792    }
793
794    #[test]
795    fn observer_multiple_targets() {
796        #[derive(Resource, Default)]
797        struct R(i32);
798
799        let mut world = World::new();
800        let component_a = world.register_component::<A>();
801        let component_b = world.register_component::<B>();
802        world.init_resource::<R>();
803
804        // targets (entity_1, A)
805        let entity_1 = world
806            .spawn_empty()
807            .observe(|_: On<EntityComponents<A>>, mut res: ResMut<R>| res.0 += 1)
808            .id();
809        // targets (entity_2, B)
810        let entity_2 = world
811            .spawn_empty()
812            .observe(|_: On<EntityComponents<B>>, mut res: ResMut<R>| res.0 += 10)
813            .id();
814        // targets any entity or component
815        world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
816        // targets any entity, and components A or B
817        world.add_observer(|_: On<EntityComponents<(A, B)>>, mut res: ResMut<R>| res.0 += 1000);
818        // test all tuples
819        world.add_observer(
820            |_: On<EntityComponents<(A, B, (A, B))>>, mut res: ResMut<R>| res.0 += 10000,
821        );
822        world.add_observer(
823            |_: On<EntityComponents<(A, B, (A, B), ((A, B), (A, B)))>>, mut res: ResMut<R>| {
824                res.0 += 100000;
825            },
826        );
827        world.add_observer(
828            |_: On<EntityComponents<(A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>>,
829             mut res: ResMut<R>| res.0 += 1000000,
830        );
831
832        // trigger for an entity and a component
833        world.trigger_with(
834            EntityComponentsEvent(entity_1),
835            EntityComponentsTrigger {
836                components: &[component_a],
837                old_archetype: None,
838                new_archetype: None,
839            },
840        );
841        // only observer that doesn't trigger is the one only watching entity_2
842        assert_eq!(1111101, world.resource::<R>().0);
843        world.resource_mut::<R>().0 = 0;
844
845        // trigger for both entities, but no components: trigger once per entity target
846        world.trigger_with(
847            EntityComponentsEvent(entity_1),
848            EntityComponentsTrigger {
849                components: &[],
850                old_archetype: None,
851                new_archetype: None,
852            },
853        );
854        world.trigger_with(
855            EntityComponentsEvent(entity_2),
856            EntityComponentsTrigger {
857                components: &[],
858                old_archetype: None,
859                new_archetype: None,
860            },
861        );
862
863        // only the observer that doesn't require components triggers - once per entity
864        assert_eq!(200, world.resource::<R>().0);
865        world.resource_mut::<R>().0 = 0;
866
867        // trigger for both entities and both components: trigger once per entity target
868        // we only get 2222211 because a given observer can trigger only once per entity target
869        world.trigger_with(
870            EntityComponentsEvent(entity_1),
871            EntityComponentsTrigger {
872                components: &[component_a, component_b],
873                old_archetype: None,
874                new_archetype: None,
875            },
876        );
877        world.trigger_with(
878            EntityComponentsEvent(entity_2),
879            EntityComponentsTrigger {
880                components: &[component_a, component_b],
881                old_archetype: None,
882                new_archetype: None,
883            },
884        );
885        assert_eq!(2222211, world.resource::<R>().0);
886        world.resource_mut::<R>().0 = 0;
887    }
888
889    #[test]
890    fn observer_dynamic_component() {
891        let mut world = World::new();
892        world.init_resource::<Order>();
893
894        let component_id = world.register_component::<A>();
895        world.spawn(
896            Observer::new(|_: On<Add<()>>, mut res: ResMut<Order>| res.observed("event_a"))
897                .with_component(component_id),
898        );
899
900        let mut entity = world.spawn_empty();
901        OwningPtr::make(A, |ptr| {
902            // SAFETY: we registered `component_id` above.
903            unsafe { entity.insert_by_id(component_id, ptr) };
904        });
905
906        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
907    }
908
909    #[test]
910    fn observer_dynamic_trigger() {
911        let mut world = World::new();
912        world.init_resource::<Order>();
913        let event_a = world.register_event_key::<EventA>();
914
915        // SAFETY: we registered `event_a` above and it matches the type of EventA
916        let observe = unsafe {
917            Observer::with_dynamic_runner(
918                |mut world, _observer, _trigger_context, _event, _trigger| {
919                    world.resource_mut::<Order>().observed("event_a");
920                },
921            )
922            .with_event_key(event_a)
923        };
924        world.spawn(observe);
925
926        world.commands().queue(move |world: &mut World| {
927            // SAFETY: we registered `event_a` above and it matches the type of EventA
928            unsafe {
929                DeferredWorld::from(world).trigger_raw(
930                    event_a,
931                    &mut EventA,
932                    &mut GlobalTrigger,
933                    MaybeLocation::caller(),
934                );
935            }
936        });
937        world.flush();
938        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
939    }
940
941    /// Collects `u32` values read by dynamic observers through `PtrMut`.
942    #[derive(Resource, Default)]
943    struct DynamicValues(Vec<u32>);
944
945    #[test]
946    fn observer_fully_dynamic_trigger() {
947        use core::alloc::Layout;
948
949        let mut world = World::new();
950        world.init_resource::<Order>();
951        world.init_resource::<DynamicValues>();
952
953        // Register a dynamic event whose data is a u32.
954        let event_id = world.register_component_with_descriptor(
955            // SAFETY: u32 layout with no drop
956            unsafe {
957                crate::component::ComponentDescriptor::new_with_layout(
958                    "DynamicEvent",
959                    crate::component::StorageType::Table,
960                    Layout::new::<u32>(),
961                    None,
962                    false,
963                    false,
964                    crate::component::ComponentCloneBehavior::Ignore,
965                    None,
966                )
967            },
968        );
969        // SAFETY: event_id was just registered for use as an event
970        let event_key = unsafe { crate::event::EventKey::new(event_id) };
971
972        // SAFETY: event_key was just created, observer reads event_data as u32
973        let observe = unsafe {
974            Observer::with_dynamic_runner(
975                |mut world, _observer, _trigger_context, event, _trigger| {
976                    // SAFETY: caller passes a valid u32 pointer as event data
977                    let value = *event.as_ref().deref::<u32>();
978                    world.resource_mut::<Order>().observed("dynamic_event");
979                    world.resource_mut::<DynamicValues>().0.push(value);
980                },
981            )
982            .with_event_key(event_key)
983        };
984        world.spawn(observe);
985
986        let mut event_data: u32 = 42;
987        let mut trigger_data: u32 = 0;
988        // SAFETY: pointers are valid u32s matching the registered layout
989        unsafe {
990            world.trigger_dynamic(
991                event_key,
992                bevy_ptr::PtrMut::from(&mut event_data),
993                bevy_ptr::PtrMut::from(&mut trigger_data),
994            );
995        }
996
997        assert_eq!(vec!["dynamic_event"], world.resource::<Order>().0);
998        assert_eq!(vec![42], world.resource::<DynamicValues>().0);
999    }
1000
1001    #[test]
1002    fn observer_fully_dynamic_trigger_targets() {
1003        use core::alloc::Layout;
1004
1005        let mut world = World::new();
1006        world.init_resource::<Order>();
1007        world.init_resource::<DynamicValues>();
1008
1009        let event_id = world.register_component_with_descriptor(
1010            // SAFETY: u32 layout with no drop
1011            unsafe {
1012                crate::component::ComponentDescriptor::new_with_layout(
1013                    "DynamicEntityEvent",
1014                    crate::component::StorageType::Table,
1015                    Layout::new::<u32>(),
1016                    None,
1017                    false,
1018                    false,
1019                    crate::component::ComponentCloneBehavior::Ignore,
1020                    None,
1021                )
1022            },
1023        );
1024        // SAFETY: event_id was just registered for use as an event
1025        let event_key = unsafe { crate::event::EventKey::new(event_id) };
1026
1027        let target = world.spawn_empty().id();
1028        let other = world.spawn_empty().id();
1029
1030        // SAFETY: event_key was just created, observer reads event_data as u32
1031        let global = unsafe {
1032            Observer::with_dynamic_runner(
1033                |mut world, _observer, _trigger_context, event, _trigger| {
1034                    let value = *event.as_ref().deref::<u32>();
1035                    world.resource_mut::<Order>().observed("global");
1036                    world.resource_mut::<DynamicValues>().0.push(value);
1037                },
1038            )
1039            .with_event_key(event_key)
1040        };
1041        world.spawn(global);
1042
1043        // SAFETY: event_key was just created, observer reads event_data as u32
1044        let entity_scoped = unsafe {
1045            Observer::with_dynamic_runner(
1046                |mut world, _observer, _trigger_context, event, _trigger| {
1047                    let value = *event.as_ref().deref::<u32>();
1048                    world.resource_mut::<Order>().observed("entity_scoped");
1049                    world.resource_mut::<DynamicValues>().0.push(value);
1050                },
1051            )
1052            .with_event_key(event_key)
1053            .with_entity(target)
1054        };
1055        world.spawn(entity_scoped);
1056
1057        // Trigger targeting `target`: both global and entity-scoped should fire.
1058        let mut event_data: u32 = 7;
1059        let mut trigger_data: u32 = 0;
1060        // SAFETY: pointers are valid u32s matching the registered layout
1061        unsafe {
1062            world.trigger_dynamic_targets(
1063                event_key,
1064                target,
1065                bevy_ptr::PtrMut::from(&mut event_data),
1066                bevy_ptr::PtrMut::from(&mut trigger_data),
1067            );
1068        }
1069
1070        assert_eq!(vec!["global", "entity_scoped"], world.resource::<Order>().0);
1071        assert_eq!(vec![7, 7], world.resource::<DynamicValues>().0);
1072
1073        // Trigger targeting `other`: only global should fire.
1074        world.resource_mut::<Order>().0.clear();
1075        world.resource_mut::<DynamicValues>().0.clear();
1076        let mut event_data: u32 = 99;
1077        let mut trigger_data: u32 = 0;
1078        // SAFETY: pointers are valid u32s matching the registered layout
1079        unsafe {
1080            world.trigger_dynamic_targets(
1081                event_key,
1082                other,
1083                bevy_ptr::PtrMut::from(&mut event_data),
1084                bevy_ptr::PtrMut::from(&mut trigger_data),
1085            );
1086        }
1087
1088        assert_eq!(vec!["global"], world.resource::<Order>().0);
1089        assert_eq!(vec![99], world.resource::<DynamicValues>().0);
1090    }
1091
1092    #[test]
1093    fn observer_fully_dynamic_trigger_targets_components() {
1094        use core::alloc::Layout;
1095
1096        let mut world = World::new();
1097        world.init_resource::<Order>();
1098        world.init_resource::<DynamicValues>();
1099
1100        let event_id = world.register_component_with_descriptor(
1101            // SAFETY: u32 layout with no drop
1102            unsafe {
1103                crate::component::ComponentDescriptor::new_with_layout(
1104                    "DynamicComponentEvent",
1105                    crate::component::StorageType::Table,
1106                    Layout::new::<u32>(),
1107                    None,
1108                    false,
1109                    false,
1110                    crate::component::ComponentCloneBehavior::Ignore,
1111                    None,
1112                )
1113            },
1114        );
1115        // SAFETY: event_id was just registered for use as an event
1116        let event_key = unsafe { crate::event::EventKey::new(event_id) };
1117
1118        // Register a dynamic component to scope an observer to.
1119        let comp_id = world.register_component_with_descriptor(
1120            // SAFETY: ZST layout with no drop
1121            unsafe {
1122                crate::component::ComponentDescriptor::new_with_layout(
1123                    "DynamicComp",
1124                    crate::component::StorageType::Table,
1125                    Layout::new::<()>(),
1126                    None,
1127                    false,
1128                    false,
1129                    crate::component::ComponentCloneBehavior::Ignore,
1130                    None,
1131                )
1132            },
1133        );
1134
1135        let target = world.spawn_empty().id();
1136
1137        // SAFETY: event_key was just created, observer reads event_data as u32
1138        let global = unsafe {
1139            Observer::with_dynamic_runner(
1140                |mut world, _observer, _trigger_context, event, _trigger| {
1141                    let value = *event.as_ref().deref::<u32>();
1142                    world.resource_mut::<Order>().observed("global");
1143                    world.resource_mut::<DynamicValues>().0.push(value);
1144                },
1145            )
1146            .with_event_key(event_key)
1147        };
1148        world.spawn(global);
1149
1150        // SAFETY: event_key was just created, observer reads event_data as u32
1151        let comp_scoped = unsafe {
1152            Observer::with_dynamic_runner(
1153                |mut world, _observer, _trigger_context, event, _trigger| {
1154                    let value = *event.as_ref().deref::<u32>();
1155                    world.resource_mut::<Order>().observed("comp_scoped");
1156                    world.resource_mut::<DynamicValues>().0.push(value);
1157                },
1158            )
1159            .with_event_key(event_key)
1160            .with_component(comp_id)
1161        };
1162        world.spawn(comp_scoped);
1163
1164        // Trigger with `comp_id` in the components list: both should fire.
1165        let mut event_data: u32 = 5;
1166        let mut trigger_data: u32 = 0;
1167        // SAFETY: pointers are valid u32s matching the registered layout
1168        unsafe {
1169            world.trigger_dynamic_targets_components(
1170                event_key,
1171                target,
1172                &[comp_id],
1173                bevy_ptr::PtrMut::from(&mut event_data),
1174                bevy_ptr::PtrMut::from(&mut trigger_data),
1175            );
1176        }
1177
1178        assert_eq!(vec!["global", "comp_scoped"], world.resource::<Order>().0);
1179        assert_eq!(vec![5, 5], world.resource::<DynamicValues>().0);
1180
1181        // Trigger without components: only global should fire.
1182        world.resource_mut::<Order>().0.clear();
1183        world.resource_mut::<DynamicValues>().0.clear();
1184        let mut event_data: u32 = 10;
1185        let mut trigger_data: u32 = 0;
1186        // SAFETY: pointers are valid u32s matching the registered layout
1187        unsafe {
1188            world.trigger_dynamic_targets_components(
1189                event_key,
1190                target,
1191                &[],
1192                bevy_ptr::PtrMut::from(&mut event_data),
1193                bevy_ptr::PtrMut::from(&mut trigger_data),
1194            );
1195        }
1196
1197        assert_eq!(vec!["global"], world.resource::<Order>().0);
1198        assert_eq!(vec![10], world.resource::<DynamicValues>().0);
1199    }
1200
1201    #[test]
1202    fn observer_propagating() {
1203        let mut world = World::new();
1204        world.init_resource::<Order>();
1205
1206        let parent = world.spawn_empty().id();
1207        let child = world.spawn(ChildOf(parent)).id();
1208
1209        world.entity_mut(parent).observe(
1210            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1211                res.observed("parent");
1212
1213                assert_eq!(event.event_target(), parent);
1214                assert_eq!(event.original_event_target(), child);
1215            },
1216        );
1217
1218        world.entity_mut(child).observe(
1219            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1220                res.observed("child");
1221                assert_eq!(event.event_target(), child);
1222                assert_eq!(event.original_event_target(), child);
1223            },
1224        );
1225
1226        world.trigger(EventPropagating(child));
1227
1228        assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
1229    }
1230
1231    #[test]
1232    fn observer_propagating_redundant_dispatch_same_entity() {
1233        let mut world = World::new();
1234        world.init_resource::<Order>();
1235
1236        let parent = world
1237            .spawn_empty()
1238            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1239                res.observed("parent");
1240            })
1241            .id();
1242
1243        let child = world
1244            .spawn(ChildOf(parent))
1245            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1246                res.observed("child");
1247            })
1248            .id();
1249
1250        world.trigger(EventPropagating(child));
1251        world.trigger(EventPropagating(child));
1252
1253        assert_eq!(
1254            vec!["child", "parent", "child", "parent"],
1255            world.resource::<Order>().0
1256        );
1257    }
1258
1259    #[test]
1260    fn observer_propagating_redundant_dispatch_parent_child() {
1261        let mut world = World::new();
1262        world.init_resource::<Order>();
1263
1264        let parent = world
1265            .spawn_empty()
1266            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1267                res.observed("parent");
1268            })
1269            .id();
1270
1271        let child = world
1272            .spawn(ChildOf(parent))
1273            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1274                res.observed("child");
1275            })
1276            .id();
1277
1278        world.trigger(EventPropagating(child));
1279        world.trigger(EventPropagating(parent));
1280
1281        assert_eq!(
1282            vec!["child", "parent", "parent"],
1283            world.resource::<Order>().0
1284        );
1285    }
1286
1287    #[test]
1288    fn observer_propagating_halt() {
1289        let mut world = World::new();
1290        world.init_resource::<Order>();
1291
1292        let parent = world
1293            .spawn_empty()
1294            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1295                res.observed("parent");
1296            })
1297            .id();
1298
1299        let child = world
1300            .spawn(ChildOf(parent))
1301            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1302                res.observed("child");
1303                event.propagate(false);
1304            })
1305            .id();
1306
1307        world.trigger(EventPropagating(child));
1308
1309        assert_eq!(vec!["child"], world.resource::<Order>().0);
1310    }
1311
1312    #[test]
1313    fn observer_propagating_join() {
1314        let mut world = World::new();
1315        world.init_resource::<Order>();
1316
1317        let parent = world
1318            .spawn_empty()
1319            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1320                res.observed("parent");
1321            })
1322            .id();
1323
1324        let child_a = world
1325            .spawn(ChildOf(parent))
1326            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1327                res.observed("child_a");
1328            })
1329            .id();
1330
1331        let child_b = world
1332            .spawn(ChildOf(parent))
1333            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1334                res.observed("child_b");
1335            })
1336            .id();
1337
1338        world.trigger(EventPropagating(child_a));
1339        world.trigger(EventPropagating(child_b));
1340
1341        assert_eq!(
1342            vec!["child_a", "parent", "child_b", "parent"],
1343            world.resource::<Order>().0
1344        );
1345    }
1346
1347    #[test]
1348    fn observer_propagating_no_next() {
1349        let mut world = World::new();
1350        world.init_resource::<Order>();
1351
1352        let entity = world
1353            .spawn_empty()
1354            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1355                res.observed("event");
1356            })
1357            .id();
1358
1359        world.trigger(EventPropagating(entity));
1360        assert_eq!(vec!["event"], world.resource::<Order>().0);
1361    }
1362
1363    #[test]
1364    fn observer_propagating_parallel_propagation() {
1365        let mut world = World::new();
1366        world.init_resource::<Order>();
1367
1368        let parent_a = world
1369            .spawn_empty()
1370            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1371                res.observed("parent_a");
1372            })
1373            .id();
1374
1375        let child_a = world
1376            .spawn(ChildOf(parent_a))
1377            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1378                res.observed("child_a");
1379                event.propagate(false);
1380            })
1381            .id();
1382
1383        let parent_b = world
1384            .spawn_empty()
1385            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1386                res.observed("parent_b");
1387            })
1388            .id();
1389
1390        let child_b = world
1391            .spawn(ChildOf(parent_b))
1392            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1393                res.observed("child_b");
1394            })
1395            .id();
1396
1397        world.trigger(EventPropagating(child_a));
1398        world.trigger(EventPropagating(child_b));
1399
1400        assert_eq!(
1401            vec!["child_a", "child_b", "parent_b"],
1402            world.resource::<Order>().0
1403        );
1404    }
1405
1406    #[test]
1407    fn observer_propagating_world() {
1408        let mut world = World::new();
1409        world.init_resource::<Order>();
1410
1411        world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1412            res.observed("event");
1413        });
1414
1415        let grandparent = world.spawn_empty().id();
1416        let parent = world.spawn(ChildOf(grandparent)).id();
1417        let child = world.spawn(ChildOf(parent)).id();
1418
1419        world.trigger(EventPropagating(child));
1420
1421        assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
1422    }
1423
1424    #[test]
1425    fn observer_propagating_world_skipping() {
1426        let mut world = World::new();
1427        world.init_resource::<Order>();
1428
1429        world.add_observer(
1430            |event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
1431                if query.get(event.event_target()).is_ok() {
1432                    res.observed("event");
1433                }
1434            },
1435        );
1436
1437        let grandparent = world.spawn(A).id();
1438        let parent = world.spawn(ChildOf(grandparent)).id();
1439        let child = world.spawn((A, ChildOf(parent))).id();
1440
1441        world.trigger(EventPropagating(child));
1442
1443        assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
1444    }
1445
1446    // Originally for https://github.com/bevyengine/bevy/issues/18452
1447    #[test]
1448    fn observer_modifies_relationship() {
1449        fn on_add(add: On<Add<A>>, mut commands: Commands) {
1450            commands
1451                .entity(add.entity)
1452                .with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
1453                    rsc.spawn_empty();
1454                });
1455        }
1456
1457        let mut world = World::new();
1458        world.add_observer(on_add);
1459        world.spawn(A);
1460    }
1461
1462    // Regression test for https://github.com/bevyengine/bevy/issues/14467
1463    // Fails prior to https://github.com/bevyengine/bevy/pull/15398
1464    #[test]
1465    fn observer_on_remove_during_despawn_spawn_empty() {
1466        let mut world = World::new();
1467
1468        // Observe the removal of A - this will run during despawn
1469        world.add_observer(|_: On<Remove<A>>, mut cmd: Commands| {
1470            // Spawn a new entity - this reserves a new ID and requires a flush
1471            // afterward before Entities::free can be called.
1472            cmd.spawn_empty();
1473        });
1474
1475        let ent = world.spawn(A).id();
1476
1477        // Despawn our entity, which runs the Remove observer and allocates a
1478        // new Entity.
1479        // Should not panic - if it does, then Entities was not flushed properly
1480        // after the observer's spawn_empty.
1481        world.despawn(ent);
1482    }
1483
1484    #[test]
1485    #[should_panic]
1486    fn observer_invalid_params() {
1487        #[derive(Resource)]
1488        struct ResA;
1489
1490        #[derive(Resource)]
1491        struct ResB;
1492
1493        let mut world = World::new();
1494        // This fails because `ResA` is not present in the world
1495        world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
1496            commands.insert_resource(ResB);
1497        });
1498        world.trigger(EventA);
1499    }
1500
1501    #[test]
1502    fn observer_apply_deferred_from_param_set() {
1503        #[derive(Resource)]
1504        struct ResA;
1505
1506        let mut world = World::new();
1507        world.add_observer(
1508            |_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1509                params.p1().insert_resource(ResA);
1510            },
1511        );
1512
1513        world.trigger(EventA);
1514        world.flush();
1515
1516        assert!(world.get_resource::<ResA>().is_some());
1517    }
1518
1519    #[test]
1520    #[track_caller]
1521    fn observer_caller_location_event() {
1522        #[derive(Event)]
1523        struct EventA;
1524
1525        let caller = MaybeLocation::caller();
1526        let mut world = World::new();
1527        world.add_observer(move |event: On<EventA>| {
1528            assert_eq!(event.caller(), caller);
1529        });
1530        world.trigger(EventA);
1531    }
1532
1533    #[test]
1534    #[track_caller]
1535    fn observer_caller_location_command_archetype_move() {
1536        #[derive(Component)]
1537        struct Component;
1538
1539        let caller = MaybeLocation::caller();
1540        let mut world = World::new();
1541        world.add_observer(move |event: On<Add<Component>>| {
1542            assert_eq!(event.caller(), caller);
1543        });
1544        world.add_observer(move |event: On<Remove<Component>>| {
1545            assert_eq!(event.caller(), caller);
1546        });
1547        world.commands().spawn(Component).clear();
1548    }
1549
1550    #[test]
1551    fn observer_watch_entities() {
1552        let mut world = World::new();
1553        world.init_resource::<Order>();
1554        let entities = world
1555            .spawn_batch(core::iter::repeat_n((), 4))
1556            .collect::<Vec<_>>();
1557        let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1558            order.observed("a");
1559        });
1560        world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1561
1562        world.trigger(EntityEventA(entities[0]));
1563        world.trigger(EntityEventA(entities[1]));
1564        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1565        world.trigger(EntityEventA(entities[2]));
1566        world.trigger(EntityEventA(entities[3]));
1567        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1568    }
1569
1570    #[test]
1571    fn unregister_global_observer() {
1572        let mut world = World::new();
1573        let mut observer = world.add_observer(|_: On<EventA>| {});
1574        observer.remove::<Observer>();
1575        let id = observer.id();
1576        let event_key = world.event_key::<EventA>().unwrap();
1577        assert!(!world
1578            .observers
1579            .get_observers_mut(event_key)
1580            .global_observers
1581            .contains_key(&id));
1582    }
1583
1584    #[test]
1585    fn unregister_entity_observer() {
1586        let mut world = World::new();
1587        let entity = world.spawn_empty().id();
1588        let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1589        let mut observer = world.spawn(observer);
1590        observer.remove::<Observer>();
1591        let event_key = world.event_key::<EventA>().unwrap();
1592        assert!(!world
1593            .observers
1594            .get_observers_mut(event_key)
1595            .entity_observers
1596            .contains_key(&entity));
1597    }
1598
1599    #[test]
1600    fn unregister_component_observer() {
1601        let mut world = World::new();
1602        let a = world.register_component::<A>();
1603        let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1604        let mut observer = world.spawn(observer);
1605        observer.remove::<Observer>();
1606        let event_key = world.event_key::<EventA>().unwrap();
1607        assert!(!world
1608            .observers
1609            .get_observers_mut(event_key)
1610            .component_observers()
1611            .contains_key(&a));
1612    }
1613
1614    #[derive(Resource)]
1615    struct RunConditionFlag(bool);
1616
1617    #[test]
1618    fn observer_run_condition_true() {
1619        let mut world = World::new();
1620        world.insert_resource(RunConditionFlag(true));
1621        world.init_resource::<Order>();
1622
1623        world.add_observer(
1624            (|_: On<EventA>, mut order: ResMut<Order>| {
1625                order.observed("event");
1626            })
1627            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1628        );
1629
1630        world.trigger(EventA);
1631        assert_eq!(vec!["event"], world.resource::<Order>().0);
1632    }
1633
1634    #[test]
1635    fn observer_run_condition_false() {
1636        let mut world = World::new();
1637        world.insert_resource(RunConditionFlag(false));
1638        world.init_resource::<Order>();
1639
1640        world.add_observer(
1641            (|_: On<EventA>, mut order: ResMut<Order>| {
1642                order.observed("event");
1643            })
1644            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1645        );
1646
1647        world.trigger(EventA);
1648        assert!(world.resource::<Order>().0.is_empty());
1649    }
1650
1651    #[test]
1652    fn observer_run_condition_chained() {
1653        let mut world = World::new();
1654        world.insert_resource(RunConditionFlag(true));
1655        world.init_resource::<Order>();
1656
1657        #[derive(Resource)]
1658        struct SecondFlag(bool);
1659        world.insert_resource(SecondFlag(true));
1660
1661        world.add_observer(
1662            (|_: On<EventA>, mut order: ResMut<Order>| {
1663                order.observed("event");
1664            })
1665            .run_if(|flag: Res<RunConditionFlag>| flag.0)
1666            .run_if(|flag: Res<SecondFlag>| flag.0),
1667        );
1668
1669        world.trigger(EventA);
1670        assert_eq!(vec!["event"], world.resource::<Order>().0);
1671
1672        world.resource_mut::<Order>().0.clear();
1673        world.resource_mut::<SecondFlag>().0 = false;
1674        world.trigger(EventA);
1675        assert!(world.resource::<Order>().0.is_empty());
1676    }
1677
1678    #[test]
1679    fn observer_run_condition_re_evaluated() {
1680        let mut world = World::new();
1681        world.insert_resource(RunConditionFlag(false));
1682        world.init_resource::<Order>();
1683
1684        world.add_observer(
1685            (|_: On<EventA>, mut order: ResMut<Order>| {
1686                order.observed("event");
1687            })
1688            .run_if(|flag: Res<RunConditionFlag>| flag.0),
1689        );
1690
1691        world.trigger(EventA);
1692        assert!(world.resource::<Order>().0.is_empty());
1693
1694        world.resource_mut::<RunConditionFlag>().0 = true;
1695        world.trigger(EventA);
1696        assert_eq!(vec!["event"], world.resource::<Order>().0);
1697    }
1698
1699    #[test]
1700    fn observer_run_condition_result_bool() {
1701        let mut world = World::new();
1702        world.init_resource::<Order>();
1703
1704        world.add_observer(
1705            (|_: On<EventA>, mut order: ResMut<Order>| {
1706                order.observed("err");
1707            })
1708            .run_if(|| -> Result<bool> { Err(core::fmt::Error.into()) }),
1709        );
1710        world.add_observer(
1711            (|_: On<EventA>, mut order: ResMut<Order>| {
1712                order.observed("false");
1713            })
1714            .run_if(|| -> Result<bool> { Ok(false) }),
1715        );
1716        world.add_observer(
1717            (|_: On<EventA>, mut order: ResMut<Order>| {
1718                order.observed("true");
1719            })
1720            .run_if(|| -> Result<bool> { Ok(true) }),
1721        );
1722
1723        world.trigger(EventA);
1724        assert_eq!(vec!["true"], world.resource::<Order>().0);
1725    }
1726
1727    #[test]
1728    fn observer_conditions_and_change_detection() {
1729        #[derive(Resource, Default)]
1730        struct Bool2(pub bool);
1731
1732        let mut world = World::new();
1733        world.init_resource::<Order>();
1734        world.insert_resource(RunConditionFlag(false));
1735        world.insert_resource(Bool2(false));
1736
1737        world.add_observer(
1738            (|_: On<EventA>, mut order: ResMut<Order>| {
1739                order.observed("event");
1740            })
1741            .run_if(|res1: Res<RunConditionFlag>| res1.is_changed())
1742            .run_if(|res2: Res<Bool2>| res2.is_changed()),
1743        );
1744
1745        // both resources were just added.
1746        world.trigger(EventA);
1747        assert_eq!(vec!["event"], world.resource::<Order>().0);
1748
1749        // nothing has changed
1750        world.resource_mut::<Order>().0.clear();
1751        world.trigger(EventA);
1752        assert!(world.resource::<Order>().0.is_empty());
1753
1754        // RunConditionFlag has changed, but observer did not run
1755        world.resource_mut::<RunConditionFlag>().0 = true;
1756        world.trigger(EventA);
1757        assert!(world.resource::<Order>().0.is_empty());
1758
1759        // internal state for the Bool2 condition was updated in the
1760        // previous run, so observer still does not run
1761        world.resource_mut::<Bool2>().0 = true;
1762        world.trigger(EventA);
1763        assert!(world.resource::<Order>().0.is_empty());
1764
1765        // internal state for Bool2 was updated, so observer still does not run
1766        world.resource_mut::<RunConditionFlag>().0 = false;
1767        world.trigger(EventA);
1768        assert!(world.resource::<Order>().0.is_empty());
1769
1770        // now check that it works correctly changing Bool2 first and then RunConditionFlag
1771        world.resource_mut::<Bool2>().0 = false;
1772        world.resource_mut::<RunConditionFlag>().0 = true;
1773        world.trigger(EventA);
1774        assert_eq!(vec!["event"], world.resource::<Order>().0);
1775    }
1776
1777    #[test]
1778    fn entity_observer_with_run_condition() {
1779        let mut world = World::new();
1780        world.insert_resource(RunConditionFlag(true));
1781        world.init_resource::<Order>();
1782
1783        let entity = world
1784            .spawn_empty()
1785            .observe(
1786                (|_: On<EntityEventA>, mut order: ResMut<Order>| {
1787                    order.observed("entity_event");
1788                })
1789                .run_if(|flag: Res<RunConditionFlag>| flag.0),
1790            )
1791            .id();
1792
1793        world.trigger(EntityEventA(entity));
1794        assert_eq!(vec!["entity_event"], world.resource::<Order>().0);
1795
1796        world.resource_mut::<Order>().0.clear();
1797        world.resource_mut::<RunConditionFlag>().0 = false;
1798        world.trigger(EntityEventA(entity));
1799        assert!(world.resource::<Order>().0.is_empty());
1800    }
1801
1802    #[test]
1803    fn observer_builder_run_if() {
1804        let mut world = World::new();
1805        world.insert_resource(RunConditionFlag(true));
1806        world.init_resource::<Order>();
1807
1808        let observer = Observer::new(|_: On<EventA>, mut order: ResMut<Order>| {
1809            order.observed("event");
1810        })
1811        .run_if(|flag: Res<RunConditionFlag>| flag.0);
1812
1813        world.spawn(observer);
1814
1815        world.trigger(EventA);
1816        assert_eq!(vec!["event"], world.resource::<Order>().0);
1817
1818        world.resource_mut::<Order>().0.clear();
1819        world.resource_mut::<RunConditionFlag>().0 = false;
1820        world.trigger(EventA);
1821        assert!(world.resource::<Order>().0.is_empty());
1822    }
1823
1824    #[test]
1825    fn observer_new_old_archetypes() {
1826        #[derive(Resource, Default)]
1827        struct Changes(Vec<(&'static str, Option<ArchetypeId>, Option<ArchetypeId>)>);
1828
1829        let mut world = World::new();
1830        world.init_resource::<Changes>();
1831
1832        fn observer<E>(e: On<E>, mut c: ResMut<Changes>)
1833        where
1834            E: EventPattern,
1835            E::Event: for<'a> Event<Trigger<'a> = EntityComponentsTrigger<'a>>,
1836        {
1837            c.0.push((
1838                type_name::<E::Event>(),
1839                e.trigger().old_archetype.map(Archetype::id),
1840                e.trigger().new_archetype.map(Archetype::id),
1841            ));
1842        }
1843
1844        let empty = world.spawn(()).archetype().id();
1845        let a = world.spawn(A).archetype().id();
1846        let ab = world.spawn((A, B)).archetype().id();
1847
1848        world.add_observer(observer::<Add<A>>);
1849        world.add_observer(observer::<Insert<A>>);
1850        world.add_observer(observer::<Discard<A>>);
1851        world.add_observer(observer::<Remove<A>>);
1852        world.add_observer(observer::<Despawn<A>>);
1853
1854        let mut entity = world.spawn((A, B));
1855        entity.remove::<(A, B)>();
1856        entity.insert(A);
1857        entity.insert(A);
1858        entity.despawn();
1859
1860        assert_eq!(
1861            &world.resource_mut::<Changes>().0,
1862            &[
1863                ("bevy_ecs::lifecycle::AddEvent", None, Some(ab)),
1864                ("bevy_ecs::lifecycle::InsertEvent", None, Some(ab)),
1865                ("bevy_ecs::lifecycle::DiscardEvent", Some(ab), Some(empty)),
1866                ("bevy_ecs::lifecycle::RemoveEvent", Some(ab), Some(empty)),
1867                ("bevy_ecs::lifecycle::AddEvent", Some(empty), Some(a)),
1868                ("bevy_ecs::lifecycle::InsertEvent", Some(empty), Some(a)),
1869                ("bevy_ecs::lifecycle::DiscardEvent", Some(a), Some(a)),
1870                ("bevy_ecs::lifecycle::InsertEvent", Some(a), Some(a)),
1871                ("bevy_ecs::lifecycle::DespawnEvent", Some(a), None),
1872                ("bevy_ecs::lifecycle::DiscardEvent", Some(a), None),
1873                ("bevy_ecs::lifecycle::RemoveEvent", Some(a), None),
1874            ],
1875        );
1876    }
1877
1878    #[test]
1879    fn despawning_observer_removes_observed_by() {
1880        let mut world = World::new();
1881
1882        #[derive(EntityEvent)]
1883        struct Hi {
1884            entity: Entity,
1885        }
1886
1887        let target = world.spawn_empty().id();
1888        let observer = world
1889            .spawn(Observer::new(|_: On<Hi>| {}).with_entity(target))
1890            .id();
1891
1892        assert_eq!(
1893            world.entity(target).get::<ObservedBy>().unwrap().get(),
1894            &[observer]
1895        );
1896
1897        world.entity_mut(observer).despawn();
1898
1899        assert!(!world.entity(target).contains::<ObservedBy>());
1900    }
1901
1902    #[test]
1903    fn despawning_observer_removes_observed_by_repeated() {
1904        let mut world = World::new();
1905
1906        #[derive(EntityEvent)]
1907        struct Hi {
1908            entity: Entity,
1909        }
1910
1911        let target = world.spawn_empty().id();
1912        let observer = world
1913            // Observe the same entity multiple times.
1914            .spawn(Observer::new(|_: On<Hi>| {}).with_entities([target, target]))
1915            .id();
1916
1917        // Having an observer observe the same entity multiple times is likely not desired, but
1918        // preventing this is not worth it, so make sure it behaves correctly.
1919        assert_eq!(
1920            world.entity(target).get::<ObservedBy>().unwrap().get(),
1921            &[observer, observer]
1922        );
1923
1924        world.entity_mut(observer).despawn();
1925
1926        assert!(!world.entity(target).contains::<ObservedBy>());
1927    }
1928
1929    #[test]
1930    fn observer_system_despawns_observer() {
1931        let mut world = World::new();
1932        world.add_observer(DespawnObserversOnInit(0));
1933
1934        use crate::change_detection::{CheckChangeTicks, Tick};
1935        use crate::system::{RunSystemError, SystemAccess, SystemStateFlags};
1936        use crate::world::unsafe_world_cell::UnsafeWorldCell;
1937        use bevy_utils::prelude::DebugName;
1938
1939        #[expect(unused, reason = "This will only trigger UB if it has nonzero size")]
1940        struct DespawnObserversOnInit(usize);
1941        impl System for DespawnObserversOnInit {
1942            type In = On<'static, 'static, Add<()>>;
1943
1944            type Out = ();
1945
1946            fn name(&self) -> DebugName {
1947                DebugName::type_name::<DespawnObserversOnInit>()
1948            }
1949
1950            fn flags(&self) -> SystemStateFlags {
1951                SystemStateFlags::empty()
1952            }
1953
1954            unsafe fn run_unsafe(
1955                &mut self,
1956                _input: SystemIn<'_, Self>,
1957                _world: UnsafeWorldCell,
1958            ) -> Result<Self::Out, RunSystemError> {
1959                Ok(())
1960            }
1961
1962            #[cfg(feature = "hotpatching")]
1963            fn refresh_hotpatch(&mut self) {}
1964
1965            fn apply_deferred(&mut self, _world: &mut World) {}
1966
1967            fn queue_deferred(&mut self, _world: DeferredWorld) {
1968                todo!()
1969            }
1970
1971            fn initialize(&mut self, world: &mut World) -> SystemAccess {
1972                let observers: Vec<_> = world
1973                    .query_filtered::<Entity, With<Observer>>()
1974                    .query(world)
1975                    .iter()
1976                    .collect();
1977                for observer in observers {
1978                    world.despawn(observer);
1979                }
1980
1981                SystemAccess::None
1982            }
1983
1984            fn check_change_tick(&mut self, _check: CheckChangeTicks) {}
1985
1986            fn get_last_run(&self) -> Tick {
1987                unimplemented!()
1988            }
1989
1990            fn set_last_run(&mut self, _last_run: Tick) {}
1991        }
1992    }
1993}