1mod centralized_storage;
7mod condition;
8mod distributed_storage;
9mod entity_cloning;
10mod runner;
11mod system_param;
12
13pub use centralized_storage::*;
14pub use condition::*;
15pub use distributed_storage::*;
16pub use runner::*;
17pub use system_param::*;
18
19use crate::{
20 change_detection::MaybeLocation,
21 event::Event,
22 prelude::*,
23 world::{DeferredWorld, *},
24};
25
26impl World {
27 pub fn add_observer<M>(&mut self, observer: impl IntoObserver<M>) -> EntityWorldMut<'_> {
56 self.spawn(observer.into_observer())
57 }
58
59 #[track_caller]
63 pub fn trigger<'a, E: Event<Trigger<'a>: Default>>(&mut self, mut event: E) {
64 self.trigger_ref_with_caller(
65 &mut event,
66 &mut <E::Trigger<'a> as Default>::default(),
67 MaybeLocation::caller(),
68 );
69 }
70
71 #[track_caller]
75 pub fn trigger_with<'a, E: Event>(&mut self, mut event: E, mut trigger: E::Trigger<'a>) {
76 self.trigger_ref_with_caller(&mut event, &mut trigger, MaybeLocation::caller());
77 }
78
79 #[track_caller]
84 pub fn trigger_ref<'a, E: Event<Trigger<'a>: Default>>(&mut self, event: &mut E) {
85 self.trigger_ref_with_caller(
86 event,
87 &mut <E::Trigger<'a> as Default>::default(),
88 MaybeLocation::caller(),
89 );
90 }
91
92 pub fn trigger_ref_with<'a, E: Event>(&mut self, event: &mut E, trigger: &mut E::Trigger<'a>) {
98 self.trigger_ref_with_caller(event, trigger, MaybeLocation::caller());
99 }
100
101 pub(crate) fn trigger_ref_with_caller<'a, E: Event>(
102 &mut self,
103 event: &mut E,
104 trigger: &mut E::Trigger<'a>,
105 caller: MaybeLocation,
106 ) {
107 let event_key = self.register_event_key::<E>();
108 unsafe {
110 DeferredWorld::from(self).trigger_raw(event_key, event, trigger, caller);
111 }
112 }
113
114 unsafe fn split_for_event(
122 &mut self,
123 event_key: crate::event::EventKey,
124 ) -> Option<(DeferredWorld<'_>, &CachedObservers)> {
125 let world_cell = self.as_unsafe_world_cell();
126 let observers = world_cell.observers();
127 let observers = observers.try_get_observers(event_key)?;
128 Some((unsafe { world_cell.into_deferred() }, observers))
131 }
132
133 #[track_caller]
149 pub unsafe fn trigger_dynamic(
150 &mut self,
151 event_key: crate::event::EventKey,
152 mut event_data: bevy_ptr::PtrMut,
153 mut trigger_data: bevy_ptr::PtrMut,
154 ) {
155 let Some((mut world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
158 return;
159 };
160
161 let context = TriggerContext {
162 event_key,
163 caller: MaybeLocation::caller(),
164 };
165
166 unsafe {
168 world.as_unsafe_world_cell().increment_trigger_id();
169 }
170
171 for (observer, runner) in observers.global_observers() {
172 unsafe {
176 (runner)(
177 world.reborrow(),
178 *observer,
179 &context,
180 event_data.reborrow(),
181 trigger_data.reborrow(),
182 );
183 }
184 }
185 }
186
187 #[track_caller]
200 pub unsafe fn trigger_dynamic_targets(
201 &mut self,
202 event_key: crate::event::EventKey,
203 entity: Entity,
204 event_data: bevy_ptr::PtrMut,
205 trigger_data: bevy_ptr::PtrMut,
206 ) {
207 let Some((world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
210 return;
211 };
212
213 let context = TriggerContext {
214 event_key,
215 caller: MaybeLocation::caller(),
216 };
217
218 unsafe {
223 crate::event::trigger_entity_internal(
224 world,
225 observers,
226 event_data,
227 trigger_data,
228 entity,
229 &context,
230 );
231 }
232 }
233
234 #[track_caller]
249 pub unsafe fn trigger_dynamic_targets_components(
250 &mut self,
251 event_key: crate::event::EventKey,
252 entity: Entity,
253 components: &[crate::component::ComponentId],
254 mut event_data: bevy_ptr::PtrMut,
255 mut trigger_data: bevy_ptr::PtrMut,
256 ) {
257 let Some((mut world, observers)) = (unsafe { self.split_for_event(event_key) }) else {
260 return;
261 };
262
263 let context = TriggerContext {
264 event_key,
265 caller: MaybeLocation::caller(),
266 };
267
268 unsafe {
273 crate::event::trigger_entity_internal(
274 world.reborrow(),
275 observers,
276 event_data.reborrow(),
277 trigger_data.reborrow(),
278 entity,
279 &context,
280 );
281 }
282
283 for id in components {
285 if let Some(component_observers) = observers.component_observers().get(id) {
286 for (observer, runner) in component_observers.global_observers() {
287 unsafe {
289 (runner)(
290 world.reborrow(),
291 *observer,
292 &context,
293 event_data.reborrow(),
294 trigger_data.reborrow(),
295 );
296 }
297 }
298
299 if let Some(map) = component_observers
300 .entity_component_observers()
301 .get(&entity)
302 {
303 for (observer, runner) in map {
304 unsafe {
306 (runner)(
307 world.reborrow(),
308 *observer,
309 &context,
310 event_data.reborrow(),
311 trigger_data.reborrow(),
312 );
313 }
314 }
315 }
316 }
317 }
318 }
319
320 pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
322 let (observer_state, archetypes, observers) = unsafe {
324 let observer_state: *const Observer = self.get::<Observer>(observer_entity).unwrap();
325 for watched_entity in (*observer_state).descriptor.entities.iter().copied() {
327 let mut entity_mut = self.entity_mut(watched_entity);
328 let mut observed_by = entity_mut.entry::<ObservedBy>().or_default().into_mut();
329 observed_by.0.push(observer_entity);
330 }
331 (&*observer_state, &mut self.archetypes, &mut self.observers)
332 };
333 let descriptor = &observer_state.descriptor;
334
335 for &event_key in &descriptor.event_keys {
336 let cache = observers.get_observers_mut(event_key);
337
338 if descriptor.components.is_empty() && descriptor.entities.is_empty() {
339 cache
340 .global_observers
341 .insert(observer_entity, observer_state.runner);
342 } else if descriptor.components.is_empty() {
343 for &watched_entity in &observer_state.descriptor.entities {
345 let map = cache.entity_observers.entry(watched_entity).or_default();
346 map.insert(observer_entity, observer_state.runner);
347 }
348 } else {
349 for &component in &descriptor.components {
351 let observers =
352 cache
353 .component_observers
354 .entry(component)
355 .or_insert_with(|| {
356 if let Some(flag) = Observers::is_archetype_cached(event_key) {
357 archetypes.update_flags(component, flag, true);
358 }
359 CachedComponentObservers::default()
360 });
361 if descriptor.entities.is_empty() {
362 observers
364 .global_observers
365 .insert(observer_entity, observer_state.runner);
366 } else {
367 for &watched_entity in &descriptor.entities {
369 let map = observers
370 .entity_component_observers
371 .entry(watched_entity)
372 .or_default();
373 map.insert(observer_entity, observer_state.runner);
374 }
375 }
376 }
377 }
378 }
379 }
380
381 pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
383 for &observing in descriptor.entities.iter() {
385 let Ok(mut observing) = self.get_entity_mut(observing) else {
386 continue;
389 };
390 let Some(mut observed_by) = observing.get_mut::<ObservedBy>() else {
391 continue;
395 };
396
397 observed_by.0.retain(|e| *e != entity);
398 if observed_by.0.is_empty() {
399 observing.remove::<ObservedBy>();
400 }
401 }
402
403 let archetypes = &mut self.archetypes;
404 let observers = &mut self.observers;
405
406 for &event_key in &descriptor.event_keys {
407 let cache = observers.get_observers_mut(event_key);
408 if descriptor.components.is_empty() && descriptor.entities.is_empty() {
409 cache.global_observers.remove(&entity);
410 } else if descriptor.components.is_empty() {
411 for watched_entity in &descriptor.entities {
412 let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
414 continue;
415 };
416 observers.remove(&entity);
417 if observers.is_empty() {
418 cache.entity_observers.remove(watched_entity);
419 }
420 }
421 } else {
422 for component in &descriptor.components {
423 let Some(observers) = cache.component_observers.get_mut(component) else {
424 continue;
425 };
426 if descriptor.entities.is_empty() {
427 observers.global_observers.remove(&entity);
428 } else {
429 for watched_entity in &descriptor.entities {
430 let Some(map) =
431 observers.entity_component_observers.get_mut(watched_entity)
432 else {
433 continue;
434 };
435 map.remove(&entity);
436 if map.is_empty() {
437 observers.entity_component_observers.remove(watched_entity);
438 }
439 }
440 }
441
442 if observers.global_observers.is_empty()
443 && observers.entity_component_observers.is_empty()
444 {
445 cache.component_observers.remove(component);
446 if let Some(flag) = Observers::is_archetype_cached(event_key)
447 && let Some(by_component) = archetypes.by_component.get(component)
448 {
449 for archetype in by_component.keys() {
450 let archetype = &mut archetypes.archetypes[archetype.index()];
451 if archetype.contains(*component) {
452 let no_longer_observed = archetype
453 .iter_components()
454 .all(|id| !cache.component_observers.contains_key(&id));
455
456 if no_longer_observed {
457 archetype.flags.set(flag, false);
458 }
459 }
460 }
461 }
462 }
463 }
464 }
465 }
466 }
467}
468
469#[cfg(test)]
470mod tests {
471 use alloc::{vec, vec::Vec};
472 use core::{any::type_name, marker::PhantomData};
473
474 use bevy_ptr::OwningPtr;
475
476 use crate::{
477 archetype::{Archetype, ArchetypeId},
478 change_detection::MaybeLocation,
479 error::Result,
480 event::{EntityComponentsTrigger, Event, EventPattern, GlobalTrigger},
481 hierarchy::ChildOf,
482 lifecycle::RemoveEvent,
483 observer::{Discard, ObservedBy, Observer},
484 prelude::*,
485 world::DeferredWorld,
486 };
487
488 #[derive(Component)]
489 struct A;
490
491 #[derive(Component)]
492 struct B;
493
494 #[derive(Component)]
495 #[component(storage = "SparseSet")]
496 struct S;
497
498 #[derive(Event)]
499 struct EventA;
500
501 #[derive(EntityEvent)]
502 struct EntityEventA(Entity);
503
504 #[derive(EntityEvent)]
505 #[entity_event(trigger = EntityComponentsTrigger<'a>)]
506 struct EntityComponentsEvent(Entity);
507
508 struct EntityComponents<B: Bundle>(PhantomData<B>);
509
510 impl<B: Bundle> EventPattern for EntityComponents<B> {
511 type Event = EntityComponentsEvent;
512 type Components = B;
513 }
514
515 #[derive(Event)]
516 struct EventWithData {
517 counter: usize,
518 }
519
520 #[derive(Resource, Default)]
521 struct Order(Vec<&'static str>);
522
523 impl Order {
524 #[track_caller]
525 fn observed(&mut self, name: &'static str) {
526 self.0.push(name);
527 }
528 }
529
530 #[derive(Component, EntityEvent)]
531 #[entity_event(propagate, auto_propagate)]
532 struct EventPropagating(Entity);
533
534 #[test]
535 fn observer_order_spawn_despawn() {
536 let mut world = World::new();
537 world.init_resource::<Order>();
538
539 world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add"));
540 world.add_observer(|_: On<Insert<A>>, mut res: ResMut<Order>| res.observed("insert"));
541 world.add_observer(|_: On<Discard<A>>, mut res: ResMut<Order>| {
542 res.observed("discard");
543 });
544 world.add_observer(|_: On<Remove<A>>, mut res: ResMut<Order>| res.observed("remove"));
545
546 let entity = world.spawn(A).id();
547 world.despawn(entity);
548 assert_eq!(
549 vec!["add", "insert", "discard", "remove"],
550 world.resource::<Order>().0
551 );
552 }
553
554 #[test]
555 fn observer_order_insert_remove() {
556 let mut world = World::new();
557 world.init_resource::<Order>();
558
559 world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add"));
560 world.add_observer(|_: On<Insert<A>>, mut res: ResMut<Order>| res.observed("insert"));
561 world.add_observer(|_: On<Discard<A>>, mut res: ResMut<Order>| {
562 res.observed("discard");
563 });
564 world.add_observer(|_: On<Remove<A>>, mut res: ResMut<Order>| res.observed("remove"));
565
566 let mut entity = world.spawn_empty();
567 entity.insert(A);
568 entity.remove::<A>();
569 entity.flush();
570 assert_eq!(
571 vec!["add", "insert", "discard", "remove"],
572 world.resource::<Order>().0
573 );
574 }
575
576 #[test]
577 fn observer_order_insert_remove_sparse() {
578 let mut world = World::new();
579 world.init_resource::<Order>();
580
581 world.add_observer(|_: On<Add<S>>, mut res: ResMut<Order>| res.observed("add"));
582 world.add_observer(|_: On<Insert<S>>, mut res: ResMut<Order>| res.observed("insert"));
583 world.add_observer(|_: On<Discard<S>>, mut res: ResMut<Order>| {
584 res.observed("discard");
585 });
586 world.add_observer(|_: On<Remove<S>>, mut res: ResMut<Order>| res.observed("remove"));
587
588 let mut entity = world.spawn_empty();
589 entity.insert(S);
590 entity.remove::<S>();
591 entity.flush();
592 assert_eq!(
593 vec!["add", "insert", "discard", "remove"],
594 world.resource::<Order>().0
595 );
596 }
597
598 #[test]
599 fn observer_order_replace() {
600 let mut world = World::new();
601 world.init_resource::<Order>();
602
603 let entity = world.spawn(A).id();
604
605 world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add"));
606 world.add_observer(|_: On<Insert<A>>, mut res: ResMut<Order>| res.observed("insert"));
607 world.add_observer(|_: On<Discard<A>>, mut res: ResMut<Order>| {
608 res.observed("discard");
609 });
610 world.add_observer(|_: On<Remove<A>>, mut res: ResMut<Order>| res.observed("remove"));
611
612 let mut entity = world.entity_mut(entity);
613 entity.insert(A);
614 entity.flush();
615 assert_eq!(vec!["discard", "insert"], world.resource::<Order>().0);
616 }
617
618 #[test]
619 fn observer_order_recursive() {
620 let mut world = World::new();
621 world.init_resource::<Order>();
622 world.add_observer(
623 |add: On<Add<A>>, mut res: ResMut<Order>, mut commands: Commands| {
624 res.observed("add_a");
625 commands.entity(add.entity).insert(B);
626 },
627 );
628 world.add_observer(
629 |remove: On<Remove<A>>, mut res: ResMut<Order>, mut commands: Commands| {
630 res.observed("remove_a");
631 commands.entity(remove.entity).remove::<B>();
632 },
633 );
634
635 world.add_observer(
636 |add: On<Add<B>>, mut res: ResMut<Order>, mut commands: Commands| {
637 res.observed("add_b");
638 commands.entity(add.entity).remove::<A>();
639 },
640 );
641 world.add_observer(|_: On<Remove<B>>, mut res: ResMut<Order>| {
642 res.observed("remove_b");
643 });
644
645 let entity = world.spawn(A).flush();
646 let entity = world.get_entity(entity).unwrap();
647 assert!(!entity.contains::<A>());
648 assert!(!entity.contains::<B>());
649 assert_eq!(
650 vec!["add_a", "add_b", "remove_a", "remove_b"],
651 world.resource::<Order>().0
652 );
653 }
654
655 #[test]
656 fn observer_trigger_ref() {
657 let mut world = World::new();
658
659 world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
660 world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
661 world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
662
663 let mut event = EventWithData { counter: 0 };
664 world.trigger_ref(&mut event);
665 assert_eq!(7, event.counter);
666 }
667
668 #[test]
669 fn observer_multiple_listeners() {
670 let mut world = World::new();
671 world.init_resource::<Order>();
672
673 world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add_1"));
674 world.add_observer(|_: On<Add<A>>, mut res: ResMut<Order>| res.observed("add_2"));
675
676 world.spawn(A).flush();
677 assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
678 assert_eq!(world.query::<&A>().query(&world).count(), 1);
680 assert_eq!(world.query::<&Observer>().query(&world).count(), 2);
681 }
682
683 #[test]
684 fn observer_multiple_events() {
685 let mut world = World::new();
686 world.init_resource::<Order>();
687 let on_remove = world.register_event_key::<RemoveEvent>();
688 world.spawn(
689 unsafe {
691 Observer::new(|_: On<Add<A>>, mut res: ResMut<Order>| {
692 res.observed("add/remove");
693 })
694 .with_event_key(on_remove)
695 },
696 );
697
698 let entity = world.spawn(A).id();
699 world.despawn(entity);
700 assert_eq!(
701 vec!["add/remove", "add/remove"],
702 world.resource::<Order>().0
703 );
704 }
705
706 #[test]
707 fn observer_multiple_components() {
708 let mut world = World::new();
709 world.init_resource::<Order>();
710 world.register_component::<A>();
711 world.register_component::<B>();
712
713 world.add_observer(|_: On<Add<(A, B)>>, mut res: ResMut<Order>| {
714 res.observed("add_ab");
715 });
716
717 let entity = world.spawn(A).id();
718 world.entity_mut(entity).insert(B);
719 assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
720 }
721
722 #[test]
723 fn observer_despawn() {
724 let mut world = World::new();
725
726 let system: fn(On<Add<A>>) = |_| {
727 panic!("Observer triggered after being despawned.");
728 };
729 let observer = world.add_observer(system).id();
730 world.despawn(observer);
731 world.spawn(A).flush();
732 }
733
734 #[test]
736 fn observer_despawn_archetype_flags() {
737 let mut world = World::new();
738 world.init_resource::<Order>();
739
740 let entity = world.spawn((A, B)).flush();
741
742 world.add_observer(|_: On<Remove<A>>, mut res: ResMut<Order>| {
743 res.observed("remove_a");
744 });
745
746 let system: fn(On<Remove<B>>) = |_: On<Remove<B>>| {
747 panic!("Observer triggered after being despawned.");
748 };
749
750 let observer = world.add_observer(system).flush();
751 world.despawn(observer);
752
753 world.despawn(entity);
754
755 assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
756 }
757
758 #[test]
759 fn observer_multiple_matches() {
760 let mut world = World::new();
761 world.init_resource::<Order>();
762
763 world.add_observer(|_: On<Add<(A, B)>>, mut res: ResMut<Order>| {
764 res.observed("add_ab");
765 });
766
767 world.spawn((A, B)).flush();
768 assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
769 }
770
771 #[test]
772 fn observer_entity_routing() {
773 let mut world = World::new();
774 world.init_resource::<Order>();
775
776 let system: fn(On<EntityEventA>) = |_| {
777 panic!("Trigger routed to non-targeted entity.");
778 };
779
780 world.spawn_empty().observe(system);
781 let entity = world
782 .spawn_empty()
783 .observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
784 .id();
785 world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
786 assert_eq!(event.event_target(), entity);
787 res.observed("a_2");
788 });
789
790 world.trigger(EntityEventA(entity));
791 assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
792 }
793
794 #[test]
795 fn observer_multiple_targets() {
796 #[derive(Resource, Default)]
797 struct R(i32);
798
799 let mut world = World::new();
800 let component_a = world.register_component::<A>();
801 let component_b = world.register_component::<B>();
802 world.init_resource::<R>();
803
804 let entity_1 = world
806 .spawn_empty()
807 .observe(|_: On<EntityComponents<A>>, mut res: ResMut<R>| res.0 += 1)
808 .id();
809 let entity_2 = world
811 .spawn_empty()
812 .observe(|_: On<EntityComponents<B>>, mut res: ResMut<R>| res.0 += 10)
813 .id();
814 world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
816 world.add_observer(|_: On<EntityComponents<(A, B)>>, mut res: ResMut<R>| res.0 += 1000);
818 world.add_observer(
820 |_: On<EntityComponents<(A, B, (A, B))>>, mut res: ResMut<R>| res.0 += 10000,
821 );
822 world.add_observer(
823 |_: On<EntityComponents<(A, B, (A, B), ((A, B), (A, B)))>>, mut res: ResMut<R>| {
824 res.0 += 100000;
825 },
826 );
827 world.add_observer(
828 |_: On<EntityComponents<(A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>>,
829 mut res: ResMut<R>| res.0 += 1000000,
830 );
831
832 world.trigger_with(
834 EntityComponentsEvent(entity_1),
835 EntityComponentsTrigger {
836 components: &[component_a],
837 old_archetype: None,
838 new_archetype: None,
839 },
840 );
841 assert_eq!(1111101, world.resource::<R>().0);
843 world.resource_mut::<R>().0 = 0;
844
845 world.trigger_with(
847 EntityComponentsEvent(entity_1),
848 EntityComponentsTrigger {
849 components: &[],
850 old_archetype: None,
851 new_archetype: None,
852 },
853 );
854 world.trigger_with(
855 EntityComponentsEvent(entity_2),
856 EntityComponentsTrigger {
857 components: &[],
858 old_archetype: None,
859 new_archetype: None,
860 },
861 );
862
863 assert_eq!(200, world.resource::<R>().0);
865 world.resource_mut::<R>().0 = 0;
866
867 world.trigger_with(
870 EntityComponentsEvent(entity_1),
871 EntityComponentsTrigger {
872 components: &[component_a, component_b],
873 old_archetype: None,
874 new_archetype: None,
875 },
876 );
877 world.trigger_with(
878 EntityComponentsEvent(entity_2),
879 EntityComponentsTrigger {
880 components: &[component_a, component_b],
881 old_archetype: None,
882 new_archetype: None,
883 },
884 );
885 assert_eq!(2222211, world.resource::<R>().0);
886 world.resource_mut::<R>().0 = 0;
887 }
888
889 #[test]
890 fn observer_dynamic_component() {
891 let mut world = World::new();
892 world.init_resource::<Order>();
893
894 let component_id = world.register_component::<A>();
895 world.spawn(
896 Observer::new(|_: On<Add<()>>, mut res: ResMut<Order>| res.observed("event_a"))
897 .with_component(component_id),
898 );
899
900 let mut entity = world.spawn_empty();
901 OwningPtr::make(A, |ptr| {
902 unsafe { entity.insert_by_id(component_id, ptr) };
904 });
905
906 assert_eq!(vec!["event_a"], world.resource::<Order>().0);
907 }
908
909 #[test]
910 fn observer_dynamic_trigger() {
911 let mut world = World::new();
912 world.init_resource::<Order>();
913 let event_a = world.register_event_key::<EventA>();
914
915 let observe = unsafe {
917 Observer::with_dynamic_runner(
918 |mut world, _observer, _trigger_context, _event, _trigger| {
919 world.resource_mut::<Order>().observed("event_a");
920 },
921 )
922 .with_event_key(event_a)
923 };
924 world.spawn(observe);
925
926 world.commands().queue(move |world: &mut World| {
927 unsafe {
929 DeferredWorld::from(world).trigger_raw(
930 event_a,
931 &mut EventA,
932 &mut GlobalTrigger,
933 MaybeLocation::caller(),
934 );
935 }
936 });
937 world.flush();
938 assert_eq!(vec!["event_a"], world.resource::<Order>().0);
939 }
940
941 #[derive(Resource, Default)]
943 struct DynamicValues(Vec<u32>);
944
945 #[test]
946 fn observer_fully_dynamic_trigger() {
947 use core::alloc::Layout;
948
949 let mut world = World::new();
950 world.init_resource::<Order>();
951 world.init_resource::<DynamicValues>();
952
953 let event_id = world.register_component_with_descriptor(
955 unsafe {
957 crate::component::ComponentDescriptor::new_with_layout(
958 "DynamicEvent",
959 crate::component::StorageType::Table,
960 Layout::new::<u32>(),
961 None,
962 false,
963 false,
964 crate::component::ComponentCloneBehavior::Ignore,
965 None,
966 )
967 },
968 );
969 let event_key = unsafe { crate::event::EventKey::new(event_id) };
971
972 let observe = unsafe {
974 Observer::with_dynamic_runner(
975 |mut world, _observer, _trigger_context, event, _trigger| {
976 let value = *event.as_ref().deref::<u32>();
978 world.resource_mut::<Order>().observed("dynamic_event");
979 world.resource_mut::<DynamicValues>().0.push(value);
980 },
981 )
982 .with_event_key(event_key)
983 };
984 world.spawn(observe);
985
986 let mut event_data: u32 = 42;
987 let mut trigger_data: u32 = 0;
988 unsafe {
990 world.trigger_dynamic(
991 event_key,
992 bevy_ptr::PtrMut::from(&mut event_data),
993 bevy_ptr::PtrMut::from(&mut trigger_data),
994 );
995 }
996
997 assert_eq!(vec!["dynamic_event"], world.resource::<Order>().0);
998 assert_eq!(vec![42], world.resource::<DynamicValues>().0);
999 }
1000
1001 #[test]
1002 fn observer_fully_dynamic_trigger_targets() {
1003 use core::alloc::Layout;
1004
1005 let mut world = World::new();
1006 world.init_resource::<Order>();
1007 world.init_resource::<DynamicValues>();
1008
1009 let event_id = world.register_component_with_descriptor(
1010 unsafe {
1012 crate::component::ComponentDescriptor::new_with_layout(
1013 "DynamicEntityEvent",
1014 crate::component::StorageType::Table,
1015 Layout::new::<u32>(),
1016 None,
1017 false,
1018 false,
1019 crate::component::ComponentCloneBehavior::Ignore,
1020 None,
1021 )
1022 },
1023 );
1024 let event_key = unsafe { crate::event::EventKey::new(event_id) };
1026
1027 let target = world.spawn_empty().id();
1028 let other = world.spawn_empty().id();
1029
1030 let global = unsafe {
1032 Observer::with_dynamic_runner(
1033 |mut world, _observer, _trigger_context, event, _trigger| {
1034 let value = *event.as_ref().deref::<u32>();
1035 world.resource_mut::<Order>().observed("global");
1036 world.resource_mut::<DynamicValues>().0.push(value);
1037 },
1038 )
1039 .with_event_key(event_key)
1040 };
1041 world.spawn(global);
1042
1043 let entity_scoped = unsafe {
1045 Observer::with_dynamic_runner(
1046 |mut world, _observer, _trigger_context, event, _trigger| {
1047 let value = *event.as_ref().deref::<u32>();
1048 world.resource_mut::<Order>().observed("entity_scoped");
1049 world.resource_mut::<DynamicValues>().0.push(value);
1050 },
1051 )
1052 .with_event_key(event_key)
1053 .with_entity(target)
1054 };
1055 world.spawn(entity_scoped);
1056
1057 let mut event_data: u32 = 7;
1059 let mut trigger_data: u32 = 0;
1060 unsafe {
1062 world.trigger_dynamic_targets(
1063 event_key,
1064 target,
1065 bevy_ptr::PtrMut::from(&mut event_data),
1066 bevy_ptr::PtrMut::from(&mut trigger_data),
1067 );
1068 }
1069
1070 assert_eq!(vec!["global", "entity_scoped"], world.resource::<Order>().0);
1071 assert_eq!(vec![7, 7], world.resource::<DynamicValues>().0);
1072
1073 world.resource_mut::<Order>().0.clear();
1075 world.resource_mut::<DynamicValues>().0.clear();
1076 let mut event_data: u32 = 99;
1077 let mut trigger_data: u32 = 0;
1078 unsafe {
1080 world.trigger_dynamic_targets(
1081 event_key,
1082 other,
1083 bevy_ptr::PtrMut::from(&mut event_data),
1084 bevy_ptr::PtrMut::from(&mut trigger_data),
1085 );
1086 }
1087
1088 assert_eq!(vec!["global"], world.resource::<Order>().0);
1089 assert_eq!(vec![99], world.resource::<DynamicValues>().0);
1090 }
1091
1092 #[test]
1093 fn observer_fully_dynamic_trigger_targets_components() {
1094 use core::alloc::Layout;
1095
1096 let mut world = World::new();
1097 world.init_resource::<Order>();
1098 world.init_resource::<DynamicValues>();
1099
1100 let event_id = world.register_component_with_descriptor(
1101 unsafe {
1103 crate::component::ComponentDescriptor::new_with_layout(
1104 "DynamicComponentEvent",
1105 crate::component::StorageType::Table,
1106 Layout::new::<u32>(),
1107 None,
1108 false,
1109 false,
1110 crate::component::ComponentCloneBehavior::Ignore,
1111 None,
1112 )
1113 },
1114 );
1115 let event_key = unsafe { crate::event::EventKey::new(event_id) };
1117
1118 let comp_id = world.register_component_with_descriptor(
1120 unsafe {
1122 crate::component::ComponentDescriptor::new_with_layout(
1123 "DynamicComp",
1124 crate::component::StorageType::Table,
1125 Layout::new::<()>(),
1126 None,
1127 false,
1128 false,
1129 crate::component::ComponentCloneBehavior::Ignore,
1130 None,
1131 )
1132 },
1133 );
1134
1135 let target = world.spawn_empty().id();
1136
1137 let global = unsafe {
1139 Observer::with_dynamic_runner(
1140 |mut world, _observer, _trigger_context, event, _trigger| {
1141 let value = *event.as_ref().deref::<u32>();
1142 world.resource_mut::<Order>().observed("global");
1143 world.resource_mut::<DynamicValues>().0.push(value);
1144 },
1145 )
1146 .with_event_key(event_key)
1147 };
1148 world.spawn(global);
1149
1150 let comp_scoped = unsafe {
1152 Observer::with_dynamic_runner(
1153 |mut world, _observer, _trigger_context, event, _trigger| {
1154 let value = *event.as_ref().deref::<u32>();
1155 world.resource_mut::<Order>().observed("comp_scoped");
1156 world.resource_mut::<DynamicValues>().0.push(value);
1157 },
1158 )
1159 .with_event_key(event_key)
1160 .with_component(comp_id)
1161 };
1162 world.spawn(comp_scoped);
1163
1164 let mut event_data: u32 = 5;
1166 let mut trigger_data: u32 = 0;
1167 unsafe {
1169 world.trigger_dynamic_targets_components(
1170 event_key,
1171 target,
1172 &[comp_id],
1173 bevy_ptr::PtrMut::from(&mut event_data),
1174 bevy_ptr::PtrMut::from(&mut trigger_data),
1175 );
1176 }
1177
1178 assert_eq!(vec!["global", "comp_scoped"], world.resource::<Order>().0);
1179 assert_eq!(vec![5, 5], world.resource::<DynamicValues>().0);
1180
1181 world.resource_mut::<Order>().0.clear();
1183 world.resource_mut::<DynamicValues>().0.clear();
1184 let mut event_data: u32 = 10;
1185 let mut trigger_data: u32 = 0;
1186 unsafe {
1188 world.trigger_dynamic_targets_components(
1189 event_key,
1190 target,
1191 &[],
1192 bevy_ptr::PtrMut::from(&mut event_data),
1193 bevy_ptr::PtrMut::from(&mut trigger_data),
1194 );
1195 }
1196
1197 assert_eq!(vec!["global"], world.resource::<Order>().0);
1198 assert_eq!(vec![10], world.resource::<DynamicValues>().0);
1199 }
1200
1201 #[test]
1202 fn observer_propagating() {
1203 let mut world = World::new();
1204 world.init_resource::<Order>();
1205
1206 let parent = world.spawn_empty().id();
1207 let child = world.spawn(ChildOf(parent)).id();
1208
1209 world.entity_mut(parent).observe(
1210 move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1211 res.observed("parent");
1212
1213 assert_eq!(event.event_target(), parent);
1214 assert_eq!(event.original_event_target(), child);
1215 },
1216 );
1217
1218 world.entity_mut(child).observe(
1219 move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1220 res.observed("child");
1221 assert_eq!(event.event_target(), child);
1222 assert_eq!(event.original_event_target(), child);
1223 },
1224 );
1225
1226 world.trigger(EventPropagating(child));
1227
1228 assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
1229 }
1230
1231 #[test]
1232 fn observer_propagating_redundant_dispatch_same_entity() {
1233 let mut world = World::new();
1234 world.init_resource::<Order>();
1235
1236 let parent = world
1237 .spawn_empty()
1238 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1239 res.observed("parent");
1240 })
1241 .id();
1242
1243 let child = world
1244 .spawn(ChildOf(parent))
1245 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1246 res.observed("child");
1247 })
1248 .id();
1249
1250 world.trigger(EventPropagating(child));
1251 world.trigger(EventPropagating(child));
1252
1253 assert_eq!(
1254 vec!["child", "parent", "child", "parent"],
1255 world.resource::<Order>().0
1256 );
1257 }
1258
1259 #[test]
1260 fn observer_propagating_redundant_dispatch_parent_child() {
1261 let mut world = World::new();
1262 world.init_resource::<Order>();
1263
1264 let parent = world
1265 .spawn_empty()
1266 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1267 res.observed("parent");
1268 })
1269 .id();
1270
1271 let child = world
1272 .spawn(ChildOf(parent))
1273 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1274 res.observed("child");
1275 })
1276 .id();
1277
1278 world.trigger(EventPropagating(child));
1279 world.trigger(EventPropagating(parent));
1280
1281 assert_eq!(
1282 vec!["child", "parent", "parent"],
1283 world.resource::<Order>().0
1284 );
1285 }
1286
1287 #[test]
1288 fn observer_propagating_halt() {
1289 let mut world = World::new();
1290 world.init_resource::<Order>();
1291
1292 let parent = world
1293 .spawn_empty()
1294 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1295 res.observed("parent");
1296 })
1297 .id();
1298
1299 let child = world
1300 .spawn(ChildOf(parent))
1301 .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1302 res.observed("child");
1303 event.propagate(false);
1304 })
1305 .id();
1306
1307 world.trigger(EventPropagating(child));
1308
1309 assert_eq!(vec!["child"], world.resource::<Order>().0);
1310 }
1311
1312 #[test]
1313 fn observer_propagating_join() {
1314 let mut world = World::new();
1315 world.init_resource::<Order>();
1316
1317 let parent = world
1318 .spawn_empty()
1319 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1320 res.observed("parent");
1321 })
1322 .id();
1323
1324 let child_a = world
1325 .spawn(ChildOf(parent))
1326 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1327 res.observed("child_a");
1328 })
1329 .id();
1330
1331 let child_b = world
1332 .spawn(ChildOf(parent))
1333 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1334 res.observed("child_b");
1335 })
1336 .id();
1337
1338 world.trigger(EventPropagating(child_a));
1339 world.trigger(EventPropagating(child_b));
1340
1341 assert_eq!(
1342 vec!["child_a", "parent", "child_b", "parent"],
1343 world.resource::<Order>().0
1344 );
1345 }
1346
1347 #[test]
1348 fn observer_propagating_no_next() {
1349 let mut world = World::new();
1350 world.init_resource::<Order>();
1351
1352 let entity = world
1353 .spawn_empty()
1354 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1355 res.observed("event");
1356 })
1357 .id();
1358
1359 world.trigger(EventPropagating(entity));
1360 assert_eq!(vec!["event"], world.resource::<Order>().0);
1361 }
1362
1363 #[test]
1364 fn observer_propagating_parallel_propagation() {
1365 let mut world = World::new();
1366 world.init_resource::<Order>();
1367
1368 let parent_a = world
1369 .spawn_empty()
1370 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1371 res.observed("parent_a");
1372 })
1373 .id();
1374
1375 let child_a = world
1376 .spawn(ChildOf(parent_a))
1377 .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1378 res.observed("child_a");
1379 event.propagate(false);
1380 })
1381 .id();
1382
1383 let parent_b = world
1384 .spawn_empty()
1385 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1386 res.observed("parent_b");
1387 })
1388 .id();
1389
1390 let child_b = world
1391 .spawn(ChildOf(parent_b))
1392 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1393 res.observed("child_b");
1394 })
1395 .id();
1396
1397 world.trigger(EventPropagating(child_a));
1398 world.trigger(EventPropagating(child_b));
1399
1400 assert_eq!(
1401 vec!["child_a", "child_b", "parent_b"],
1402 world.resource::<Order>().0
1403 );
1404 }
1405
1406 #[test]
1407 fn observer_propagating_world() {
1408 let mut world = World::new();
1409 world.init_resource::<Order>();
1410
1411 world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1412 res.observed("event");
1413 });
1414
1415 let grandparent = world.spawn_empty().id();
1416 let parent = world.spawn(ChildOf(grandparent)).id();
1417 let child = world.spawn(ChildOf(parent)).id();
1418
1419 world.trigger(EventPropagating(child));
1420
1421 assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
1422 }
1423
1424 #[test]
1425 fn observer_propagating_world_skipping() {
1426 let mut world = World::new();
1427 world.init_resource::<Order>();
1428
1429 world.add_observer(
1430 |event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
1431 if query.get(event.event_target()).is_ok() {
1432 res.observed("event");
1433 }
1434 },
1435 );
1436
1437 let grandparent = world.spawn(A).id();
1438 let parent = world.spawn(ChildOf(grandparent)).id();
1439 let child = world.spawn((A, ChildOf(parent))).id();
1440
1441 world.trigger(EventPropagating(child));
1442
1443 assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
1444 }
1445
1446 #[test]
1448 fn observer_modifies_relationship() {
1449 fn on_add(add: On<Add<A>>, mut commands: Commands) {
1450 commands
1451 .entity(add.entity)
1452 .with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
1453 rsc.spawn_empty();
1454 });
1455 }
1456
1457 let mut world = World::new();
1458 world.add_observer(on_add);
1459 world.spawn(A);
1460 }
1461
1462 #[test]
1465 fn observer_on_remove_during_despawn_spawn_empty() {
1466 let mut world = World::new();
1467
1468 world.add_observer(|_: On<Remove<A>>, mut cmd: Commands| {
1470 cmd.spawn_empty();
1473 });
1474
1475 let ent = world.spawn(A).id();
1476
1477 world.despawn(ent);
1482 }
1483
1484 #[test]
1485 #[should_panic]
1486 fn observer_invalid_params() {
1487 #[derive(Resource)]
1488 struct ResA;
1489
1490 #[derive(Resource)]
1491 struct ResB;
1492
1493 let mut world = World::new();
1494 world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
1496 commands.insert_resource(ResB);
1497 });
1498 world.trigger(EventA);
1499 }
1500
1501 #[test]
1502 fn observer_apply_deferred_from_param_set() {
1503 #[derive(Resource)]
1504 struct ResA;
1505
1506 let mut world = World::new();
1507 world.add_observer(
1508 |_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1509 params.p1().insert_resource(ResA);
1510 },
1511 );
1512
1513 world.trigger(EventA);
1514 world.flush();
1515
1516 assert!(world.get_resource::<ResA>().is_some());
1517 }
1518
1519 #[test]
1520 #[track_caller]
1521 fn observer_caller_location_event() {
1522 #[derive(Event)]
1523 struct EventA;
1524
1525 let caller = MaybeLocation::caller();
1526 let mut world = World::new();
1527 world.add_observer(move |event: On<EventA>| {
1528 assert_eq!(event.caller(), caller);
1529 });
1530 world.trigger(EventA);
1531 }
1532
1533 #[test]
1534 #[track_caller]
1535 fn observer_caller_location_command_archetype_move() {
1536 #[derive(Component)]
1537 struct Component;
1538
1539 let caller = MaybeLocation::caller();
1540 let mut world = World::new();
1541 world.add_observer(move |event: On<Add<Component>>| {
1542 assert_eq!(event.caller(), caller);
1543 });
1544 world.add_observer(move |event: On<Remove<Component>>| {
1545 assert_eq!(event.caller(), caller);
1546 });
1547 world.commands().spawn(Component).clear();
1548 }
1549
1550 #[test]
1551 fn observer_watch_entities() {
1552 let mut world = World::new();
1553 world.init_resource::<Order>();
1554 let entities = world
1555 .spawn_batch(core::iter::repeat_n((), 4))
1556 .collect::<Vec<_>>();
1557 let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1558 order.observed("a");
1559 });
1560 world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1561
1562 world.trigger(EntityEventA(entities[0]));
1563 world.trigger(EntityEventA(entities[1]));
1564 assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1565 world.trigger(EntityEventA(entities[2]));
1566 world.trigger(EntityEventA(entities[3]));
1567 assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1568 }
1569
1570 #[test]
1571 fn unregister_global_observer() {
1572 let mut world = World::new();
1573 let mut observer = world.add_observer(|_: On<EventA>| {});
1574 observer.remove::<Observer>();
1575 let id = observer.id();
1576 let event_key = world.event_key::<EventA>().unwrap();
1577 assert!(!world
1578 .observers
1579 .get_observers_mut(event_key)
1580 .global_observers
1581 .contains_key(&id));
1582 }
1583
1584 #[test]
1585 fn unregister_entity_observer() {
1586 let mut world = World::new();
1587 let entity = world.spawn_empty().id();
1588 let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1589 let mut observer = world.spawn(observer);
1590 observer.remove::<Observer>();
1591 let event_key = world.event_key::<EventA>().unwrap();
1592 assert!(!world
1593 .observers
1594 .get_observers_mut(event_key)
1595 .entity_observers
1596 .contains_key(&entity));
1597 }
1598
1599 #[test]
1600 fn unregister_component_observer() {
1601 let mut world = World::new();
1602 let a = world.register_component::<A>();
1603 let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1604 let mut observer = world.spawn(observer);
1605 observer.remove::<Observer>();
1606 let event_key = world.event_key::<EventA>().unwrap();
1607 assert!(!world
1608 .observers
1609 .get_observers_mut(event_key)
1610 .component_observers()
1611 .contains_key(&a));
1612 }
1613
1614 #[derive(Resource)]
1615 struct RunConditionFlag(bool);
1616
1617 #[test]
1618 fn observer_run_condition_true() {
1619 let mut world = World::new();
1620 world.insert_resource(RunConditionFlag(true));
1621 world.init_resource::<Order>();
1622
1623 world.add_observer(
1624 (|_: On<EventA>, mut order: ResMut<Order>| {
1625 order.observed("event");
1626 })
1627 .run_if(|flag: Res<RunConditionFlag>| flag.0),
1628 );
1629
1630 world.trigger(EventA);
1631 assert_eq!(vec!["event"], world.resource::<Order>().0);
1632 }
1633
1634 #[test]
1635 fn observer_run_condition_false() {
1636 let mut world = World::new();
1637 world.insert_resource(RunConditionFlag(false));
1638 world.init_resource::<Order>();
1639
1640 world.add_observer(
1641 (|_: On<EventA>, mut order: ResMut<Order>| {
1642 order.observed("event");
1643 })
1644 .run_if(|flag: Res<RunConditionFlag>| flag.0),
1645 );
1646
1647 world.trigger(EventA);
1648 assert!(world.resource::<Order>().0.is_empty());
1649 }
1650
1651 #[test]
1652 fn observer_run_condition_chained() {
1653 let mut world = World::new();
1654 world.insert_resource(RunConditionFlag(true));
1655 world.init_resource::<Order>();
1656
1657 #[derive(Resource)]
1658 struct SecondFlag(bool);
1659 world.insert_resource(SecondFlag(true));
1660
1661 world.add_observer(
1662 (|_: On<EventA>, mut order: ResMut<Order>| {
1663 order.observed("event");
1664 })
1665 .run_if(|flag: Res<RunConditionFlag>| flag.0)
1666 .run_if(|flag: Res<SecondFlag>| flag.0),
1667 );
1668
1669 world.trigger(EventA);
1670 assert_eq!(vec!["event"], world.resource::<Order>().0);
1671
1672 world.resource_mut::<Order>().0.clear();
1673 world.resource_mut::<SecondFlag>().0 = false;
1674 world.trigger(EventA);
1675 assert!(world.resource::<Order>().0.is_empty());
1676 }
1677
1678 #[test]
1679 fn observer_run_condition_re_evaluated() {
1680 let mut world = World::new();
1681 world.insert_resource(RunConditionFlag(false));
1682 world.init_resource::<Order>();
1683
1684 world.add_observer(
1685 (|_: On<EventA>, mut order: ResMut<Order>| {
1686 order.observed("event");
1687 })
1688 .run_if(|flag: Res<RunConditionFlag>| flag.0),
1689 );
1690
1691 world.trigger(EventA);
1692 assert!(world.resource::<Order>().0.is_empty());
1693
1694 world.resource_mut::<RunConditionFlag>().0 = true;
1695 world.trigger(EventA);
1696 assert_eq!(vec!["event"], world.resource::<Order>().0);
1697 }
1698
1699 #[test]
1700 fn observer_run_condition_result_bool() {
1701 let mut world = World::new();
1702 world.init_resource::<Order>();
1703
1704 world.add_observer(
1705 (|_: On<EventA>, mut order: ResMut<Order>| {
1706 order.observed("err");
1707 })
1708 .run_if(|| -> Result<bool> { Err(core::fmt::Error.into()) }),
1709 );
1710 world.add_observer(
1711 (|_: On<EventA>, mut order: ResMut<Order>| {
1712 order.observed("false");
1713 })
1714 .run_if(|| -> Result<bool> { Ok(false) }),
1715 );
1716 world.add_observer(
1717 (|_: On<EventA>, mut order: ResMut<Order>| {
1718 order.observed("true");
1719 })
1720 .run_if(|| -> Result<bool> { Ok(true) }),
1721 );
1722
1723 world.trigger(EventA);
1724 assert_eq!(vec!["true"], world.resource::<Order>().0);
1725 }
1726
1727 #[test]
1728 fn observer_conditions_and_change_detection() {
1729 #[derive(Resource, Default)]
1730 struct Bool2(pub bool);
1731
1732 let mut world = World::new();
1733 world.init_resource::<Order>();
1734 world.insert_resource(RunConditionFlag(false));
1735 world.insert_resource(Bool2(false));
1736
1737 world.add_observer(
1738 (|_: On<EventA>, mut order: ResMut<Order>| {
1739 order.observed("event");
1740 })
1741 .run_if(|res1: Res<RunConditionFlag>| res1.is_changed())
1742 .run_if(|res2: Res<Bool2>| res2.is_changed()),
1743 );
1744
1745 world.trigger(EventA);
1747 assert_eq!(vec!["event"], world.resource::<Order>().0);
1748
1749 world.resource_mut::<Order>().0.clear();
1751 world.trigger(EventA);
1752 assert!(world.resource::<Order>().0.is_empty());
1753
1754 world.resource_mut::<RunConditionFlag>().0 = true;
1756 world.trigger(EventA);
1757 assert!(world.resource::<Order>().0.is_empty());
1758
1759 world.resource_mut::<Bool2>().0 = true;
1762 world.trigger(EventA);
1763 assert!(world.resource::<Order>().0.is_empty());
1764
1765 world.resource_mut::<RunConditionFlag>().0 = false;
1767 world.trigger(EventA);
1768 assert!(world.resource::<Order>().0.is_empty());
1769
1770 world.resource_mut::<Bool2>().0 = false;
1772 world.resource_mut::<RunConditionFlag>().0 = true;
1773 world.trigger(EventA);
1774 assert_eq!(vec!["event"], world.resource::<Order>().0);
1775 }
1776
1777 #[test]
1778 fn entity_observer_with_run_condition() {
1779 let mut world = World::new();
1780 world.insert_resource(RunConditionFlag(true));
1781 world.init_resource::<Order>();
1782
1783 let entity = world
1784 .spawn_empty()
1785 .observe(
1786 (|_: On<EntityEventA>, mut order: ResMut<Order>| {
1787 order.observed("entity_event");
1788 })
1789 .run_if(|flag: Res<RunConditionFlag>| flag.0),
1790 )
1791 .id();
1792
1793 world.trigger(EntityEventA(entity));
1794 assert_eq!(vec!["entity_event"], world.resource::<Order>().0);
1795
1796 world.resource_mut::<Order>().0.clear();
1797 world.resource_mut::<RunConditionFlag>().0 = false;
1798 world.trigger(EntityEventA(entity));
1799 assert!(world.resource::<Order>().0.is_empty());
1800 }
1801
1802 #[test]
1803 fn observer_builder_run_if() {
1804 let mut world = World::new();
1805 world.insert_resource(RunConditionFlag(true));
1806 world.init_resource::<Order>();
1807
1808 let observer = Observer::new(|_: On<EventA>, mut order: ResMut<Order>| {
1809 order.observed("event");
1810 })
1811 .run_if(|flag: Res<RunConditionFlag>| flag.0);
1812
1813 world.spawn(observer);
1814
1815 world.trigger(EventA);
1816 assert_eq!(vec!["event"], world.resource::<Order>().0);
1817
1818 world.resource_mut::<Order>().0.clear();
1819 world.resource_mut::<RunConditionFlag>().0 = false;
1820 world.trigger(EventA);
1821 assert!(world.resource::<Order>().0.is_empty());
1822 }
1823
1824 #[test]
1825 fn observer_new_old_archetypes() {
1826 #[derive(Resource, Default)]
1827 struct Changes(Vec<(&'static str, Option<ArchetypeId>, Option<ArchetypeId>)>);
1828
1829 let mut world = World::new();
1830 world.init_resource::<Changes>();
1831
1832 fn observer<E>(e: On<E>, mut c: ResMut<Changes>)
1833 where
1834 E: EventPattern,
1835 E::Event: for<'a> Event<Trigger<'a> = EntityComponentsTrigger<'a>>,
1836 {
1837 c.0.push((
1838 type_name::<E::Event>(),
1839 e.trigger().old_archetype.map(Archetype::id),
1840 e.trigger().new_archetype.map(Archetype::id),
1841 ));
1842 }
1843
1844 let empty = world.spawn(()).archetype().id();
1845 let a = world.spawn(A).archetype().id();
1846 let ab = world.spawn((A, B)).archetype().id();
1847
1848 world.add_observer(observer::<Add<A>>);
1849 world.add_observer(observer::<Insert<A>>);
1850 world.add_observer(observer::<Discard<A>>);
1851 world.add_observer(observer::<Remove<A>>);
1852 world.add_observer(observer::<Despawn<A>>);
1853
1854 let mut entity = world.spawn((A, B));
1855 entity.remove::<(A, B)>();
1856 entity.insert(A);
1857 entity.insert(A);
1858 entity.despawn();
1859
1860 assert_eq!(
1861 &world.resource_mut::<Changes>().0,
1862 &[
1863 ("bevy_ecs::lifecycle::AddEvent", None, Some(ab)),
1864 ("bevy_ecs::lifecycle::InsertEvent", None, Some(ab)),
1865 ("bevy_ecs::lifecycle::DiscardEvent", Some(ab), Some(empty)),
1866 ("bevy_ecs::lifecycle::RemoveEvent", Some(ab), Some(empty)),
1867 ("bevy_ecs::lifecycle::AddEvent", Some(empty), Some(a)),
1868 ("bevy_ecs::lifecycle::InsertEvent", Some(empty), Some(a)),
1869 ("bevy_ecs::lifecycle::DiscardEvent", Some(a), Some(a)),
1870 ("bevy_ecs::lifecycle::InsertEvent", Some(a), Some(a)),
1871 ("bevy_ecs::lifecycle::DespawnEvent", Some(a), None),
1872 ("bevy_ecs::lifecycle::DiscardEvent", Some(a), None),
1873 ("bevy_ecs::lifecycle::RemoveEvent", Some(a), None),
1874 ],
1875 );
1876 }
1877
1878 #[test]
1879 fn despawning_observer_removes_observed_by() {
1880 let mut world = World::new();
1881
1882 #[derive(EntityEvent)]
1883 struct Hi {
1884 entity: Entity,
1885 }
1886
1887 let target = world.spawn_empty().id();
1888 let observer = world
1889 .spawn(Observer::new(|_: On<Hi>| {}).with_entity(target))
1890 .id();
1891
1892 assert_eq!(
1893 world.entity(target).get::<ObservedBy>().unwrap().get(),
1894 &[observer]
1895 );
1896
1897 world.entity_mut(observer).despawn();
1898
1899 assert!(!world.entity(target).contains::<ObservedBy>());
1900 }
1901
1902 #[test]
1903 fn despawning_observer_removes_observed_by_repeated() {
1904 let mut world = World::new();
1905
1906 #[derive(EntityEvent)]
1907 struct Hi {
1908 entity: Entity,
1909 }
1910
1911 let target = world.spawn_empty().id();
1912 let observer = world
1913 .spawn(Observer::new(|_: On<Hi>| {}).with_entities([target, target]))
1915 .id();
1916
1917 assert_eq!(
1920 world.entity(target).get::<ObservedBy>().unwrap().get(),
1921 &[observer, observer]
1922 );
1923
1924 world.entity_mut(observer).despawn();
1925
1926 assert!(!world.entity(target).contains::<ObservedBy>());
1927 }
1928
1929 #[test]
1930 fn observer_system_despawns_observer() {
1931 let mut world = World::new();
1932 world.add_observer(DespawnObserversOnInit(0));
1933
1934 use crate::change_detection::{CheckChangeTicks, Tick};
1935 use crate::system::{RunSystemError, SystemAccess, SystemStateFlags};
1936 use crate::world::unsafe_world_cell::UnsafeWorldCell;
1937 use bevy_utils::prelude::DebugName;
1938
1939 #[expect(unused, reason = "This will only trigger UB if it has nonzero size")]
1940 struct DespawnObserversOnInit(usize);
1941 impl System for DespawnObserversOnInit {
1942 type In = On<'static, 'static, Add<()>>;
1943
1944 type Out = ();
1945
1946 fn name(&self) -> DebugName {
1947 DebugName::type_name::<DespawnObserversOnInit>()
1948 }
1949
1950 fn flags(&self) -> SystemStateFlags {
1951 SystemStateFlags::empty()
1952 }
1953
1954 unsafe fn run_unsafe(
1955 &mut self,
1956 _input: SystemIn<'_, Self>,
1957 _world: UnsafeWorldCell,
1958 ) -> Result<Self::Out, RunSystemError> {
1959 Ok(())
1960 }
1961
1962 #[cfg(feature = "hotpatching")]
1963 fn refresh_hotpatch(&mut self) {}
1964
1965 fn apply_deferred(&mut self, _world: &mut World) {}
1966
1967 fn queue_deferred(&mut self, _world: DeferredWorld) {
1968 todo!()
1969 }
1970
1971 fn initialize(&mut self, world: &mut World) -> SystemAccess {
1972 let observers: Vec<_> = world
1973 .query_filtered::<Entity, With<Observer>>()
1974 .query(world)
1975 .iter()
1976 .collect();
1977 for observer in observers {
1978 world.despawn(observer);
1979 }
1980
1981 SystemAccess::None
1982 }
1983
1984 fn check_change_tick(&mut self, _check: CheckChangeTicks) {}
1985
1986 fn get_last_run(&self) -> Tick {
1987 unimplemented!()
1988 }
1989
1990 fn set_last_run(&mut self, _last_run: Tick) {}
1991 }
1992 }
1993}