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