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;
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, GlobalTrigger},
481 hierarchy::ChildOf,
482 observer::{Discard, ObservedBy, Observer},
483 prelude::*,
484 world::DeferredWorld,
485 };
486
487 #[derive(Component)]
488 struct A;
489
490 #[derive(Component)]
491 struct B;
492
493 #[derive(Component)]
494 #[component(storage = "SparseSet")]
495 struct S;
496
497 #[derive(Event)]
498 struct EventA;
499
500 #[derive(EntityEvent)]
501 struct EntityEventA(Entity);
502
503 #[derive(EntityEvent)]
504 #[entity_event(trigger = EntityComponentsTrigger<'a>)]
505 struct EntityComponentsEvent(Entity);
506
507 #[derive(Event)]
508 struct EventWithData {
509 counter: usize,
510 }
511
512 #[derive(Resource, Default)]
513 struct Order(Vec<&'static str>);
514
515 impl Order {
516 #[track_caller]
517 fn observed(&mut self, name: &'static str) {
518 self.0.push(name);
519 }
520 }
521
522 #[derive(Component, EntityEvent)]
523 #[entity_event(propagate, auto_propagate)]
524 struct EventPropagating(Entity);
525
526 #[test]
527 fn observer_order_spawn_despawn() {
528 let mut world = World::new();
529 world.init_resource::<Order>();
530
531 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
532 world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
533 world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
534 res.observed("discard");
535 });
536 world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
537
538 let entity = world.spawn(A).id();
539 world.despawn(entity);
540 assert_eq!(
541 vec!["add", "insert", "discard", "remove"],
542 world.resource::<Order>().0
543 );
544 }
545
546 #[test]
547 fn observer_order_insert_remove() {
548 let mut world = World::new();
549 world.init_resource::<Order>();
550
551 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
552 world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
553 world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
554 res.observed("discard");
555 });
556 world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
557
558 let mut entity = world.spawn_empty();
559 entity.insert(A);
560 entity.remove::<A>();
561 entity.flush();
562 assert_eq!(
563 vec!["add", "insert", "discard", "remove"],
564 world.resource::<Order>().0
565 );
566 }
567
568 #[test]
569 fn observer_order_insert_remove_sparse() {
570 let mut world = World::new();
571 world.init_resource::<Order>();
572
573 world.add_observer(|_: On<Add, S>, mut res: ResMut<Order>| res.observed("add"));
574 world.add_observer(|_: On<Insert, S>, mut res: ResMut<Order>| res.observed("insert"));
575 world.add_observer(|_: On<Discard, S>, mut res: ResMut<Order>| {
576 res.observed("discard");
577 });
578 world.add_observer(|_: On<Remove, S>, mut res: ResMut<Order>| res.observed("remove"));
579
580 let mut entity = world.spawn_empty();
581 entity.insert(S);
582 entity.remove::<S>();
583 entity.flush();
584 assert_eq!(
585 vec!["add", "insert", "discard", "remove"],
586 world.resource::<Order>().0
587 );
588 }
589
590 #[test]
591 fn observer_order_replace() {
592 let mut world = World::new();
593 world.init_resource::<Order>();
594
595 let entity = world.spawn(A).id();
596
597 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
598 world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
599 world.add_observer(|_: On<Discard, A>, mut res: ResMut<Order>| {
600 res.observed("discard");
601 });
602 world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
603
604 let mut entity = world.entity_mut(entity);
605 entity.insert(A);
606 entity.flush();
607 assert_eq!(vec!["discard", "insert"], world.resource::<Order>().0);
608 }
609
610 #[test]
611 fn observer_order_recursive() {
612 let mut world = World::new();
613 world.init_resource::<Order>();
614 world.add_observer(
615 |add: On<Add, A>, mut res: ResMut<Order>, mut commands: Commands| {
616 res.observed("add_a");
617 commands.entity(add.entity).insert(B);
618 },
619 );
620 world.add_observer(
621 |remove: On<Remove, A>, mut res: ResMut<Order>, mut commands: Commands| {
622 res.observed("remove_a");
623 commands.entity(remove.entity).remove::<B>();
624 },
625 );
626
627 world.add_observer(
628 |add: On<Add, B>, mut res: ResMut<Order>, mut commands: Commands| {
629 res.observed("add_b");
630 commands.entity(add.entity).remove::<A>();
631 },
632 );
633 world.add_observer(|_: On<Remove, B>, mut res: ResMut<Order>| {
634 res.observed("remove_b");
635 });
636
637 let entity = world.spawn(A).flush();
638 let entity = world.get_entity(entity).unwrap();
639 assert!(!entity.contains::<A>());
640 assert!(!entity.contains::<B>());
641 assert_eq!(
642 vec!["add_a", "add_b", "remove_a", "remove_b"],
643 world.resource::<Order>().0
644 );
645 }
646
647 #[test]
648 fn observer_trigger_ref() {
649 let mut world = World::new();
650
651 world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
652 world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
653 world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
654
655 let mut event = EventWithData { counter: 0 };
656 world.trigger_ref(&mut event);
657 assert_eq!(7, event.counter);
658 }
659
660 #[test]
661 fn observer_multiple_listeners() {
662 let mut world = World::new();
663 world.init_resource::<Order>();
664
665 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
666 world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));
667
668 world.spawn(A).flush();
669 assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
670 assert_eq!(world.query::<&A>().query(&world).count(), 1);
672 assert_eq!(world.query::<&Observer>().query(&world).count(), 2);
673 }
674
675 #[test]
676 fn observer_multiple_events() {
677 let mut world = World::new();
678 world.init_resource::<Order>();
679 let on_remove = world.register_event_key::<Remove>();
680 world.spawn(
681 unsafe {
683 Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
684 res.observed("add/remove");
685 })
686 .with_event_key(on_remove)
687 },
688 );
689
690 let entity = world.spawn(A).id();
691 world.despawn(entity);
692 assert_eq!(
693 vec!["add/remove", "add/remove"],
694 world.resource::<Order>().0
695 );
696 }
697
698 #[test]
699 fn observer_multiple_components() {
700 let mut world = World::new();
701 world.init_resource::<Order>();
702 world.register_component::<A>();
703 world.register_component::<B>();
704
705 world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
706 res.observed("add_ab");
707 });
708
709 let entity = world.spawn(A).id();
710 world.entity_mut(entity).insert(B);
711 assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
712 }
713
714 #[test]
715 fn observer_despawn() {
716 let mut world = World::new();
717
718 let system: fn(On<Add, A>) = |_| {
719 panic!("Observer triggered after being despawned.");
720 };
721 let observer = world.add_observer(system).id();
722 world.despawn(observer);
723 world.spawn(A).flush();
724 }
725
726 #[test]
728 fn observer_despawn_archetype_flags() {
729 let mut world = World::new();
730 world.init_resource::<Order>();
731
732 let entity = world.spawn((A, B)).flush();
733
734 world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| {
735 res.observed("remove_a");
736 });
737
738 let system: fn(On<Remove, B>) = |_: On<Remove, B>| {
739 panic!("Observer triggered after being despawned.");
740 };
741
742 let observer = world.add_observer(system).flush();
743 world.despawn(observer);
744
745 world.despawn(entity);
746
747 assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
748 }
749
750 #[test]
751 fn observer_multiple_matches() {
752 let mut world = World::new();
753 world.init_resource::<Order>();
754
755 world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
756 res.observed("add_ab");
757 });
758
759 world.spawn((A, B)).flush();
760 assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
761 }
762
763 #[test]
764 fn observer_entity_routing() {
765 let mut world = World::new();
766 world.init_resource::<Order>();
767
768 let system: fn(On<EntityEventA>) = |_| {
769 panic!("Trigger routed to non-targeted entity.");
770 };
771
772 world.spawn_empty().observe(system);
773 let entity = world
774 .spawn_empty()
775 .observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
776 .id();
777 world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
778 assert_eq!(event.event_target(), entity);
779 res.observed("a_2");
780 });
781
782 world.trigger(EntityEventA(entity));
783 assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
784 }
785
786 #[test]
787 fn observer_multiple_targets() {
788 #[derive(Resource, Default)]
789 struct R(i32);
790
791 let mut world = World::new();
792 let component_a = world.register_component::<A>();
793 let component_b = world.register_component::<B>();
794 world.init_resource::<R>();
795
796 let entity_1 = world
798 .spawn_empty()
799 .observe(|_: On<EntityComponentsEvent, A>, mut res: ResMut<R>| res.0 += 1)
800 .id();
801 let entity_2 = world
803 .spawn_empty()
804 .observe(|_: On<EntityComponentsEvent, B>, mut res: ResMut<R>| res.0 += 10)
805 .id();
806 world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
808 world
810 .add_observer(|_: On<EntityComponentsEvent, (A, B)>, mut res: ResMut<R>| res.0 += 1000);
811 world.add_observer(
813 |_: On<EntityComponentsEvent, (A, B, (A, B))>, mut res: ResMut<R>| res.0 += 10000,
814 );
815 world.add_observer(
816 |_: On<EntityComponentsEvent, (A, B, (A, B), ((A, B), (A, B)))>, mut res: ResMut<R>| {
817 res.0 += 100000;
818 },
819 );
820 world.add_observer(
821 |_: On<EntityComponentsEvent, (A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>,
822 mut res: ResMut<R>| res.0 += 1000000,
823 );
824
825 world.trigger_with(
827 EntityComponentsEvent(entity_1),
828 EntityComponentsTrigger {
829 components: &[component_a],
830 old_archetype: None,
831 new_archetype: None,
832 },
833 );
834 assert_eq!(1111101, world.resource::<R>().0);
836 world.resource_mut::<R>().0 = 0;
837
838 world.trigger_with(
840 EntityComponentsEvent(entity_1),
841 EntityComponentsTrigger {
842 components: &[],
843 old_archetype: None,
844 new_archetype: None,
845 },
846 );
847 world.trigger_with(
848 EntityComponentsEvent(entity_2),
849 EntityComponentsTrigger {
850 components: &[],
851 old_archetype: None,
852 new_archetype: None,
853 },
854 );
855
856 assert_eq!(200, world.resource::<R>().0);
858 world.resource_mut::<R>().0 = 0;
859
860 world.trigger_with(
863 EntityComponentsEvent(entity_1),
864 EntityComponentsTrigger {
865 components: &[component_a, component_b],
866 old_archetype: None,
867 new_archetype: None,
868 },
869 );
870 world.trigger_with(
871 EntityComponentsEvent(entity_2),
872 EntityComponentsTrigger {
873 components: &[component_a, component_b],
874 old_archetype: None,
875 new_archetype: None,
876 },
877 );
878 assert_eq!(2222211, world.resource::<R>().0);
879 world.resource_mut::<R>().0 = 0;
880 }
881
882 #[test]
883 fn observer_dynamic_component() {
884 let mut world = World::new();
885 world.init_resource::<Order>();
886
887 let component_id = world.register_component::<A>();
888 world.spawn(
889 Observer::new(|_: On<Add>, mut res: ResMut<Order>| res.observed("event_a"))
890 .with_component(component_id),
891 );
892
893 let mut entity = world.spawn_empty();
894 OwningPtr::make(A, |ptr| {
895 unsafe { entity.insert_by_id(component_id, ptr) };
897 });
898
899 assert_eq!(vec!["event_a"], world.resource::<Order>().0);
900 }
901
902 #[test]
903 fn observer_dynamic_trigger() {
904 let mut world = World::new();
905 world.init_resource::<Order>();
906 let event_a = world.register_event_key::<EventA>();
907
908 let observe = unsafe {
910 Observer::with_dynamic_runner(
911 |mut world, _observer, _trigger_context, _event, _trigger| {
912 world.resource_mut::<Order>().observed("event_a");
913 },
914 )
915 .with_event_key(event_a)
916 };
917 world.spawn(observe);
918
919 world.commands().queue(move |world: &mut World| {
920 unsafe {
922 DeferredWorld::from(world).trigger_raw(
923 event_a,
924 &mut EventA,
925 &mut GlobalTrigger,
926 MaybeLocation::caller(),
927 );
928 }
929 });
930 world.flush();
931 assert_eq!(vec!["event_a"], world.resource::<Order>().0);
932 }
933
934 #[derive(Resource, Default)]
936 struct DynamicValues(Vec<u32>);
937
938 #[test]
939 fn observer_fully_dynamic_trigger() {
940 use core::alloc::Layout;
941
942 let mut world = World::new();
943 world.init_resource::<Order>();
944 world.init_resource::<DynamicValues>();
945
946 let event_id = world.register_component_with_descriptor(
948 unsafe {
950 crate::component::ComponentDescriptor::new_with_layout(
951 "DynamicEvent",
952 crate::component::StorageType::Table,
953 Layout::new::<u32>(),
954 None,
955 false,
956 crate::component::ComponentCloneBehavior::Ignore,
957 None,
958 )
959 },
960 );
961 let event_key = unsafe { crate::event::EventKey::new(event_id) };
963
964 let observe = unsafe {
966 Observer::with_dynamic_runner(
967 |mut world, _observer, _trigger_context, event, _trigger| {
968 let value = *event.as_ref().deref::<u32>();
970 world.resource_mut::<Order>().observed("dynamic_event");
971 world.resource_mut::<DynamicValues>().0.push(value);
972 },
973 )
974 .with_event_key(event_key)
975 };
976 world.spawn(observe);
977
978 let mut event_data: u32 = 42;
979 let mut trigger_data: u32 = 0;
980 unsafe {
982 world.trigger_dynamic(
983 event_key,
984 bevy_ptr::PtrMut::from(&mut event_data),
985 bevy_ptr::PtrMut::from(&mut trigger_data),
986 );
987 }
988
989 assert_eq!(vec!["dynamic_event"], world.resource::<Order>().0);
990 assert_eq!(vec![42], world.resource::<DynamicValues>().0);
991 }
992
993 #[test]
994 fn observer_fully_dynamic_trigger_targets() {
995 use core::alloc::Layout;
996
997 let mut world = World::new();
998 world.init_resource::<Order>();
999 world.init_resource::<DynamicValues>();
1000
1001 let event_id = world.register_component_with_descriptor(
1002 unsafe {
1004 crate::component::ComponentDescriptor::new_with_layout(
1005 "DynamicEntityEvent",
1006 crate::component::StorageType::Table,
1007 Layout::new::<u32>(),
1008 None,
1009 false,
1010 crate::component::ComponentCloneBehavior::Ignore,
1011 None,
1012 )
1013 },
1014 );
1015 let event_key = unsafe { crate::event::EventKey::new(event_id) };
1017
1018 let target = world.spawn_empty().id();
1019 let other = world.spawn_empty().id();
1020
1021 let global = unsafe {
1023 Observer::with_dynamic_runner(
1024 |mut world, _observer, _trigger_context, event, _trigger| {
1025 let value = *event.as_ref().deref::<u32>();
1026 world.resource_mut::<Order>().observed("global");
1027 world.resource_mut::<DynamicValues>().0.push(value);
1028 },
1029 )
1030 .with_event_key(event_key)
1031 };
1032 world.spawn(global);
1033
1034 let entity_scoped = unsafe {
1036 Observer::with_dynamic_runner(
1037 |mut world, _observer, _trigger_context, event, _trigger| {
1038 let value = *event.as_ref().deref::<u32>();
1039 world.resource_mut::<Order>().observed("entity_scoped");
1040 world.resource_mut::<DynamicValues>().0.push(value);
1041 },
1042 )
1043 .with_event_key(event_key)
1044 .with_entity(target)
1045 };
1046 world.spawn(entity_scoped);
1047
1048 let mut event_data: u32 = 7;
1050 let mut trigger_data: u32 = 0;
1051 unsafe {
1053 world.trigger_dynamic_targets(
1054 event_key,
1055 target,
1056 bevy_ptr::PtrMut::from(&mut event_data),
1057 bevy_ptr::PtrMut::from(&mut trigger_data),
1058 );
1059 }
1060
1061 assert_eq!(vec!["global", "entity_scoped"], world.resource::<Order>().0);
1062 assert_eq!(vec![7, 7], world.resource::<DynamicValues>().0);
1063
1064 world.resource_mut::<Order>().0.clear();
1066 world.resource_mut::<DynamicValues>().0.clear();
1067 let mut event_data: u32 = 99;
1068 let mut trigger_data: u32 = 0;
1069 unsafe {
1071 world.trigger_dynamic_targets(
1072 event_key,
1073 other,
1074 bevy_ptr::PtrMut::from(&mut event_data),
1075 bevy_ptr::PtrMut::from(&mut trigger_data),
1076 );
1077 }
1078
1079 assert_eq!(vec!["global"], world.resource::<Order>().0);
1080 assert_eq!(vec![99], world.resource::<DynamicValues>().0);
1081 }
1082
1083 #[test]
1084 fn observer_fully_dynamic_trigger_targets_components() {
1085 use core::alloc::Layout;
1086
1087 let mut world = World::new();
1088 world.init_resource::<Order>();
1089 world.init_resource::<DynamicValues>();
1090
1091 let event_id = world.register_component_with_descriptor(
1092 unsafe {
1094 crate::component::ComponentDescriptor::new_with_layout(
1095 "DynamicComponentEvent",
1096 crate::component::StorageType::Table,
1097 Layout::new::<u32>(),
1098 None,
1099 false,
1100 crate::component::ComponentCloneBehavior::Ignore,
1101 None,
1102 )
1103 },
1104 );
1105 let event_key = unsafe { crate::event::EventKey::new(event_id) };
1107
1108 let comp_id = world.register_component_with_descriptor(
1110 unsafe {
1112 crate::component::ComponentDescriptor::new_with_layout(
1113 "DynamicComp",
1114 crate::component::StorageType::Table,
1115 Layout::new::<()>(),
1116 None,
1117 false,
1118 crate::component::ComponentCloneBehavior::Ignore,
1119 None,
1120 )
1121 },
1122 );
1123
1124 let target = world.spawn_empty().id();
1125
1126 let global = unsafe {
1128 Observer::with_dynamic_runner(
1129 |mut world, _observer, _trigger_context, event, _trigger| {
1130 let value = *event.as_ref().deref::<u32>();
1131 world.resource_mut::<Order>().observed("global");
1132 world.resource_mut::<DynamicValues>().0.push(value);
1133 },
1134 )
1135 .with_event_key(event_key)
1136 };
1137 world.spawn(global);
1138
1139 let comp_scoped = unsafe {
1141 Observer::with_dynamic_runner(
1142 |mut world, _observer, _trigger_context, event, _trigger| {
1143 let value = *event.as_ref().deref::<u32>();
1144 world.resource_mut::<Order>().observed("comp_scoped");
1145 world.resource_mut::<DynamicValues>().0.push(value);
1146 },
1147 )
1148 .with_event_key(event_key)
1149 .with_component(comp_id)
1150 };
1151 world.spawn(comp_scoped);
1152
1153 let mut event_data: u32 = 5;
1155 let mut trigger_data: u32 = 0;
1156 unsafe {
1158 world.trigger_dynamic_targets_components(
1159 event_key,
1160 target,
1161 &[comp_id],
1162 bevy_ptr::PtrMut::from(&mut event_data),
1163 bevy_ptr::PtrMut::from(&mut trigger_data),
1164 );
1165 }
1166
1167 assert_eq!(vec!["global", "comp_scoped"], world.resource::<Order>().0);
1168 assert_eq!(vec![5, 5], world.resource::<DynamicValues>().0);
1169
1170 world.resource_mut::<Order>().0.clear();
1172 world.resource_mut::<DynamicValues>().0.clear();
1173 let mut event_data: u32 = 10;
1174 let mut trigger_data: u32 = 0;
1175 unsafe {
1177 world.trigger_dynamic_targets_components(
1178 event_key,
1179 target,
1180 &[],
1181 bevy_ptr::PtrMut::from(&mut event_data),
1182 bevy_ptr::PtrMut::from(&mut trigger_data),
1183 );
1184 }
1185
1186 assert_eq!(vec!["global"], world.resource::<Order>().0);
1187 assert_eq!(vec![10], world.resource::<DynamicValues>().0);
1188 }
1189
1190 #[test]
1191 fn observer_propagating() {
1192 let mut world = World::new();
1193 world.init_resource::<Order>();
1194
1195 let parent = world.spawn_empty().id();
1196 let child = world.spawn(ChildOf(parent)).id();
1197
1198 world.entity_mut(parent).observe(
1199 move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1200 res.observed("parent");
1201
1202 assert_eq!(event.event_target(), parent);
1203 assert_eq!(event.original_event_target(), child);
1204 },
1205 );
1206
1207 world.entity_mut(child).observe(
1208 move |event: On<EventPropagating>, mut res: ResMut<Order>| {
1209 res.observed("child");
1210 assert_eq!(event.event_target(), child);
1211 assert_eq!(event.original_event_target(), child);
1212 },
1213 );
1214
1215 world.trigger(EventPropagating(child));
1216
1217 assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
1218 }
1219
1220 #[test]
1221 fn observer_propagating_redundant_dispatch_same_entity() {
1222 let mut world = World::new();
1223 world.init_resource::<Order>();
1224
1225 let parent = world
1226 .spawn_empty()
1227 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1228 res.observed("parent");
1229 })
1230 .id();
1231
1232 let child = world
1233 .spawn(ChildOf(parent))
1234 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1235 res.observed("child");
1236 })
1237 .id();
1238
1239 world.trigger(EventPropagating(child));
1240 world.trigger(EventPropagating(child));
1241
1242 assert_eq!(
1243 vec!["child", "parent", "child", "parent"],
1244 world.resource::<Order>().0
1245 );
1246 }
1247
1248 #[test]
1249 fn observer_propagating_redundant_dispatch_parent_child() {
1250 let mut world = World::new();
1251 world.init_resource::<Order>();
1252
1253 let parent = world
1254 .spawn_empty()
1255 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1256 res.observed("parent");
1257 })
1258 .id();
1259
1260 let child = world
1261 .spawn(ChildOf(parent))
1262 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1263 res.observed("child");
1264 })
1265 .id();
1266
1267 world.trigger(EventPropagating(child));
1268 world.trigger(EventPropagating(parent));
1269
1270 assert_eq!(
1271 vec!["child", "parent", "parent"],
1272 world.resource::<Order>().0
1273 );
1274 }
1275
1276 #[test]
1277 fn observer_propagating_halt() {
1278 let mut world = World::new();
1279 world.init_resource::<Order>();
1280
1281 let parent = world
1282 .spawn_empty()
1283 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1284 res.observed("parent");
1285 })
1286 .id();
1287
1288 let child = world
1289 .spawn(ChildOf(parent))
1290 .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1291 res.observed("child");
1292 event.propagate(false);
1293 })
1294 .id();
1295
1296 world.trigger(EventPropagating(child));
1297
1298 assert_eq!(vec!["child"], world.resource::<Order>().0);
1299 }
1300
1301 #[test]
1302 fn observer_propagating_join() {
1303 let mut world = World::new();
1304 world.init_resource::<Order>();
1305
1306 let parent = world
1307 .spawn_empty()
1308 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1309 res.observed("parent");
1310 })
1311 .id();
1312
1313 let child_a = world
1314 .spawn(ChildOf(parent))
1315 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1316 res.observed("child_a");
1317 })
1318 .id();
1319
1320 let child_b = world
1321 .spawn(ChildOf(parent))
1322 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1323 res.observed("child_b");
1324 })
1325 .id();
1326
1327 world.trigger(EventPropagating(child_a));
1328 world.trigger(EventPropagating(child_b));
1329
1330 assert_eq!(
1331 vec!["child_a", "parent", "child_b", "parent"],
1332 world.resource::<Order>().0
1333 );
1334 }
1335
1336 #[test]
1337 fn observer_propagating_no_next() {
1338 let mut world = World::new();
1339 world.init_resource::<Order>();
1340
1341 let entity = world
1342 .spawn_empty()
1343 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1344 res.observed("event");
1345 })
1346 .id();
1347
1348 world.trigger(EventPropagating(entity));
1349 assert_eq!(vec!["event"], world.resource::<Order>().0);
1350 }
1351
1352 #[test]
1353 fn observer_propagating_parallel_propagation() {
1354 let mut world = World::new();
1355 world.init_resource::<Order>();
1356
1357 let parent_a = world
1358 .spawn_empty()
1359 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1360 res.observed("parent_a");
1361 })
1362 .id();
1363
1364 let child_a = world
1365 .spawn(ChildOf(parent_a))
1366 .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
1367 res.observed("child_a");
1368 event.propagate(false);
1369 })
1370 .id();
1371
1372 let parent_b = world
1373 .spawn_empty()
1374 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1375 res.observed("parent_b");
1376 })
1377 .id();
1378
1379 let child_b = world
1380 .spawn(ChildOf(parent_b))
1381 .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1382 res.observed("child_b");
1383 })
1384 .id();
1385
1386 world.trigger(EventPropagating(child_a));
1387 world.trigger(EventPropagating(child_b));
1388
1389 assert_eq!(
1390 vec!["child_a", "child_b", "parent_b"],
1391 world.resource::<Order>().0
1392 );
1393 }
1394
1395 #[test]
1396 fn observer_propagating_world() {
1397 let mut world = World::new();
1398 world.init_resource::<Order>();
1399
1400 world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
1401 res.observed("event");
1402 });
1403
1404 let grandparent = world.spawn_empty().id();
1405 let parent = world.spawn(ChildOf(grandparent)).id();
1406 let child = world.spawn(ChildOf(parent)).id();
1407
1408 world.trigger(EventPropagating(child));
1409
1410 assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
1411 }
1412
1413 #[test]
1414 fn observer_propagating_world_skipping() {
1415 let mut world = World::new();
1416 world.init_resource::<Order>();
1417
1418 world.add_observer(
1419 |event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
1420 if query.get(event.event_target()).is_ok() {
1421 res.observed("event");
1422 }
1423 },
1424 );
1425
1426 let grandparent = world.spawn(A).id();
1427 let parent = world.spawn(ChildOf(grandparent)).id();
1428 let child = world.spawn((A, ChildOf(parent))).id();
1429
1430 world.trigger(EventPropagating(child));
1431
1432 assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
1433 }
1434
1435 #[test]
1437 fn observer_modifies_relationship() {
1438 fn on_add(add: On<Add, A>, mut commands: Commands) {
1439 commands
1440 .entity(add.entity)
1441 .with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
1442 rsc.spawn_empty();
1443 });
1444 }
1445
1446 let mut world = World::new();
1447 world.add_observer(on_add);
1448 world.spawn(A);
1449 }
1450
1451 #[test]
1454 fn observer_on_remove_during_despawn_spawn_empty() {
1455 let mut world = World::new();
1456
1457 world.add_observer(|_: On<Remove, A>, mut cmd: Commands| {
1459 cmd.spawn_empty();
1462 });
1463
1464 let ent = world.spawn(A).id();
1465
1466 world.despawn(ent);
1471 }
1472
1473 #[test]
1474 #[should_panic]
1475 fn observer_invalid_params() {
1476 #[derive(Resource)]
1477 struct ResA;
1478
1479 #[derive(Resource)]
1480 struct ResB;
1481
1482 let mut world = World::new();
1483 world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
1485 commands.insert_resource(ResB);
1486 });
1487 world.trigger(EventA);
1488 }
1489
1490 #[test]
1491 fn observer_apply_deferred_from_param_set() {
1492 #[derive(Resource)]
1493 struct ResA;
1494
1495 let mut world = World::new();
1496 world.add_observer(
1497 |_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1498 params.p1().insert_resource(ResA);
1499 },
1500 );
1501
1502 world.trigger(EventA);
1503 world.flush();
1504
1505 assert!(world.get_resource::<ResA>().is_some());
1506 }
1507
1508 #[test]
1509 #[track_caller]
1510 fn observer_caller_location_event() {
1511 #[derive(Event)]
1512 struct EventA;
1513
1514 let caller = MaybeLocation::caller();
1515 let mut world = World::new();
1516 world.add_observer(move |event: On<EventA>| {
1517 assert_eq!(event.caller(), caller);
1518 });
1519 world.trigger(EventA);
1520 }
1521
1522 #[test]
1523 #[track_caller]
1524 fn observer_caller_location_command_archetype_move() {
1525 #[derive(Component)]
1526 struct Component;
1527
1528 let caller = MaybeLocation::caller();
1529 let mut world = World::new();
1530 world.add_observer(move |event: On<Add, Component>| {
1531 assert_eq!(event.caller(), caller);
1532 });
1533 world.add_observer(move |event: On<Remove, Component>| {
1534 assert_eq!(event.caller(), caller);
1535 });
1536 world.commands().spawn(Component).clear();
1537 }
1538
1539 #[test]
1540 fn observer_watch_entities() {
1541 let mut world = World::new();
1542 world.init_resource::<Order>();
1543 let entities = world
1544 .spawn_batch(core::iter::repeat_n((), 4))
1545 .collect::<Vec<_>>();
1546 let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1547 order.observed("a");
1548 });
1549 world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1550
1551 world.trigger(EntityEventA(entities[0]));
1552 world.trigger(EntityEventA(entities[1]));
1553 assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1554 world.trigger(EntityEventA(entities[2]));
1555 world.trigger(EntityEventA(entities[3]));
1556 assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1557 }
1558
1559 #[test]
1560 fn unregister_global_observer() {
1561 let mut world = World::new();
1562 let mut observer = world.add_observer(|_: On<EventA>| {});
1563 observer.remove::<Observer>();
1564 let id = observer.id();
1565 let event_key = world.event_key::<EventA>().unwrap();
1566 assert!(!world
1567 .observers
1568 .get_observers_mut(event_key)
1569 .global_observers
1570 .contains_key(&id));
1571 }
1572
1573 #[test]
1574 fn unregister_entity_observer() {
1575 let mut world = World::new();
1576 let entity = world.spawn_empty().id();
1577 let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1578 let mut observer = world.spawn(observer);
1579 observer.remove::<Observer>();
1580 let event_key = world.event_key::<EventA>().unwrap();
1581 assert!(!world
1582 .observers
1583 .get_observers_mut(event_key)
1584 .entity_observers
1585 .contains_key(&entity));
1586 }
1587
1588 #[test]
1589 fn unregister_component_observer() {
1590 let mut world = World::new();
1591 let a = world.register_component::<A>();
1592 let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1593 let mut observer = world.spawn(observer);
1594 observer.remove::<Observer>();
1595 let event_key = world.event_key::<EventA>().unwrap();
1596 assert!(!world
1597 .observers
1598 .get_observers_mut(event_key)
1599 .component_observers()
1600 .contains_key(&a));
1601 }
1602
1603 #[derive(Resource)]
1604 struct RunConditionFlag(bool);
1605
1606 #[test]
1607 fn observer_run_condition_true() {
1608 let mut world = World::new();
1609 world.insert_resource(RunConditionFlag(true));
1610 world.init_resource::<Order>();
1611
1612 world.add_observer(
1613 (|_: On<EventA>, mut order: ResMut<Order>| {
1614 order.observed("event");
1615 })
1616 .run_if(|flag: Res<RunConditionFlag>| flag.0),
1617 );
1618
1619 world.trigger(EventA);
1620 assert_eq!(vec!["event"], world.resource::<Order>().0);
1621 }
1622
1623 #[test]
1624 fn observer_run_condition_false() {
1625 let mut world = World::new();
1626 world.insert_resource(RunConditionFlag(false));
1627 world.init_resource::<Order>();
1628
1629 world.add_observer(
1630 (|_: On<EventA>, mut order: ResMut<Order>| {
1631 order.observed("event");
1632 })
1633 .run_if(|flag: Res<RunConditionFlag>| flag.0),
1634 );
1635
1636 world.trigger(EventA);
1637 assert!(world.resource::<Order>().0.is_empty());
1638 }
1639
1640 #[test]
1641 fn observer_run_condition_chained() {
1642 let mut world = World::new();
1643 world.insert_resource(RunConditionFlag(true));
1644 world.init_resource::<Order>();
1645
1646 #[derive(Resource)]
1647 struct SecondFlag(bool);
1648 world.insert_resource(SecondFlag(true));
1649
1650 world.add_observer(
1651 (|_: On<EventA>, mut order: ResMut<Order>| {
1652 order.observed("event");
1653 })
1654 .run_if(|flag: Res<RunConditionFlag>| flag.0)
1655 .run_if(|flag: Res<SecondFlag>| flag.0),
1656 );
1657
1658 world.trigger(EventA);
1659 assert_eq!(vec!["event"], world.resource::<Order>().0);
1660
1661 world.resource_mut::<Order>().0.clear();
1662 world.resource_mut::<SecondFlag>().0 = false;
1663 world.trigger(EventA);
1664 assert!(world.resource::<Order>().0.is_empty());
1665 }
1666
1667 #[test]
1668 fn observer_run_condition_re_evaluated() {
1669 let mut world = World::new();
1670 world.insert_resource(RunConditionFlag(false));
1671 world.init_resource::<Order>();
1672
1673 world.add_observer(
1674 (|_: On<EventA>, mut order: ResMut<Order>| {
1675 order.observed("event");
1676 })
1677 .run_if(|flag: Res<RunConditionFlag>| flag.0),
1678 );
1679
1680 world.trigger(EventA);
1681 assert!(world.resource::<Order>().0.is_empty());
1682
1683 world.resource_mut::<RunConditionFlag>().0 = true;
1684 world.trigger(EventA);
1685 assert_eq!(vec!["event"], world.resource::<Order>().0);
1686 }
1687
1688 #[test]
1689 fn observer_run_condition_result_bool() {
1690 let mut world = World::new();
1691 world.init_resource::<Order>();
1692
1693 world.add_observer(
1694 (|_: On<EventA>, mut order: ResMut<Order>| {
1695 order.observed("err");
1696 })
1697 .run_if(|| -> Result<bool> { Err(core::fmt::Error.into()) }),
1698 );
1699 world.add_observer(
1700 (|_: On<EventA>, mut order: ResMut<Order>| {
1701 order.observed("false");
1702 })
1703 .run_if(|| -> Result<bool> { Ok(false) }),
1704 );
1705 world.add_observer(
1706 (|_: On<EventA>, mut order: ResMut<Order>| {
1707 order.observed("true");
1708 })
1709 .run_if(|| -> Result<bool> { Ok(true) }),
1710 );
1711
1712 world.trigger(EventA);
1713 assert_eq!(vec!["true"], world.resource::<Order>().0);
1714 }
1715
1716 #[test]
1717 fn observer_conditions_and_change_detection() {
1718 #[derive(Resource, Default)]
1719 struct Bool2(pub bool);
1720
1721 let mut world = World::new();
1722 world.init_resource::<Order>();
1723 world.insert_resource(RunConditionFlag(false));
1724 world.insert_resource(Bool2(false));
1725
1726 world.add_observer(
1727 (|_: On<EventA>, mut order: ResMut<Order>| {
1728 order.observed("event");
1729 })
1730 .run_if(|res1: Res<RunConditionFlag>| res1.is_changed())
1731 .run_if(|res2: Res<Bool2>| res2.is_changed()),
1732 );
1733
1734 world.trigger(EventA);
1736 assert_eq!(vec!["event"], world.resource::<Order>().0);
1737
1738 world.resource_mut::<Order>().0.clear();
1740 world.trigger(EventA);
1741 assert!(world.resource::<Order>().0.is_empty());
1742
1743 world.resource_mut::<RunConditionFlag>().0 = true;
1745 world.trigger(EventA);
1746 assert!(world.resource::<Order>().0.is_empty());
1747
1748 world.resource_mut::<Bool2>().0 = true;
1751 world.trigger(EventA);
1752 assert!(world.resource::<Order>().0.is_empty());
1753
1754 world.resource_mut::<RunConditionFlag>().0 = false;
1756 world.trigger(EventA);
1757 assert!(world.resource::<Order>().0.is_empty());
1758
1759 world.resource_mut::<Bool2>().0 = false;
1761 world.resource_mut::<RunConditionFlag>().0 = true;
1762 world.trigger(EventA);
1763 assert_eq!(vec!["event"], world.resource::<Order>().0);
1764 }
1765
1766 #[test]
1767 fn entity_observer_with_run_condition() {
1768 let mut world = World::new();
1769 world.insert_resource(RunConditionFlag(true));
1770 world.init_resource::<Order>();
1771
1772 let entity = world
1773 .spawn_empty()
1774 .observe(
1775 (|_: On<EntityEventA>, mut order: ResMut<Order>| {
1776 order.observed("entity_event");
1777 })
1778 .run_if(|flag: Res<RunConditionFlag>| flag.0),
1779 )
1780 .id();
1781
1782 world.trigger(EntityEventA(entity));
1783 assert_eq!(vec!["entity_event"], world.resource::<Order>().0);
1784
1785 world.resource_mut::<Order>().0.clear();
1786 world.resource_mut::<RunConditionFlag>().0 = false;
1787 world.trigger(EntityEventA(entity));
1788 assert!(world.resource::<Order>().0.is_empty());
1789 }
1790
1791 #[test]
1792 fn observer_builder_run_if() {
1793 let mut world = World::new();
1794 world.insert_resource(RunConditionFlag(true));
1795 world.init_resource::<Order>();
1796
1797 let observer = Observer::new(|_: On<EventA>, mut order: ResMut<Order>| {
1798 order.observed("event");
1799 })
1800 .run_if(|flag: Res<RunConditionFlag>| flag.0);
1801
1802 world.spawn(observer);
1803
1804 world.trigger(EventA);
1805 assert_eq!(vec!["event"], world.resource::<Order>().0);
1806
1807 world.resource_mut::<Order>().0.clear();
1808 world.resource_mut::<RunConditionFlag>().0 = false;
1809 world.trigger(EventA);
1810 assert!(world.resource::<Order>().0.is_empty());
1811 }
1812
1813 #[test]
1814 fn observer_new_old_archetypes() {
1815 #[derive(Resource, Default)]
1816 struct Changes(Vec<(&'static str, Option<ArchetypeId>, Option<ArchetypeId>)>);
1817
1818 let mut world = World::new();
1819 world.init_resource::<Changes>();
1820
1821 fn observer<E: for<'a> Event<Trigger<'a> = EntityComponentsTrigger<'a>>>(
1822 e: On<E, A>,
1823 mut c: ResMut<Changes>,
1824 ) {
1825 c.0.push((
1826 type_name::<E>(),
1827 e.trigger().old_archetype.map(Archetype::id),
1828 e.trigger().new_archetype.map(Archetype::id),
1829 ));
1830 }
1831
1832 let empty = world.spawn(()).archetype().id();
1833 let a = world.spawn(A).archetype().id();
1834 let ab = world.spawn((A, B)).archetype().id();
1835
1836 world.add_observer(observer::<Add>);
1837 world.add_observer(observer::<Insert>);
1838 world.add_observer(observer::<Discard>);
1839 world.add_observer(observer::<Remove>);
1840 world.add_observer(observer::<Despawn>);
1841
1842 let mut entity = world.spawn((A, B));
1843 entity.remove::<(A, B)>();
1844 entity.insert(A);
1845 entity.insert(A);
1846 entity.despawn();
1847
1848 assert_eq!(
1849 &world.resource_mut::<Changes>().0,
1850 &[
1851 ("bevy_ecs::lifecycle::Add", None, Some(ab)),
1852 ("bevy_ecs::lifecycle::Insert", None, Some(ab)),
1853 ("bevy_ecs::lifecycle::Discard", Some(ab), Some(empty)),
1854 ("bevy_ecs::lifecycle::Remove", Some(ab), Some(empty)),
1855 ("bevy_ecs::lifecycle::Add", Some(empty), Some(a)),
1856 ("bevy_ecs::lifecycle::Insert", Some(empty), Some(a)),
1857 ("bevy_ecs::lifecycle::Discard", Some(a), Some(a)),
1858 ("bevy_ecs::lifecycle::Insert", Some(a), Some(a)),
1859 ("bevy_ecs::lifecycle::Despawn", Some(a), None),
1860 ("bevy_ecs::lifecycle::Discard", Some(a), None),
1861 ("bevy_ecs::lifecycle::Remove", Some(a), None),
1862 ],
1863 );
1864 }
1865
1866 #[test]
1867 fn despawning_observer_removes_observed_by() {
1868 let mut world = World::new();
1869
1870 #[derive(EntityEvent)]
1871 struct Hi {
1872 entity: Entity,
1873 }
1874
1875 let target = world.spawn_empty().id();
1876 let observer = world
1877 .spawn(Observer::new(|_: On<Hi>| {}).with_entity(target))
1878 .id();
1879
1880 assert_eq!(
1881 world.entity(target).get::<ObservedBy>().unwrap().get(),
1882 &[observer]
1883 );
1884
1885 world.entity_mut(observer).despawn();
1886
1887 assert!(!world.entity(target).contains::<ObservedBy>());
1888 }
1889
1890 #[test]
1891 fn despawning_observer_removes_observed_by_repeated() {
1892 let mut world = World::new();
1893
1894 #[derive(EntityEvent)]
1895 struct Hi {
1896 entity: Entity,
1897 }
1898
1899 let target = world.spawn_empty().id();
1900 let observer = world
1901 .spawn(Observer::new(|_: On<Hi>| {}).with_entities([target, target]))
1903 .id();
1904
1905 assert_eq!(
1908 world.entity(target).get::<ObservedBy>().unwrap().get(),
1909 &[observer, observer]
1910 );
1911
1912 world.entity_mut(observer).despawn();
1913
1914 assert!(!world.entity(target).contains::<ObservedBy>());
1915 }
1916}