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