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