1mod 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
28pub 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 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 pub fn event_type(&self) -> ComponentId {
51 self.trigger.event_type
52 }
53
54 pub fn event(&self) -> &E {
56 self.event
57 }
58
59 pub fn event_mut(&mut self) -> &mut E {
61 self.event
62 }
63
64 pub fn event_ptr(&self) -> Ptr {
66 Ptr::from(&self.event)
67 }
68
69 pub fn entity(&self) -> Entity {
71 self.trigger.entity
72 }
73
74 pub fn components(&self) -> &[ComponentId] {
78 &self.trigger.components
79 }
80
81 pub fn observer(&self) -> Entity {
104 self.trigger.observer
105 }
106
107 pub fn propagate(&mut self, should_propagate: bool) {
120 *self.propagate = should_propagate;
121 }
122
123 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#[derive(Default, Clone)]
158pub struct ObserverDescriptor {
159 events: Vec<ComponentId>,
161
162 components: Vec<ComponentId>,
164
165 entities: Vec<Entity>,
167}
168
169impl ObserverDescriptor {
170 pub unsafe fn with_events(mut self, events: Vec<ComponentId>) -> Self {
175 self.events = events;
176 self
177 }
178
179 pub fn with_components(mut self, components: Vec<ComponentId>) -> Self {
181 self.components = components;
182 self
183 }
184
185 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#[derive(Debug)]
201pub struct ObserverTrigger {
202 pub observer: Entity,
204 pub event_type: ComponentId,
206 components: SmallVec<[ComponentId; 2]>,
208 pub entity: Entity,
210}
211
212impl ObserverTrigger {
213 pub fn components(&self) -> &[ComponentId] {
215 &self.components
216 }
217}
218
219type ObserverMap = EntityHashMap<ObserverRunner>;
221
222#[derive(Default, Debug)]
224pub struct CachedComponentObservers {
225 map: ObserverMap,
227 entity_map: EntityHashMap<ObserverMap>,
229}
230
231#[derive(Default, Debug)]
233pub struct CachedObservers {
234 map: ObserverMap,
236 component_observers: HashMap<ComponentId, CachedComponentObservers>,
238 entity_observers: EntityHashMap<ObserverMap>,
240}
241
242#[derive(Default, Debug)]
244pub struct Observers {
245 on_add: CachedObservers,
247 on_insert: CachedObservers,
248 on_replace: CachedObservers,
249 on_remove: CachedObservers,
250 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 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 let (mut world, observers) = unsafe {
286 let world = world.as_unsafe_world_cell();
287 world.increment_trigger_id();
289 let observers = world.observers();
290 let Some(observers) = observers.try_get_observers(event_type) else {
291 return;
292 };
293 (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 observers.map.iter().for_each(&mut trigger_observer);
314
315 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_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 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 pub fn trigger(&mut self, event: impl Event) {
420 TriggerEvent { event, targets: () }.trigger(self);
421 }
422
423 pub fn trigger_ref(&mut self, event: &mut impl Event) {
428 TriggerEvent { event, targets: () }.trigger_ref(self);
429 }
430
431 pub fn trigger_targets(&mut self, event: impl Event, targets: impl TriggerTargets) {
437 TriggerEvent { event, targets }.trigger(self);
438 }
439
440 pub fn trigger_targets_ref(&mut self, event: &mut impl Event, targets: impl TriggerTargets) {
446 TriggerEvent { event, targets }.trigger_ref(self);
447 }
448
449 pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
451 let (observer_state, archetypes, observers) = unsafe {
453 let observer_state: *const ObserverState =
454 self.get::<ObserverState>(observer_entity).unwrap();
455 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 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 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 observers.map.insert(observer_entity, observer_state.runner);
492 } else {
493 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 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 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 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 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 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 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 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 #[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 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 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 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 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 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 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 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 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 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 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 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 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 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 world.flush();
1262 world.trigger_targets(EventPropagating, child);
1263 world.flush();
1264 assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
1265 }
1266
1267 #[test]
1270 fn observer_on_remove_during_despawn_spawn_empty() {
1271 let mut world = World::new();
1272
1273 world.add_observer(|_: Trigger<OnRemove, A>, mut cmd: Commands| {
1275 cmd.spawn_empty();
1278 });
1279
1280 let ent = world.spawn(A).id();
1281
1282 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 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 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}