1mod centralized_storage;
7mod distributed_storage;
8mod entity_cloning;
9mod runner;
10mod system_param;
11
12pub use centralized_storage::*;
13pub use distributed_storage::*;
14pub use runner::*;
15pub use system_param::*;
16
17use crate::{
18 change_detection::MaybeLocation,
19 event::Event,
20 prelude::*,
21 system::IntoObserverSystem,
22 world::{DeferredWorld, *},
23};
24
25impl World {
26 pub fn add_observer<E: Event, B: Bundle, M>(
55 &mut self,
56 system: impl IntoObserverSystem<E, B, M>,
57 ) -> EntityWorldMut<'_> {
58 self.spawn(Observer::new(system))
59 }
60
61 #[track_caller]
65 pub fn trigger<'a, E: Event<Trigger<'a>: Default>>(&mut self, mut event: E) {
66 self.trigger_ref_with_caller(
67 &mut event,
68 &mut <E::Trigger<'a> as Default>::default(),
69 MaybeLocation::caller(),
70 );
71 }
72
73 #[deprecated(since = "0.17.0", note = "Use `World::trigger` instead.")]
79 pub fn trigger_targets<'a>(&mut self, event: impl Event<Trigger<'a>: Default>) {
80 self.trigger(event);
81 }
82
83 #[track_caller]
87 pub fn trigger_with<'a, E: Event>(&mut self, mut event: E, mut trigger: E::Trigger<'a>) {
88 self.trigger_ref_with_caller(&mut event, &mut trigger, MaybeLocation::caller());
89 }
90
91 #[track_caller]
96 pub fn trigger_ref<'a, E: Event<Trigger<'a>: Default>>(&mut self, event: &mut E) {
97 self.trigger_ref_with_caller(
98 event,
99 &mut <E::Trigger<'a> as Default>::default(),
100 MaybeLocation::caller(),
101 );
102 }
103
104 pub fn trigger_ref_with<'a, E: Event>(&mut self, event: &mut E, trigger: &mut E::Trigger<'a>) {
110 self.trigger_ref_with_caller(event, trigger, MaybeLocation::caller());
111 }
112
113 pub(crate) fn trigger_ref_with_caller<'a, E: Event>(
114 &mut self,
115 event: &mut E,
116 trigger: &mut E::Trigger<'a>,
117 caller: MaybeLocation,
118 ) {
119 let event_key = self.register_event_key::<E>();
120 unsafe {
122 DeferredWorld::from(self).trigger_raw(event_key, event, trigger, caller);
123 }
124 }
125
126 pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
128 let (observer_state, archetypes, observers) = unsafe {
130 let observer_state: *const Observer = self.get::<Observer>(observer_entity).unwrap();
131 for watched_entity in (*observer_state).descriptor.entities.iter().copied() {
133 let mut entity_mut = self.entity_mut(watched_entity);
134 let mut observed_by = entity_mut.entry::<ObservedBy>().or_default().into_mut();
135 observed_by.0.push(observer_entity);
136 }
137 (&*observer_state, &mut self.archetypes, &mut self.observers)
138 };
139 let descriptor = &observer_state.descriptor;
140
141 for &event_key in &descriptor.event_keys {
142 let cache = observers.get_observers_mut(event_key);
143
144 if descriptor.components.is_empty() && descriptor.entities.is_empty() {
145 cache
146 .global_observers
147 .insert(observer_entity, observer_state.runner);
148 } else if descriptor.components.is_empty() {
149 for &watched_entity in &observer_state.descriptor.entities {
151 let map = cache.entity_observers.entry(watched_entity).or_default();
152 map.insert(observer_entity, observer_state.runner);
153 }
154 } else {
155 for &component in &descriptor.components {
157 let observers =
158 cache
159 .component_observers
160 .entry(component)
161 .or_insert_with(|| {
162 if let Some(flag) = Observers::is_archetype_cached(event_key) {
163 archetypes.update_flags(component, flag, true);
164 }
165 CachedComponentObservers::default()
166 });
167 if descriptor.entities.is_empty() {
168 observers
170 .global_observers
171 .insert(observer_entity, observer_state.runner);
172 } else {
173 for &watched_entity in &descriptor.entities {
175 let map = observers
176 .entity_component_observers
177 .entry(watched_entity)
178 .or_default();
179 map.insert(observer_entity, observer_state.runner);
180 }
181 }
182 }
183 }
184 }
185 }
186
187 pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
189 let archetypes = &mut self.archetypes;
190 let observers = &mut self.observers;
191
192 for &event_key in &descriptor.event_keys {
193 let cache = observers.get_observers_mut(event_key);
194 if descriptor.components.is_empty() && descriptor.entities.is_empty() {
195 cache.global_observers.remove(&entity);
196 } else if descriptor.components.is_empty() {
197 for watched_entity in &descriptor.entities {
198 let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
200 continue;
201 };
202 observers.remove(&entity);
203 if observers.is_empty() {
204 cache.entity_observers.remove(watched_entity);
205 }
206 }
207 } else {
208 for component in &descriptor.components {
209 let Some(observers) = cache.component_observers.get_mut(component) else {
210 continue;
211 };
212 if descriptor.entities.is_empty() {
213 observers.global_observers.remove(&entity);
214 } else {
215 for watched_entity in &descriptor.entities {
216 let Some(map) =
217 observers.entity_component_observers.get_mut(watched_entity)
218 else {
219 continue;
220 };
221 map.remove(&entity);
222 if map.is_empty() {
223 observers.entity_component_observers.remove(watched_entity);
224 }
225 }
226 }
227
228 if observers.global_observers.is_empty()
229 && observers.entity_component_observers.is_empty()
230 {
231 cache.component_observers.remove(component);
232 if let Some(flag) = Observers::is_archetype_cached(event_key) {
233 if let Some(by_component) = archetypes.by_component.get(component) {
234 for archetype in by_component.keys() {
235 let archetype = &mut archetypes.archetypes[archetype.index()];
236 if archetype.contains(*component) {
237 let no_longer_observed = archetype
238 .iter_components()
239 .all(|id| !cache.component_observers.contains_key(&id));
240
241 if no_longer_observed {
242 archetype.flags.set(flag, false);
243 }
244 }
245 }
246 }
247 }
248 }
249 }
250 }
251 }
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use alloc::{vec, vec::Vec};
258
259 use bevy_ptr::OwningPtr;
260
261 use crate::{
262 change_detection::MaybeLocation,
263 entity_disabling::Internal,
264 event::{EntityComponentsTrigger, Event, GlobalTrigger},
265 hierarchy::ChildOf,
266 observer::{Observer, Replace},
267 prelude::*,
268 world::DeferredWorld,
269 };
270
271 #[derive(Component)]
272 struct A;
273
274 #[derive(Component)]
275 struct B;
276
277 #[derive(Component)]
278 #[component(storage = "SparseSet")]
279 struct S;
280
281 #[derive(Event)]
282 struct EventA;
283
284 #[derive(EntityEvent)]
285 struct EntityEventA(Entity);
286
287 #[derive(EntityEvent)]
288 #[entity_event(trigger = EntityComponentsTrigger<'a>)]
289 struct EntityComponentsEvent(Entity);
290
291 #[derive(Event)]
292 struct EventWithData {
293 counter: usize,
294 }
295
296 #[derive(Resource, Default)]
297 struct Order(Vec<&'static str>);
298
299 impl Order {
300 #[track_caller]
301 fn observed(&mut self, name: &'static str) {
302 self.0.push(name);
303 }
304 }
305
306 #[derive(Component, EntityEvent)]
307 #[entity_event(propagate, auto_propagate)]
308 struct EventPropagating(Entity);
309
310 #[test]
311 fn observer_order_spawn_despawn() {
312 let mut world = World::new();
313 world.init_resource::<Order>();
314
315 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
316 world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
317 world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
318 res.observed("replace");
319 });
320 world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
321
322 let entity = world.spawn(A).id();
323 world.despawn(entity);
324 assert_eq!(
325 vec!["add", "insert", "replace", "remove"],
326 world.resource::<Order>().0
327 );
328 }
329
330 #[test]
331 fn observer_order_insert_remove() {
332 let mut world = World::new();
333 world.init_resource::<Order>();
334
335 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
336 world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
337 world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
338 res.observed("replace");
339 });
340 world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
341
342 let mut entity = world.spawn_empty();
343 entity.insert(A);
344 entity.remove::<A>();
345 entity.flush();
346 assert_eq!(
347 vec!["add", "insert", "replace", "remove"],
348 world.resource::<Order>().0
349 );
350 }
351
352 #[test]
353 fn observer_order_insert_remove_sparse() {
354 let mut world = World::new();
355 world.init_resource::<Order>();
356
357 world.add_observer(|_: On<Add, S>, mut res: ResMut<Order>| res.observed("add"));
358 world.add_observer(|_: On<Insert, S>, mut res: ResMut<Order>| res.observed("insert"));
359 world.add_observer(|_: On<Replace, S>, mut res: ResMut<Order>| {
360 res.observed("replace");
361 });
362 world.add_observer(|_: On<Remove, S>, mut res: ResMut<Order>| res.observed("remove"));
363
364 let mut entity = world.spawn_empty();
365 entity.insert(S);
366 entity.remove::<S>();
367 entity.flush();
368 assert_eq!(
369 vec!["add", "insert", "replace", "remove"],
370 world.resource::<Order>().0
371 );
372 }
373
374 #[test]
375 fn observer_order_replace() {
376 let mut world = World::new();
377 world.init_resource::<Order>();
378
379 let entity = world.spawn(A).id();
380
381 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
382 world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
383 world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
384 res.observed("replace");
385 });
386 world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
387
388 let mut entity = world.entity_mut(entity);
389 entity.insert(A);
390 entity.flush();
391 assert_eq!(vec!["replace", "insert"], world.resource::<Order>().0);
392 }
393
394 #[test]
395 fn observer_order_recursive() {
396 let mut world = World::new();
397 world.init_resource::<Order>();
398 world.add_observer(
399 |add: On<Add, A>, mut res: ResMut<Order>, mut commands: Commands| {
400 res.observed("add_a");
401 commands.entity(add.entity).insert(B);
402 },
403 );
404 world.add_observer(
405 |remove: On<Remove, A>, mut res: ResMut<Order>, mut commands: Commands| {
406 res.observed("remove_a");
407 commands.entity(remove.entity).remove::<B>();
408 },
409 );
410
411 world.add_observer(
412 |add: On<Add, B>, mut res: ResMut<Order>, mut commands: Commands| {
413 res.observed("add_b");
414 commands.entity(add.entity).remove::<A>();
415 },
416 );
417 world.add_observer(|_: On<Remove, B>, mut res: ResMut<Order>| {
418 res.observed("remove_b");
419 });
420
421 let entity = world.spawn(A).flush();
422 let entity = world.get_entity(entity).unwrap();
423 assert!(!entity.contains::<A>());
424 assert!(!entity.contains::<B>());
425 assert_eq!(
426 vec!["add_a", "add_b", "remove_a", "remove_b"],
427 world.resource::<Order>().0
428 );
429 }
430
431 #[test]
432 fn observer_trigger_ref() {
433 let mut world = World::new();
434
435 world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
436 world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
437 world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
438
439 let mut event = EventWithData { counter: 0 };
440 world.trigger_ref(&mut event);
441 assert_eq!(7, event.counter);
442 }
443
444 #[test]
445 fn observer_multiple_listeners() {
446 let mut world = World::new();
447 world.init_resource::<Order>();
448
449 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
450 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));
451
452 world.spawn(A).flush();
453 assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
454 assert_eq!(world.query::<&A>().query(&world).count(), 1);
456 assert_eq!(
457 world
458 .query_filtered::<&Observer, Allow<Internal>>()
459 .query(&world)
460 .count(),
461 2
462 );
463 }
464
465 #[test]
466 fn observer_multiple_events() {
467 let mut world = World::new();
468 world.init_resource::<Order>();
469 let on_remove = world.register_event_key::<Remove>();
470 world.spawn(
471 unsafe {
473 Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
474 res.observed("add/remove");
475 })
476 .with_event_key(on_remove)
477 },
478 );
479
480 let entity = world.spawn(A).id();
481 world.despawn(entity);
482 assert_eq!(
483 vec!["add/remove", "add/remove"],
484 world.resource::<Order>().0
485 );
486 }
487
488 #[test]
489 fn observer_multiple_components() {
490 let mut world = World::new();
491 world.init_resource::<Order>();
492 world.register_component::<A>();
493 world.register_component::<B>();
494
495 world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
496 res.observed("add_ab");
497 });
498
499 let entity = world.spawn(A).id();
500 world.entity_mut(entity).insert(B);
501 assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
502 }
503
504 #[test]
505 fn observer_despawn() {
506 let mut world = World::new();
507
508 let system: fn(On<Add, A>) = |_| {
509 panic!("Observer triggered after being despawned.");
510 };
511 let observer = world.add_observer(system).id();
512 world.despawn(observer);
513 world.spawn(A).flush();
514 }
515
516 #[test]
518 fn observer_despawn_archetype_flags() {
519 let mut world = World::new();
520 world.init_resource::<Order>();
521
522 let entity = world.spawn((A, B)).flush();
523
524 world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| {
525 res.observed("remove_a");
526 });
527
528 let system: fn(On<Remove, B>) = |_: On<Remove, B>| {
529 panic!("Observer triggered after being despawned.");
530 };
531
532 let observer = world.add_observer(system).flush();
533 world.despawn(observer);
534
535 world.despawn(entity);
536
537 assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
538 }
539
540 #[test]
541 fn observer_multiple_matches() {
542 let mut world = World::new();
543 world.init_resource::<Order>();
544
545 world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
546 res.observed("add_ab");
547 });
548
549 world.spawn((A, B)).flush();
550 assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
551 }
552
553 #[test]
554 fn observer_entity_routing() {
555 let mut world = World::new();
556 world.init_resource::<Order>();
557
558 let system: fn(On<EntityEventA>) = |_| {
559 panic!("Trigger routed to non-targeted entity.");
560 };
561
562 world.spawn_empty().observe(system);
563 let entity = world
564 .spawn_empty()
565 .observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
566 .id();
567 world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
568 assert_eq!(event.event_target(), entity);
569 res.observed("a_2");
570 });
571
572 world.trigger(EntityEventA(entity));
573 assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
574 }
575
576 #[test]
577 fn observer_multiple_targets() {
578 #[derive(Resource, Default)]
579 struct R(i32);
580
581 let mut world = World::new();
582 let component_a = world.register_component::<A>();
583 let component_b = world.register_component::<B>();
584 world.init_resource::<R>();
585
586 let entity_1 = world
588 .spawn_empty()
589 .observe(|_: On<EntityComponentsEvent, A>, mut res: ResMut<R>| res.0 += 1)
590 .id();
591 let entity_2 = world
593 .spawn_empty()
594 .observe(|_: On<EntityComponentsEvent, B>, mut res: ResMut<R>| res.0 += 10)
595 .id();
596 world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
598 world
600 .add_observer(|_: On<EntityComponentsEvent, (A, B)>, mut res: ResMut<R>| res.0 += 1000);
601 world.add_observer(
603 |_: On<EntityComponentsEvent, (A, B, (A, B))>, mut res: ResMut<R>| res.0 += 10000,
604 );
605 world.add_observer(
606 |_: On<EntityComponentsEvent, (A, B, (A, B), ((A, B), (A, B)))>, mut res: ResMut<R>| {
607 res.0 += 100000;
608 },
609 );
610 world.add_observer(
611 |_: On<EntityComponentsEvent, (A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>,
612 mut res: ResMut<R>| res.0 += 1000000,
613 );
614
615 world.trigger_with(
617 EntityComponentsEvent(entity_1),
618 EntityComponentsTrigger {
619 components: &[component_a],
620 },
621 );
622 assert_eq!(1111101, world.resource::<R>().0);
624 world.resource_mut::<R>().0 = 0;
625
626 world.trigger_with(
628 EntityComponentsEvent(entity_1),
629 EntityComponentsTrigger { components: &[] },
630 );
631 world.trigger_with(
632 EntityComponentsEvent(entity_2),
633 EntityComponentsTrigger { components: &[] },
634 );
635
636 assert_eq!(200, world.resource::<R>().0);
638 world.resource_mut::<R>().0 = 0;
639
640 world.trigger_with(
643 EntityComponentsEvent(entity_1),
644 EntityComponentsTrigger {
645 components: &[component_a, component_b],
646 },
647 );
648 world.trigger_with(
649 EntityComponentsEvent(entity_2),
650 EntityComponentsTrigger {
651 components: &[component_a, component_b],
652 },
653 );
654 assert_eq!(2222211, world.resource::<R>().0);
655 world.resource_mut::<R>().0 = 0;
656 }
657
658 #[test]
659 fn observer_dynamic_component() {
660 let mut world = World::new();
661 world.init_resource::<Order>();
662
663 let component_id = world.register_component::<A>();
664 world.spawn(
665 Observer::new(|_: On<Add>, mut res: ResMut<Order>| res.observed("event_a"))
666 .with_component(component_id),
667 );
668
669 let mut entity = world.spawn_empty();
670 OwningPtr::make(A, |ptr| {
671 unsafe { entity.insert_by_id(component_id, ptr) };
673 });
674
675 assert_eq!(vec!["event_a"], world.resource::<Order>().0);
676 }
677
678 #[test]
679 fn observer_dynamic_trigger() {
680 let mut world = World::new();
681 world.init_resource::<Order>();
682 let event_a = world.register_event_key::<EventA>();
683
684 let observe = unsafe {
686 Observer::with_dynamic_runner(
687 |mut world, _observer, _trigger_context, _event, _trigger| {
688 world.resource_mut::<Order>().observed("event_a");
689 },
690 )
691 .with_event_key(event_a)
692 };
693 world.spawn(observe);
694
695 world.commands().queue(move |world: &mut World| {
696 unsafe {
698 DeferredWorld::from(world).trigger_raw(
699 event_a,
700 &mut EventA,
701 &mut GlobalTrigger,
702 MaybeLocation::caller(),
703 );
704 }
705 });
706 world.flush();
707 assert_eq!(vec!["event_a"], world.resource::<Order>().0);
708 }
709
710 #[test]
711 fn observer_propagating() {
712 let mut world = World::new();
713 world.init_resource::<Order>();
714
715 let parent = world.spawn_empty().id();
716 let child = world.spawn(ChildOf(parent)).id();
717
718 world.entity_mut(parent).observe(
719 move |event: On<EventPropagating>, mut res: ResMut<Order>| {
720 res.observed("parent");
721
722 assert_eq!(event.event_target(), parent);
723 assert_eq!(event.original_event_target(), child);
724 },
725 );
726
727 world.entity_mut(child).observe(
728 move |event: On<EventPropagating>, mut res: ResMut<Order>| {
729 res.observed("child");
730 assert_eq!(event.event_target(), child);
731 assert_eq!(event.original_event_target(), child);
732 },
733 );
734
735 world.trigger(EventPropagating(child));
736
737 assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
738 }
739
740 #[test]
741 fn observer_propagating_redundant_dispatch_same_entity() {
742 let mut world = World::new();
743 world.init_resource::<Order>();
744
745 let parent = world
746 .spawn_empty()
747 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
748 res.observed("parent");
749 })
750 .id();
751
752 let child = world
753 .spawn(ChildOf(parent))
754 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
755 res.observed("child");
756 })
757 .id();
758
759 world.trigger(EventPropagating(child));
760 world.trigger(EventPropagating(child));
761
762 assert_eq!(
763 vec!["child", "parent", "child", "parent"],
764 world.resource::<Order>().0
765 );
766 }
767
768 #[test]
769 fn observer_propagating_redundant_dispatch_parent_child() {
770 let mut world = World::new();
771 world.init_resource::<Order>();
772
773 let parent = world
774 .spawn_empty()
775 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
776 res.observed("parent");
777 })
778 .id();
779
780 let child = world
781 .spawn(ChildOf(parent))
782 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
783 res.observed("child");
784 })
785 .id();
786
787 world.trigger(EventPropagating(child));
788 world.trigger(EventPropagating(parent));
789
790 assert_eq!(
791 vec!["child", "parent", "parent"],
792 world.resource::<Order>().0
793 );
794 }
795
796 #[test]
797 fn observer_propagating_halt() {
798 let mut world = World::new();
799 world.init_resource::<Order>();
800
801 let parent = world
802 .spawn_empty()
803 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
804 res.observed("parent");
805 })
806 .id();
807
808 let child = world
809 .spawn(ChildOf(parent))
810 .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
811 res.observed("child");
812 event.propagate(false);
813 })
814 .id();
815
816 world.trigger(EventPropagating(child));
817
818 assert_eq!(vec!["child"], world.resource::<Order>().0);
819 }
820
821 #[test]
822 fn observer_propagating_join() {
823 let mut world = World::new();
824 world.init_resource::<Order>();
825
826 let parent = world
827 .spawn_empty()
828 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
829 res.observed("parent");
830 })
831 .id();
832
833 let child_a = world
834 .spawn(ChildOf(parent))
835 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
836 res.observed("child_a");
837 })
838 .id();
839
840 let child_b = world
841 .spawn(ChildOf(parent))
842 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
843 res.observed("child_b");
844 })
845 .id();
846
847 world.trigger(EventPropagating(child_a));
848 world.trigger(EventPropagating(child_b));
849
850 assert_eq!(
851 vec!["child_a", "parent", "child_b", "parent"],
852 world.resource::<Order>().0
853 );
854 }
855
856 #[test]
857 fn observer_propagating_no_next() {
858 let mut world = World::new();
859 world.init_resource::<Order>();
860
861 let entity = world
862 .spawn_empty()
863 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
864 res.observed("event");
865 })
866 .id();
867
868 world.trigger(EventPropagating(entity));
869 assert_eq!(vec!["event"], world.resource::<Order>().0);
870 }
871
872 #[test]
873 fn observer_propagating_parallel_propagation() {
874 let mut world = World::new();
875 world.init_resource::<Order>();
876
877 let parent_a = world
878 .spawn_empty()
879 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
880 res.observed("parent_a");
881 })
882 .id();
883
884 let child_a = world
885 .spawn(ChildOf(parent_a))
886 .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
887 res.observed("child_a");
888 event.propagate(false);
889 })
890 .id();
891
892 let parent_b = world
893 .spawn_empty()
894 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
895 res.observed("parent_b");
896 })
897 .id();
898
899 let child_b = world
900 .spawn(ChildOf(parent_b))
901 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
902 res.observed("child_b");
903 })
904 .id();
905
906 world.trigger(EventPropagating(child_a));
907 world.trigger(EventPropagating(child_b));
908
909 assert_eq!(
910 vec!["child_a", "child_b", "parent_b"],
911 world.resource::<Order>().0
912 );
913 }
914
915 #[test]
916 fn observer_propagating_world() {
917 let mut world = World::new();
918 world.init_resource::<Order>();
919
920 world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
921 res.observed("event");
922 });
923
924 let grandparent = world.spawn_empty().id();
925 let parent = world.spawn(ChildOf(grandparent)).id();
926 let child = world.spawn(ChildOf(parent)).id();
927
928 world.trigger(EventPropagating(child));
929
930 assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
931 }
932
933 #[test]
934 fn observer_propagating_world_skipping() {
935 let mut world = World::new();
936 world.init_resource::<Order>();
937
938 world.add_observer(
939 |event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
940 if query.get(event.event_target()).is_ok() {
941 res.observed("event");
942 }
943 },
944 );
945
946 let grandparent = world.spawn(A).id();
947 let parent = world.spawn(ChildOf(grandparent)).id();
948 let child = world.spawn((A, ChildOf(parent))).id();
949
950 world.trigger(EventPropagating(child));
951
952 assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
953 }
954
955 #[test]
957 fn observer_modifies_relationship() {
958 fn on_add(add: On<Add, A>, mut commands: Commands) {
959 commands
960 .entity(add.entity)
961 .with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
962 rsc.spawn_empty();
963 });
964 }
965
966 let mut world = World::new();
967 world.add_observer(on_add);
968 world.spawn(A);
969 }
970
971 #[test]
974 fn observer_on_remove_during_despawn_spawn_empty() {
975 let mut world = World::new();
976
977 world.add_observer(|_: On<Remove, A>, mut cmd: Commands| {
979 cmd.spawn_empty();
982 });
983
984 let ent = world.spawn(A).id();
985
986 world.despawn(ent);
991 }
992
993 #[test]
994 #[should_panic]
995 fn observer_invalid_params() {
996 #[derive(Resource)]
997 struct ResA;
998
999 #[derive(Resource)]
1000 struct ResB;
1001
1002 let mut world = World::new();
1003 world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
1005 commands.insert_resource(ResB);
1006 });
1007 world.trigger(EventA);
1008 }
1009
1010 #[test]
1011 fn observer_apply_deferred_from_param_set() {
1012 #[derive(Resource)]
1013 struct ResA;
1014
1015 let mut world = World::new();
1016 world.add_observer(
1017 |_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1018 params.p1().insert_resource(ResA);
1019 },
1020 );
1021
1022 world.trigger(EventA);
1023 world.flush();
1024
1025 assert!(world.get_resource::<ResA>().is_some());
1026 }
1027
1028 #[test]
1029 #[track_caller]
1030 fn observer_caller_location_event() {
1031 #[derive(Event)]
1032 struct EventA;
1033
1034 let caller = MaybeLocation::caller();
1035 let mut world = World::new();
1036 world.add_observer(move |event: On<EventA>| {
1037 assert_eq!(event.caller(), caller);
1038 });
1039 world.trigger(EventA);
1040 }
1041
1042 #[test]
1043 #[track_caller]
1044 fn observer_caller_location_command_archetype_move() {
1045 #[derive(Component)]
1046 struct Component;
1047
1048 let caller = MaybeLocation::caller();
1049 let mut world = World::new();
1050 world.add_observer(move |event: On<Add, Component>| {
1051 assert_eq!(event.caller(), caller);
1052 });
1053 world.add_observer(move |event: On<Remove, Component>| {
1054 assert_eq!(event.caller(), caller);
1055 });
1056 world.commands().spawn(Component).clear();
1057 }
1058
1059 #[test]
1060 fn observer_watch_entities() {
1061 let mut world = World::new();
1062 world.init_resource::<Order>();
1063 let entities = world
1064 .spawn_batch(core::iter::repeat_n((), 4))
1065 .collect::<Vec<_>>();
1066 let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1067 order.observed("a");
1068 });
1069 world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1070
1071 world.trigger(EntityEventA(entities[0]));
1072 world.trigger(EntityEventA(entities[1]));
1073 assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1074 world.trigger(EntityEventA(entities[2]));
1075 world.trigger(EntityEventA(entities[3]));
1076 assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1077 }
1078
1079 #[test]
1080 fn unregister_global_observer() {
1081 let mut world = World::new();
1082 let mut observer = world.add_observer(|_: On<EventA>| {});
1083 observer.remove::<Observer>();
1084 let id = observer.id();
1085 let event_key = world.event_key::<EventA>().unwrap();
1086 assert!(!world
1087 .observers
1088 .get_observers_mut(event_key)
1089 .global_observers
1090 .contains_key(&id));
1091 }
1092
1093 #[test]
1094 fn unregister_entity_observer() {
1095 let mut world = World::new();
1096 let entity = world.spawn_empty().id();
1097 let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1098 let mut observer = world.spawn(observer);
1099 observer.remove::<Observer>();
1100 let event_key = world.event_key::<EventA>().unwrap();
1101 assert!(!world
1102 .observers
1103 .get_observers_mut(event_key)
1104 .entity_observers
1105 .contains_key(&entity));
1106 }
1107
1108 #[test]
1109 fn unregister_component_observer() {
1110 let mut world = World::new();
1111 let a = world.register_component::<A>();
1112 let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1113 let mut observer = world.spawn(observer);
1114 observer.remove::<Observer>();
1115 let event_key = world.event_key::<EventA>().unwrap();
1116 assert!(!world
1117 .observers
1118 .get_observers_mut(event_key)
1119 .component_observers()
1120 .contains_key(&a));
1121 }
1122
1123 #[test]
1124 #[expect(deprecated, reason = "We still need to test `On::target`")]
1125 fn observer_target() {
1126 let mut world = World::new();
1127 let entity = world
1128 .spawn_empty()
1129 .observe(|event: On<EntityEventA>| {
1130 assert_eq!(event.target(), event.event_target());
1131 })
1132 .id();
1133 world.trigger(EntityEventA(entity));
1134 }
1135}