bevy_ecs/observer/
mod.rs

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