bevy_ecs/observer/
mod.rs

1//! Types for creating and storing [`Observer`]s
2
3mod entity_observer;
4mod runner;
5mod trigger_event;
6
7pub use runner::*;
8pub use trigger_event::*;
9
10use crate::{
11    archetype::ArchetypeFlags,
12    component::ComponentId,
13    entity::EntityHashMap,
14    observer::entity_observer::ObservedBy,
15    prelude::*,
16    system::IntoObserverSystem,
17    world::{DeferredWorld, *},
18};
19use bevy_ptr::Ptr;
20use bevy_utils::HashMap;
21use core::{
22    fmt::Debug,
23    marker::PhantomData,
24    ops::{Deref, DerefMut},
25};
26use smallvec::SmallVec;
27
28/// Type containing triggered [`Event`] information for a given run of an [`Observer`]. This contains the
29/// [`Event`] data itself. If it was triggered for a specific [`Entity`], it includes that as well. It also
30/// contains event propagation information. See [`Trigger::propagate`] for more information.
31pub struct Trigger<'w, E, B: Bundle = ()> {
32    event: &'w mut E,
33    propagate: &'w mut bool,
34    trigger: ObserverTrigger,
35    _marker: PhantomData<B>,
36}
37
38impl<'w, E, B: Bundle> Trigger<'w, E, B> {
39    /// Creates a new trigger for the given event and observer information.
40    pub fn new(event: &'w mut E, propagate: &'w mut bool, trigger: ObserverTrigger) -> Self {
41        Self {
42            event,
43            propagate,
44            trigger,
45            _marker: PhantomData,
46        }
47    }
48
49    /// Returns the event type of this trigger.
50    pub fn event_type(&self) -> ComponentId {
51        self.trigger.event_type
52    }
53
54    /// Returns a reference to the triggered event.
55    pub fn event(&self) -> &E {
56        self.event
57    }
58
59    /// Returns a mutable reference to the triggered event.
60    pub fn event_mut(&mut self) -> &mut E {
61        self.event
62    }
63
64    /// Returns a pointer to the triggered event.
65    pub fn event_ptr(&self) -> Ptr {
66        Ptr::from(&self.event)
67    }
68
69    /// Returns the [`Entity`] that triggered the observer, could be [`Entity::PLACEHOLDER`].
70    pub fn entity(&self) -> Entity {
71        self.trigger.entity
72    }
73
74    /// Returns the components that triggered the observer, out of the
75    /// components defined in `B`. Does not necessarily include all of them as
76    /// `B` acts like an `OR` filter rather than an `AND` filter.
77    pub fn components(&self) -> &[ComponentId] {
78        &self.trigger.components
79    }
80
81    /// Returns the [`Entity`] that observed the triggered event.
82    /// This allows you to despawn the observer, ceasing observation.
83    ///
84    /// # Examples
85    ///
86    /// ```rust
87    /// # use bevy_ecs::prelude::{Commands, Trigger};
88    /// #
89    /// # struct MyEvent {
90    /// #   done: bool,
91    /// # }
92    /// #
93    /// /// Handle `MyEvent` and if it is done, stop observation.
94    /// fn my_observer(trigger: Trigger<MyEvent>, mut commands: Commands) {
95    ///     if trigger.event().done {
96    ///         commands.entity(trigger.observer()).despawn();
97    ///         return;
98    ///     }
99    ///
100    ///     // ...
101    /// }
102    /// ```
103    pub fn observer(&self) -> Entity {
104        self.trigger.observer
105    }
106
107    /// Enables or disables event propagation, allowing the same event to trigger observers on a chain of different entities.
108    ///
109    /// The path an event will propagate along is specified by its associated [`Traversal`] component. By default, events
110    /// use `()` which ends the path immediately and prevents propagation.
111    ///
112    /// To enable propagation, you must:
113    /// + Set [`Event::Traversal`] to the component you want to propagate along.
114    /// + Either call `propagate(true)` in the first observer or set [`Event::AUTO_PROPAGATE`] to `true`.
115    ///
116    /// You can prevent an event from propagating further using `propagate(false)`.
117    ///
118    /// [`Traversal`]: crate::traversal::Traversal
119    pub fn propagate(&mut self, should_propagate: bool) {
120        *self.propagate = should_propagate;
121    }
122
123    /// Returns the value of the flag that controls event propagation. See [`propagate`] for more information.
124    ///
125    /// [`propagate`]: Trigger::propagate
126    pub fn get_propagate(&self) -> bool {
127        *self.propagate
128    }
129}
130
131impl<'w, E: Debug, B: Bundle> Debug for Trigger<'w, E, B> {
132    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
133        f.debug_struct("Trigger")
134            .field("event", &self.event)
135            .field("propagate", &self.propagate)
136            .field("trigger", &self.trigger)
137            .field("_marker", &self._marker)
138            .finish()
139    }
140}
141
142impl<'w, E, B: Bundle> Deref for Trigger<'w, E, B> {
143    type Target = E;
144
145    fn deref(&self) -> &Self::Target {
146        self.event
147    }
148}
149
150impl<'w, E, B: Bundle> DerefMut for Trigger<'w, E, B> {
151    fn deref_mut(&mut self) -> &mut Self::Target {
152        self.event
153    }
154}
155
156/// A description of what an [`Observer`] observes.
157#[derive(Default, Clone)]
158pub struct ObserverDescriptor {
159    /// The events the observer is watching.
160    events: Vec<ComponentId>,
161
162    /// The components the observer is watching.
163    components: Vec<ComponentId>,
164
165    /// The entities the observer is watching.
166    entities: Vec<Entity>,
167}
168
169impl ObserverDescriptor {
170    /// Add the given `events` to the descriptor.
171    /// # Safety
172    /// The type of each [`ComponentId`] in `events` _must_ match the actual value
173    /// of the event passed into the observer.
174    pub unsafe fn with_events(mut self, events: Vec<ComponentId>) -> Self {
175        self.events = events;
176        self
177    }
178
179    /// Add the given `components` to the descriptor.
180    pub fn with_components(mut self, components: Vec<ComponentId>) -> Self {
181        self.components = components;
182        self
183    }
184
185    /// Add the given `entities` to the descriptor.
186    pub fn with_entities(mut self, entities: Vec<Entity>) -> Self {
187        self.entities = entities;
188        self
189    }
190
191    pub(crate) fn merge(&mut self, descriptor: &ObserverDescriptor) {
192        self.events.extend(descriptor.events.iter().copied());
193        self.components
194            .extend(descriptor.components.iter().copied());
195        self.entities.extend(descriptor.entities.iter().copied());
196    }
197}
198
199/// Event trigger metadata for a given [`Observer`],
200#[derive(Debug)]
201pub struct ObserverTrigger {
202    /// The [`Entity`] of the observer handling the trigger.
203    pub observer: Entity,
204    /// The [`Event`] the trigger targeted.
205    pub event_type: ComponentId,
206    /// The [`ComponentId`]s the trigger targeted.
207    components: SmallVec<[ComponentId; 2]>,
208    /// The entity the trigger targeted.
209    pub entity: Entity,
210}
211
212impl ObserverTrigger {
213    /// Returns the components that the trigger targeted.
214    pub fn components(&self) -> &[ComponentId] {
215        &self.components
216    }
217}
218
219// Map between an observer entity and its runner
220type ObserverMap = EntityHashMap<ObserverRunner>;
221
222/// Collection of [`ObserverRunner`] for [`Observer`] registered to a particular trigger targeted at a specific component.
223#[derive(Default, Debug)]
224pub struct CachedComponentObservers {
225    // Observers listening to triggers targeting this component
226    map: ObserverMap,
227    // Observers listening to triggers targeting this component on a specific entity
228    entity_map: EntityHashMap<ObserverMap>,
229}
230
231/// Collection of [`ObserverRunner`] for [`Observer`] registered to a particular trigger.
232#[derive(Default, Debug)]
233pub struct CachedObservers {
234    // Observers listening for any time this trigger is fired
235    map: ObserverMap,
236    // Observers listening for this trigger fired at a specific component
237    component_observers: HashMap<ComponentId, CachedComponentObservers>,
238    // Observers listening for this trigger fired at a specific entity
239    entity_observers: EntityHashMap<ObserverMap>,
240}
241
242/// Metadata for observers. Stores a cache mapping trigger ids to the registered observers.
243#[derive(Default, Debug)]
244pub struct Observers {
245    // Cached ECS observers to save a lookup most common triggers.
246    on_add: CachedObservers,
247    on_insert: CachedObservers,
248    on_replace: CachedObservers,
249    on_remove: CachedObservers,
250    // Map from trigger type to set of observers
251    cache: HashMap<ComponentId, CachedObservers>,
252}
253
254impl Observers {
255    pub(crate) fn get_observers(&mut self, event_type: ComponentId) -> &mut CachedObservers {
256        match event_type {
257            ON_ADD => &mut self.on_add,
258            ON_INSERT => &mut self.on_insert,
259            ON_REPLACE => &mut self.on_replace,
260            ON_REMOVE => &mut self.on_remove,
261            _ => self.cache.entry(event_type).or_default(),
262        }
263    }
264
265    pub(crate) fn try_get_observers(&self, event_type: ComponentId) -> Option<&CachedObservers> {
266        match event_type {
267            ON_ADD => Some(&self.on_add),
268            ON_INSERT => Some(&self.on_insert),
269            ON_REPLACE => Some(&self.on_replace),
270            ON_REMOVE => Some(&self.on_remove),
271            _ => self.cache.get(&event_type),
272        }
273    }
274
275    /// This will run the observers of the given `event_type`, targeting the given `entity` and `components`.
276    pub(crate) fn invoke<T>(
277        mut world: DeferredWorld,
278        event_type: ComponentId,
279        entity: Entity,
280        components: impl Iterator<Item = ComponentId> + Clone,
281        data: &mut T,
282        propagate: &mut bool,
283    ) {
284        // SAFETY: You cannot get a mutable reference to `observers` from `DeferredWorld`
285        let (mut world, observers) = unsafe {
286            let world = world.as_unsafe_world_cell();
287            // SAFETY: There are no outstanding world references
288            world.increment_trigger_id();
289            let observers = world.observers();
290            let Some(observers) = observers.try_get_observers(event_type) else {
291                return;
292            };
293            // SAFETY: The only outstanding reference to world is `observers`
294            (world.into_deferred(), observers)
295        };
296
297        let trigger_for_components = components.clone();
298
299        let mut trigger_observer = |(&observer, runner): (&Entity, &ObserverRunner)| {
300            (runner)(
301                world.reborrow(),
302                ObserverTrigger {
303                    observer,
304                    event_type,
305                    components: components.clone().collect(),
306                    entity,
307                },
308                data.into(),
309                propagate,
310            );
311        };
312        // Trigger observers listening for any kind of this trigger
313        observers.map.iter().for_each(&mut trigger_observer);
314
315        // Trigger entity observers listening for this kind of trigger
316        if entity != Entity::PLACEHOLDER {
317            if let Some(map) = observers.entity_observers.get(&entity) {
318                map.iter().for_each(&mut trigger_observer);
319            }
320        }
321
322        // Trigger observers listening to this trigger targeting a specific component
323        trigger_for_components.for_each(|id| {
324            if let Some(component_observers) = observers.component_observers.get(&id) {
325                component_observers
326                    .map
327                    .iter()
328                    .for_each(&mut trigger_observer);
329
330                if entity != Entity::PLACEHOLDER {
331                    if let Some(map) = component_observers.entity_map.get(&entity) {
332                        map.iter().for_each(&mut trigger_observer);
333                    }
334                }
335            }
336        });
337    }
338
339    pub(crate) fn is_archetype_cached(event_type: ComponentId) -> Option<ArchetypeFlags> {
340        match event_type {
341            ON_ADD => Some(ArchetypeFlags::ON_ADD_OBSERVER),
342            ON_INSERT => Some(ArchetypeFlags::ON_INSERT_OBSERVER),
343            ON_REPLACE => Some(ArchetypeFlags::ON_REPLACE_OBSERVER),
344            ON_REMOVE => Some(ArchetypeFlags::ON_REMOVE_OBSERVER),
345            _ => None,
346        }
347    }
348
349    pub(crate) fn update_archetype_flags(
350        &self,
351        component_id: ComponentId,
352        flags: &mut ArchetypeFlags,
353    ) {
354        if self.on_add.component_observers.contains_key(&component_id) {
355            flags.insert(ArchetypeFlags::ON_ADD_OBSERVER);
356        }
357
358        if self
359            .on_insert
360            .component_observers
361            .contains_key(&component_id)
362        {
363            flags.insert(ArchetypeFlags::ON_INSERT_OBSERVER);
364        }
365
366        if self
367            .on_replace
368            .component_observers
369            .contains_key(&component_id)
370        {
371            flags.insert(ArchetypeFlags::ON_REPLACE_OBSERVER);
372        }
373
374        if self
375            .on_remove
376            .component_observers
377            .contains_key(&component_id)
378        {
379            flags.insert(ArchetypeFlags::ON_REMOVE_OBSERVER);
380        }
381    }
382}
383
384impl World {
385    /// Spawns a "global" [`Observer`] which will watch for the given event.
386    /// Returns its [`Entity`] as a [`EntityWorldMut`].
387    ///
388    /// **Calling [`observe`](EntityWorldMut::observe) on the returned
389    /// [`EntityWorldMut`] will observe the observer itself, which you very
390    /// likely do not want.**
391    ///
392    /// # Example
393    ///
394    /// ```
395    /// # use bevy_ecs::prelude::*;
396    /// #[derive(Component)]
397    /// struct A;
398    ///
399    /// # let mut world = World::new();
400    /// world.add_observer(|_: Trigger<OnAdd, A>| {
401    ///     // ...
402    /// });
403    /// world.add_observer(|_: Trigger<OnRemove, A>| {
404    ///     // ...
405    /// });
406    /// ```
407    pub fn add_observer<E: Event, B: Bundle, M>(
408        &mut self,
409        system: impl IntoObserverSystem<E, B, M>,
410    ) -> EntityWorldMut {
411        self.spawn(Observer::new(system))
412    }
413
414    /// Triggers the given [`Event`], which will run any [`Observer`]s watching for it.
415    ///
416    /// While event types commonly implement [`Copy`],
417    /// those that don't will be consumed and will no longer be accessible.
418    /// If you need to use the event after triggering it, use [`World::trigger_ref`] instead.
419    pub fn trigger(&mut self, event: impl Event) {
420        TriggerEvent { event, targets: () }.trigger(self);
421    }
422
423    /// Triggers the given [`Event`] as a mutable reference, which will run any [`Observer`]s watching for it.
424    ///
425    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
426    /// or use the event after it has been modified by observers.
427    pub fn trigger_ref(&mut self, event: &mut impl Event) {
428        TriggerEvent { event, targets: () }.trigger_ref(self);
429    }
430
431    /// Triggers the given [`Event`] for the given `targets`, which will run any [`Observer`]s watching for it.
432    ///
433    /// While event types commonly implement [`Copy`],
434    /// those that don't will be consumed and will no longer be accessible.
435    /// If you need to use the event after triggering it, use [`World::trigger_targets_ref`] instead.
436    pub fn trigger_targets(&mut self, event: impl Event, targets: impl TriggerTargets) {
437        TriggerEvent { event, targets }.trigger(self);
438    }
439
440    /// Triggers the given [`Event`] as a mutable reference for the given `targets`,
441    /// which will run any [`Observer`]s watching for it.
442    ///
443    /// Compared to [`World::trigger_targets`], this method is most useful when it's necessary to check
444    /// or use the event after it has been modified by observers.
445    pub fn trigger_targets_ref(&mut self, event: &mut impl Event, targets: impl TriggerTargets) {
446        TriggerEvent { event, targets }.trigger_ref(self);
447    }
448
449    /// Register an observer to the cache, called when an observer is created
450    pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
451        // SAFETY: References do not alias.
452        let (observer_state, archetypes, observers) = unsafe {
453            let observer_state: *const ObserverState =
454                self.get::<ObserverState>(observer_entity).unwrap();
455            // Populate ObservedBy for each observed entity.
456            for watched_entity in &(*observer_state).descriptor.entities {
457                let mut entity_mut = self.entity_mut(*watched_entity);
458                let mut observed_by = entity_mut.entry::<ObservedBy>().or_default();
459                observed_by.0.push(observer_entity);
460            }
461            (&*observer_state, &mut self.archetypes, &mut self.observers)
462        };
463        let descriptor = &observer_state.descriptor;
464
465        for &event_type in &descriptor.events {
466            let cache = observers.get_observers(event_type);
467
468            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
469                cache.map.insert(observer_entity, observer_state.runner);
470            } else if descriptor.components.is_empty() {
471                // Observer is not targeting any components so register it as an entity observer
472                for &watched_entity in &observer_state.descriptor.entities {
473                    let map = cache.entity_observers.entry(watched_entity).or_default();
474                    map.insert(observer_entity, observer_state.runner);
475                }
476            } else {
477                // Register observer for each watched component
478                for &component in &descriptor.components {
479                    let observers =
480                        cache
481                            .component_observers
482                            .entry(component)
483                            .or_insert_with(|| {
484                                if let Some(flag) = Observers::is_archetype_cached(event_type) {
485                                    archetypes.update_flags(component, flag, true);
486                                }
487                                CachedComponentObservers::default()
488                            });
489                    if descriptor.entities.is_empty() {
490                        // Register for all triggers targeting the component
491                        observers.map.insert(observer_entity, observer_state.runner);
492                    } else {
493                        // Register for each watched entity
494                        for &watched_entity in &descriptor.entities {
495                            let map = observers.entity_map.entry(watched_entity).or_default();
496                            map.insert(observer_entity, observer_state.runner);
497                        }
498                    }
499                }
500            }
501        }
502    }
503
504    /// Remove the observer from the cache, called when an observer gets despawned
505    pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
506        let archetypes = &mut self.archetypes;
507        let observers = &mut self.observers;
508
509        for &event_type in &descriptor.events {
510            let cache = observers.get_observers(event_type);
511            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
512                cache.map.remove(&entity);
513            } else if descriptor.components.is_empty() {
514                for watched_entity in &descriptor.entities {
515                    // This check should be unnecessary since this observer hasn't been unregistered yet
516                    let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
517                        continue;
518                    };
519                    observers.remove(&entity);
520                    if observers.is_empty() {
521                        cache.entity_observers.remove(watched_entity);
522                    }
523                }
524            } else {
525                for component in &descriptor.components {
526                    let Some(observers) = cache.component_observers.get_mut(component) else {
527                        continue;
528                    };
529                    if descriptor.entities.is_empty() {
530                        observers.map.remove(&entity);
531                    } else {
532                        for watched_entity in &descriptor.entities {
533                            let Some(map) = observers.entity_map.get_mut(watched_entity) else {
534                                continue;
535                            };
536                            map.remove(&entity);
537                            if map.is_empty() {
538                                observers.entity_map.remove(watched_entity);
539                            }
540                        }
541                    }
542
543                    if observers.map.is_empty() && observers.entity_map.is_empty() {
544                        cache.component_observers.remove(component);
545                        if let Some(flag) = Observers::is_archetype_cached(event_type) {
546                            if let Some(by_component) = archetypes.by_component.get(component) {
547                                for archetype in by_component.keys() {
548                                    let archetype = &mut archetypes.archetypes[archetype.index()];
549                                    if archetype.contains(*component) {
550                                        let no_longer_observed = archetype
551                                            .components()
552                                            .all(|id| !cache.component_observers.contains_key(&id));
553
554                                        if no_longer_observed {
555                                            archetype.flags.set(flag, false);
556                                        }
557                                    }
558                                }
559                            }
560                        }
561                    }
562                }
563            }
564        }
565    }
566}
567
568#[cfg(test)]
569mod tests {
570    use alloc::vec;
571
572    use bevy_ptr::OwningPtr;
573    use bevy_utils::HashMap;
574
575    use crate as bevy_ecs;
576    use crate::component::ComponentId;
577    use crate::{
578        observer::{EmitDynamicTrigger, Observer, ObserverDescriptor, ObserverState, OnReplace},
579        prelude::*,
580        traversal::Traversal,
581    };
582
583    #[derive(Component)]
584    struct A;
585
586    #[derive(Component)]
587    struct B;
588
589    #[derive(Component)]
590    struct C;
591
592    #[derive(Component)]
593    #[component(storage = "SparseSet")]
594    struct S;
595
596    #[derive(Event)]
597    struct EventA;
598
599    #[derive(Event)]
600    struct EventWithData {
601        counter: usize,
602    }
603
604    #[derive(Resource, Default)]
605    struct Order(Vec<&'static str>);
606
607    impl Order {
608        #[track_caller]
609        fn observed(&mut self, name: &'static str) {
610            self.0.push(name);
611        }
612    }
613
614    #[derive(Component)]
615    struct Parent(Entity);
616
617    impl Traversal for &'_ Parent {
618        fn traverse(item: Self::Item<'_>) -> Option<Entity> {
619            Some(item.0)
620        }
621    }
622
623    #[derive(Component)]
624    struct EventPropagating;
625
626    impl Event for EventPropagating {
627        type Traversal = &'static Parent;
628
629        const AUTO_PROPAGATE: bool = true;
630    }
631
632    #[test]
633    fn observer_order_spawn_despawn() {
634        let mut world = World::new();
635        world.init_resource::<Order>();
636
637        world.add_observer(|_: Trigger<OnAdd, A>, mut res: ResMut<Order>| res.observed("add"));
638        world
639            .add_observer(|_: Trigger<OnInsert, A>, mut res: ResMut<Order>| res.observed("insert"));
640        world.add_observer(|_: Trigger<OnReplace, A>, mut res: ResMut<Order>| {
641            res.observed("replace");
642        });
643        world
644            .add_observer(|_: Trigger<OnRemove, A>, mut res: ResMut<Order>| res.observed("remove"));
645
646        let entity = world.spawn(A).id();
647        world.despawn(entity);
648        assert_eq!(
649            vec!["add", "insert", "replace", "remove"],
650            world.resource::<Order>().0
651        );
652    }
653
654    #[test]
655    fn observer_order_insert_remove() {
656        let mut world = World::new();
657        world.init_resource::<Order>();
658
659        world.add_observer(|_: Trigger<OnAdd, A>, mut res: ResMut<Order>| res.observed("add"));
660        world
661            .add_observer(|_: Trigger<OnInsert, A>, mut res: ResMut<Order>| res.observed("insert"));
662        world.add_observer(|_: Trigger<OnReplace, A>, mut res: ResMut<Order>| {
663            res.observed("replace");
664        });
665        world
666            .add_observer(|_: Trigger<OnRemove, A>, mut res: ResMut<Order>| res.observed("remove"));
667
668        let mut entity = world.spawn_empty();
669        entity.insert(A);
670        entity.remove::<A>();
671        entity.flush();
672        assert_eq!(
673            vec!["add", "insert", "replace", "remove"],
674            world.resource::<Order>().0
675        );
676    }
677
678    #[test]
679    fn observer_order_insert_remove_sparse() {
680        let mut world = World::new();
681        world.init_resource::<Order>();
682
683        world.add_observer(|_: Trigger<OnAdd, S>, mut res: ResMut<Order>| res.observed("add"));
684        world
685            .add_observer(|_: Trigger<OnInsert, S>, mut res: ResMut<Order>| res.observed("insert"));
686        world.add_observer(|_: Trigger<OnReplace, S>, mut res: ResMut<Order>| {
687            res.observed("replace");
688        });
689        world
690            .add_observer(|_: Trigger<OnRemove, S>, mut res: ResMut<Order>| res.observed("remove"));
691
692        let mut entity = world.spawn_empty();
693        entity.insert(S);
694        entity.remove::<S>();
695        entity.flush();
696        assert_eq!(
697            vec!["add", "insert", "replace", "remove"],
698            world.resource::<Order>().0
699        );
700    }
701
702    #[test]
703    fn observer_order_replace() {
704        let mut world = World::new();
705        world.init_resource::<Order>();
706
707        let entity = world.spawn(A).id();
708
709        world.add_observer(|_: Trigger<OnAdd, A>, mut res: ResMut<Order>| res.observed("add"));
710        world
711            .add_observer(|_: Trigger<OnInsert, A>, mut res: ResMut<Order>| res.observed("insert"));
712        world.add_observer(|_: Trigger<OnReplace, A>, mut res: ResMut<Order>| {
713            res.observed("replace");
714        });
715        world
716            .add_observer(|_: Trigger<OnRemove, A>, mut res: ResMut<Order>| res.observed("remove"));
717
718        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
719        // and therefore does not automatically flush.
720        world.flush();
721
722        let mut entity = world.entity_mut(entity);
723        entity.insert(A);
724        entity.flush();
725        assert_eq!(vec!["replace", "insert"], world.resource::<Order>().0);
726    }
727
728    #[test]
729    fn observer_order_recursive() {
730        let mut world = World::new();
731        world.init_resource::<Order>();
732        world.add_observer(
733            |obs: Trigger<OnAdd, A>, mut res: ResMut<Order>, mut commands: Commands| {
734                res.observed("add_a");
735                commands.entity(obs.entity()).insert(B);
736            },
737        );
738        world.add_observer(
739            |obs: Trigger<OnRemove, A>, mut res: ResMut<Order>, mut commands: Commands| {
740                res.observed("remove_a");
741                commands.entity(obs.entity()).remove::<B>();
742            },
743        );
744
745        world.add_observer(
746            |obs: Trigger<OnAdd, B>, mut res: ResMut<Order>, mut commands: Commands| {
747                res.observed("add_b");
748                commands.entity(obs.entity()).remove::<A>();
749            },
750        );
751        world.add_observer(|_: Trigger<OnRemove, B>, mut res: ResMut<Order>| {
752            res.observed("remove_b");
753        });
754
755        let entity = world.spawn(A).flush();
756        let entity = world.get_entity(entity).unwrap();
757        assert!(!entity.contains::<A>());
758        assert!(!entity.contains::<B>());
759        assert_eq!(
760            vec!["add_a", "add_b", "remove_a", "remove_b"],
761            world.resource::<Order>().0
762        );
763    }
764
765    #[test]
766    fn observer_trigger_ref() {
767        let mut world = World::new();
768
769        world.add_observer(|mut trigger: Trigger<EventWithData>| trigger.event_mut().counter += 1);
770        world.add_observer(|mut trigger: Trigger<EventWithData>| trigger.event_mut().counter += 2);
771        world.add_observer(|mut trigger: Trigger<EventWithData>| trigger.event_mut().counter += 4);
772        // This flush is required for the last observer to be called when triggering the event,
773        // due to `World::add_observer` returning `WorldEntityMut`.
774        world.flush();
775
776        let mut event = EventWithData { counter: 0 };
777        world.trigger_ref(&mut event);
778        assert_eq!(7, event.counter);
779    }
780
781    #[test]
782    fn observer_trigger_targets_ref() {
783        let mut world = World::new();
784
785        world.add_observer(|mut trigger: Trigger<EventWithData, A>| {
786            trigger.event_mut().counter += 1;
787        });
788        world.add_observer(|mut trigger: Trigger<EventWithData, B>| {
789            trigger.event_mut().counter += 2;
790        });
791        world.add_observer(|mut trigger: Trigger<EventWithData, A>| {
792            trigger.event_mut().counter += 4;
793        });
794        // This flush is required for the last observer to be called when triggering the event,
795        // due to `World::add_observer` returning `WorldEntityMut`.
796        world.flush();
797
798        let mut event = EventWithData { counter: 0 };
799        let component_a = world.register_component::<A>();
800        world.trigger_targets_ref(&mut event, component_a);
801        assert_eq!(5, event.counter);
802    }
803
804    #[test]
805    fn observer_multiple_listeners() {
806        let mut world = World::new();
807        world.init_resource::<Order>();
808
809        world.add_observer(|_: Trigger<OnAdd, A>, mut res: ResMut<Order>| res.observed("add_1"));
810        world.add_observer(|_: Trigger<OnAdd, A>, mut res: ResMut<Order>| res.observed("add_2"));
811
812        world.spawn(A).flush();
813        assert_eq!(vec!["add_1", "add_2"], world.resource::<Order>().0);
814        // Our A entity plus our two observers
815        assert_eq!(world.entities().len(), 3);
816    }
817
818    #[test]
819    fn observer_multiple_events() {
820        let mut world = World::new();
821        world.init_resource::<Order>();
822        let on_remove = world.register_component::<OnRemove>();
823        world.spawn(
824            // SAFETY: OnAdd and OnRemove are both unit types, so this is safe
825            unsafe {
826                Observer::new(|_: Trigger<OnAdd, A>, mut res: ResMut<Order>| {
827                    res.observed("add/remove");
828                })
829                .with_event(on_remove)
830            },
831        );
832
833        let entity = world.spawn(A).id();
834        world.despawn(entity);
835        assert_eq!(
836            vec!["add/remove", "add/remove"],
837            world.resource::<Order>().0
838        );
839    }
840
841    #[test]
842    fn observer_multiple_components() {
843        let mut world = World::new();
844        world.init_resource::<Order>();
845        world.register_component::<A>();
846        world.register_component::<B>();
847
848        world.add_observer(|_: Trigger<OnAdd, (A, B)>, mut res: ResMut<Order>| {
849            res.observed("add_ab");
850        });
851
852        let entity = world.spawn(A).id();
853        world.entity_mut(entity).insert(B);
854        world.flush();
855        assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
856    }
857
858    #[test]
859    fn observer_despawn() {
860        let mut world = World::new();
861
862        let observer = world
863            .add_observer(|_: Trigger<OnAdd, A>| {
864                panic!("Observer triggered after being despawned.")
865            })
866            .id();
867        world.despawn(observer);
868        world.spawn(A).flush();
869    }
870
871    // Regression test for https://github.com/bevyengine/bevy/issues/14961
872    #[test]
873    fn observer_despawn_archetype_flags() {
874        let mut world = World::new();
875        world.init_resource::<Order>();
876
877        let entity = world.spawn((A, B)).flush();
878
879        world.add_observer(|_: Trigger<OnRemove, A>, mut res: ResMut<Order>| {
880            res.observed("remove_a");
881        });
882
883        let observer = world
884            .add_observer(|_: Trigger<OnRemove, B>| {
885                panic!("Observer triggered after being despawned.")
886            })
887            .flush();
888        world.despawn(observer);
889
890        world.despawn(entity);
891
892        assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
893    }
894
895    #[test]
896    fn observer_multiple_matches() {
897        let mut world = World::new();
898        world.init_resource::<Order>();
899
900        world.add_observer(|_: Trigger<OnAdd, (A, B)>, mut res: ResMut<Order>| {
901            res.observed("add_ab");
902        });
903
904        world.spawn((A, B)).flush();
905        assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
906    }
907
908    #[test]
909    fn observer_no_target() {
910        let mut world = World::new();
911        world.init_resource::<Order>();
912
913        world
914            .spawn_empty()
915            .observe(|_: Trigger<EventA>| panic!("Trigger routed to non-targeted entity."));
916        world.add_observer(move |obs: Trigger<EventA>, mut res: ResMut<Order>| {
917            assert_eq!(obs.entity(), Entity::PLACEHOLDER);
918            res.observed("event_a");
919        });
920
921        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
922        // and therefore does not automatically flush.
923        world.flush();
924        world.trigger(EventA);
925        world.flush();
926        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
927    }
928
929    #[test]
930    fn observer_entity_routing() {
931        let mut world = World::new();
932        world.init_resource::<Order>();
933
934        world
935            .spawn_empty()
936            .observe(|_: Trigger<EventA>| panic!("Trigger routed to non-targeted entity."));
937        let entity = world
938            .spawn_empty()
939            .observe(|_: Trigger<EventA>, mut res: ResMut<Order>| res.observed("a_1"))
940            .id();
941        world.add_observer(move |obs: Trigger<EventA>, mut res: ResMut<Order>| {
942            assert_eq!(obs.entity(), entity);
943            res.observed("a_2");
944        });
945
946        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
947        // and therefore does not automatically flush.
948        world.flush();
949        world.trigger_targets(EventA, entity);
950        world.flush();
951        assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
952    }
953
954    #[test]
955    fn observer_dynamic_component() {
956        let mut world = World::new();
957        world.init_resource::<Order>();
958
959        let component_id = world.register_component::<A>();
960        world.spawn(
961            Observer::new(|_: Trigger<OnAdd>, mut res: ResMut<Order>| res.observed("event_a"))
962                .with_component(component_id),
963        );
964
965        let mut entity = world.spawn_empty();
966        OwningPtr::make(A, |ptr| {
967            // SAFETY: we registered `component_id` above.
968            unsafe { entity.insert_by_id(component_id, ptr) };
969        });
970        let entity = entity.flush();
971
972        world.trigger_targets(EventA, entity);
973        world.flush();
974        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
975    }
976
977    #[test]
978    fn observer_dynamic_trigger() {
979        let mut world = World::new();
980        world.init_resource::<Order>();
981        let event_a = world.register_component::<EventA>();
982
983        world.spawn(ObserverState {
984            // SAFETY: we registered `event_a` above and it matches the type of TriggerA
985            descriptor: unsafe { ObserverDescriptor::default().with_events(vec![event_a]) },
986            runner: |mut world, _trigger, _ptr, _propagate| {
987                world.resource_mut::<Order>().observed("event_a");
988            },
989            ..Default::default()
990        });
991
992        world.commands().queue(
993            // SAFETY: we registered `event_a` above and it matches the type of TriggerA
994            unsafe { EmitDynamicTrigger::new_with_id(event_a, EventA, ()) },
995        );
996        world.flush();
997        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
998    }
999
1000    #[test]
1001    fn observer_propagating() {
1002        let mut world = World::new();
1003        world.init_resource::<Order>();
1004
1005        let parent = world
1006            .spawn_empty()
1007            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1008                res.observed("parent");
1009            })
1010            .id();
1011
1012        let child = world
1013            .spawn(Parent(parent))
1014            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1015                res.observed("child");
1016            })
1017            .id();
1018
1019        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1020        // and therefore does not automatically flush.
1021        world.flush();
1022        world.trigger_targets(EventPropagating, child);
1023        world.flush();
1024        assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
1025    }
1026
1027    #[test]
1028    fn observer_propagating_redundant_dispatch_same_entity() {
1029        let mut world = World::new();
1030        world.init_resource::<Order>();
1031
1032        let parent = world
1033            .spawn_empty()
1034            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1035                res.observed("parent");
1036            })
1037            .id();
1038
1039        let child = world
1040            .spawn(Parent(parent))
1041            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1042                res.observed("child");
1043            })
1044            .id();
1045
1046        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1047        // and therefore does not automatically flush.
1048        world.flush();
1049        world.trigger_targets(EventPropagating, [child, child]);
1050        world.flush();
1051        assert_eq!(
1052            vec!["child", "parent", "child", "parent"],
1053            world.resource::<Order>().0
1054        );
1055    }
1056
1057    #[test]
1058    fn observer_propagating_redundant_dispatch_parent_child() {
1059        let mut world = World::new();
1060        world.init_resource::<Order>();
1061
1062        let parent = world
1063            .spawn_empty()
1064            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1065                res.observed("parent");
1066            })
1067            .id();
1068
1069        let child = world
1070            .spawn(Parent(parent))
1071            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1072                res.observed("child");
1073            })
1074            .id();
1075
1076        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1077        // and therefore does not automatically flush.
1078        world.flush();
1079        world.trigger_targets(EventPropagating, [child, parent]);
1080        world.flush();
1081        assert_eq!(
1082            vec!["child", "parent", "parent"],
1083            world.resource::<Order>().0
1084        );
1085    }
1086
1087    #[test]
1088    fn observer_propagating_halt() {
1089        let mut world = World::new();
1090        world.init_resource::<Order>();
1091
1092        let parent = world
1093            .spawn_empty()
1094            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1095                res.observed("parent");
1096            })
1097            .id();
1098
1099        let child = world
1100            .spawn(Parent(parent))
1101            .observe(
1102                |mut trigger: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1103                    res.observed("child");
1104                    trigger.propagate(false);
1105                },
1106            )
1107            .id();
1108
1109        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1110        // and therefore does not automatically flush.
1111        world.flush();
1112        world.trigger_targets(EventPropagating, child);
1113        world.flush();
1114        assert_eq!(vec!["child"], world.resource::<Order>().0);
1115    }
1116
1117    #[test]
1118    fn observer_propagating_join() {
1119        let mut world = World::new();
1120        world.init_resource::<Order>();
1121
1122        let parent = world
1123            .spawn_empty()
1124            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1125                res.observed("parent");
1126            })
1127            .id();
1128
1129        let child_a = world
1130            .spawn(Parent(parent))
1131            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1132                res.observed("child_a");
1133            })
1134            .id();
1135
1136        let child_b = world
1137            .spawn(Parent(parent))
1138            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1139                res.observed("child_b");
1140            })
1141            .id();
1142
1143        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1144        // and therefore does not automatically flush.
1145        world.flush();
1146        world.trigger_targets(EventPropagating, [child_a, child_b]);
1147        world.flush();
1148        assert_eq!(
1149            vec!["child_a", "parent", "child_b", "parent"],
1150            world.resource::<Order>().0
1151        );
1152    }
1153
1154    #[test]
1155    fn observer_propagating_no_next() {
1156        let mut world = World::new();
1157        world.init_resource::<Order>();
1158
1159        let entity = world
1160            .spawn_empty()
1161            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1162                res.observed("event");
1163            })
1164            .id();
1165
1166        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1167        // and therefore does not automatically flush.
1168        world.flush();
1169        world.trigger_targets(EventPropagating, entity);
1170        world.flush();
1171        assert_eq!(vec!["event"], world.resource::<Order>().0);
1172    }
1173
1174    #[test]
1175    fn observer_propagating_parallel_propagation() {
1176        let mut world = World::new();
1177        world.init_resource::<Order>();
1178
1179        let parent_a = world
1180            .spawn_empty()
1181            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1182                res.observed("parent_a");
1183            })
1184            .id();
1185
1186        let child_a = world
1187            .spawn(Parent(parent_a))
1188            .observe(
1189                |mut trigger: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1190                    res.observed("child_a");
1191                    trigger.propagate(false);
1192                },
1193            )
1194            .id();
1195
1196        let parent_b = world
1197            .spawn_empty()
1198            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1199                res.observed("parent_b");
1200            })
1201            .id();
1202
1203        let child_b = world
1204            .spawn(Parent(parent_b))
1205            .observe(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1206                res.observed("child_b");
1207            })
1208            .id();
1209
1210        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1211        // and therefore does not automatically flush.
1212        world.flush();
1213        world.trigger_targets(EventPropagating, [child_a, child_b]);
1214        world.flush();
1215        assert_eq!(
1216            vec!["child_a", "child_b", "parent_b"],
1217            world.resource::<Order>().0
1218        );
1219    }
1220
1221    #[test]
1222    fn observer_propagating_world() {
1223        let mut world = World::new();
1224        world.init_resource::<Order>();
1225
1226        world.add_observer(|_: Trigger<EventPropagating>, mut res: ResMut<Order>| {
1227            res.observed("event");
1228        });
1229
1230        let grandparent = world.spawn_empty().id();
1231        let parent = world.spawn(Parent(grandparent)).id();
1232        let child = world.spawn(Parent(parent)).id();
1233
1234        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1235        // and therefore does not automatically flush.
1236        world.flush();
1237        world.trigger_targets(EventPropagating, child);
1238        world.flush();
1239        assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
1240    }
1241
1242    #[test]
1243    fn observer_propagating_world_skipping() {
1244        let mut world = World::new();
1245        world.init_resource::<Order>();
1246
1247        world.add_observer(
1248            |trigger: Trigger<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
1249                if query.get(trigger.entity()).is_ok() {
1250                    res.observed("event");
1251                }
1252            },
1253        );
1254
1255        let grandparent = world.spawn(A).id();
1256        let parent = world.spawn(Parent(grandparent)).id();
1257        let child = world.spawn((A, Parent(parent))).id();
1258
1259        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1260        // and therefore does not automatically flush.
1261        world.flush();
1262        world.trigger_targets(EventPropagating, child);
1263        world.flush();
1264        assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
1265    }
1266
1267    // Regression test for https://github.com/bevyengine/bevy/issues/14467
1268    // Fails prior to https://github.com/bevyengine/bevy/pull/15398
1269    #[test]
1270    fn observer_on_remove_during_despawn_spawn_empty() {
1271        let mut world = World::new();
1272
1273        // Observe the removal of A - this will run during despawn
1274        world.add_observer(|_: Trigger<OnRemove, A>, mut cmd: Commands| {
1275            // Spawn a new entity - this reserves a new ID and requires a flush
1276            // afterward before Entities::free can be called.
1277            cmd.spawn_empty();
1278        });
1279
1280        let ent = world.spawn(A).id();
1281
1282        // Despawn our entity, which runs the OnRemove observer and allocates a
1283        // new Entity.
1284        // Should not panic - if it does, then Entities was not flushed properly
1285        // after the observer's spawn_empty.
1286        world.despawn(ent);
1287    }
1288
1289    #[test]
1290    fn observer_invalid_params() {
1291        #[derive(Resource)]
1292        struct ResA;
1293
1294        #[derive(Resource)]
1295        struct ResB;
1296
1297        let mut world = World::new();
1298        // This fails because `ResA` is not present in the world
1299        world.add_observer(|_: Trigger<EventA>, _: Res<ResA>, mut commands: Commands| {
1300            commands.insert_resource(ResB);
1301        });
1302        world.trigger(EventA);
1303
1304        assert!(world.get_resource::<ResB>().is_none());
1305    }
1306
1307    #[test]
1308    fn observer_apply_deferred_from_param_set() {
1309        #[derive(Resource)]
1310        struct ResA;
1311
1312        let mut world = World::new();
1313        world.add_observer(
1314            |_: Trigger<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1315                params.p1().insert_resource(ResA);
1316            },
1317        );
1318        // TODO: ideally this flush is not necessary, but right now observe() returns WorldEntityMut
1319        // and therefore does not automatically flush.
1320        world.flush();
1321        world.trigger(EventA);
1322        world.flush();
1323
1324        assert!(world.get_resource::<ResA>().is_some());
1325    }
1326
1327    #[test]
1328    fn observer_triggered_components() {
1329        #[derive(Resource, Default)]
1330        struct Counter(HashMap<ComponentId, usize>);
1331
1332        let mut world = World::new();
1333        world.init_resource::<Counter>();
1334        let a_id = world.register_component::<A>();
1335        let b_id = world.register_component::<B>();
1336
1337        world.add_observer(
1338            |trigger: Trigger<EventA, (A, B)>, mut counter: ResMut<Counter>| {
1339                for &component in trigger.components() {
1340                    *counter.0.entry(component).or_default() += 1;
1341                }
1342            },
1343        );
1344        world.flush();
1345
1346        world.trigger_targets(EventA, [a_id, b_id]);
1347        world.trigger_targets(EventA, a_id);
1348        world.trigger_targets(EventA, b_id);
1349        world.trigger_targets(EventA, [a_id, b_id]);
1350        world.trigger_targets(EventA, a_id);
1351        world.flush();
1352
1353        let counter = world.resource::<Counter>();
1354        assert_eq!(4, *counter.0.get(&a_id).unwrap());
1355        assert_eq!(3, *counter.0.get(&b_id).unwrap());
1356    }
1357}