Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/observer/mod.rs
9377 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 condition;
8
mod distributed_storage;
9
mod entity_cloning;
10
mod runner;
11
mod system_param;
12
13
pub use centralized_storage::*;
14
pub use condition::*;
15
pub use distributed_storage::*;
16
pub use runner::*;
17
pub use system_param::*;
18
19
use crate::{
20
change_detection::MaybeLocation,
21
event::Event,
22
prelude::*,
23
world::{DeferredWorld, *},
24
};
25
26
impl World {
27
/// Spawns a "global" [`Observer`] which will watch for the given event.
28
/// Returns its [`Entity`] as a [`EntityWorldMut`].
29
///
30
/// `system` can be any system whose first parameter is [`On`].
31
///
32
/// # Example
33
///
34
/// ```
35
/// # use bevy_ecs::prelude::*;
36
/// #[derive(Component)]
37
/// struct A;
38
///
39
/// # let mut world = World::new();
40
/// world.add_observer(|_: On<Add, A>| {
41
/// // ...
42
/// });
43
/// world.add_observer(|_: On<Remove, A>| {
44
/// // ...
45
/// });
46
/// ```
47
///
48
/// **Calling [`observe`](EntityWorldMut::observe) on the returned
49
/// [`EntityWorldMut`] will observe the observer itself, which you very
50
/// likely do not want.**
51
///
52
/// # Panics
53
///
54
/// Panics if the given system is an exclusive system.
55
pub fn add_observer<M>(&mut self, observer: impl IntoObserver<M>) -> EntityWorldMut<'_> {
56
self.spawn(observer.into_observer())
57
}
58
59
/// Triggers the given [`Event`], which will run any [`Observer`]s watching for it.
60
///
61
/// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
62
#[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
/// Triggers the given [`Event`] using the given [`Trigger`](crate::event::Trigger), which will run any [`Observer`]s watching for it.
72
///
73
/// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
74
#[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
/// Triggers the given mutable [`Event`] reference, which will run any [`Observer`]s watching for it.
80
///
81
/// Compared to [`World::trigger`], this method is most useful when it's necessary to check
82
/// or use the event after it has been modified by observers.
83
#[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
/// Triggers the given mutable [`Event`] reference using the given mutable [`Trigger`](crate::event::Trigger) reference, which
93
/// will run any [`Observer`]s watching for it.
94
///
95
/// Compared to [`World::trigger`], this method is most useful when it's necessary to check
96
/// or use the event after it has been modified by observers.
97
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
// SAFETY: event_key was just registered and matches `event`
109
unsafe {
110
DeferredWorld::from(self).trigger_raw(event_key, event, trigger, caller);
111
}
112
}
113
114
/// Register an observer to the cache, called when an observer is created
115
pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
116
// SAFETY: References do not alias.
117
let (observer_state, archetypes, observers) = unsafe {
118
let observer_state: *const Observer = self.get::<Observer>(observer_entity).unwrap();
119
// Populate ObservedBy for each observed entity.
120
for watched_entity in (*observer_state).descriptor.entities.iter().copied() {
121
let mut entity_mut = self.entity_mut(watched_entity);
122
let mut observed_by = entity_mut.entry::<ObservedBy>().or_default().into_mut();
123
observed_by.0.push(observer_entity);
124
}
125
(&*observer_state, &mut self.archetypes, &mut self.observers)
126
};
127
let descriptor = &observer_state.descriptor;
128
129
for &event_key in &descriptor.event_keys {
130
let cache = observers.get_observers_mut(event_key);
131
132
if descriptor.components.is_empty() && descriptor.entities.is_empty() {
133
cache
134
.global_observers
135
.insert(observer_entity, observer_state.runner);
136
} else if descriptor.components.is_empty() {
137
// Observer is not targeting any components so register it as an entity observer
138
for &watched_entity in &observer_state.descriptor.entities {
139
let map = cache.entity_observers.entry(watched_entity).or_default();
140
map.insert(observer_entity, observer_state.runner);
141
}
142
} else {
143
// Register observer for each watched component
144
for &component in &descriptor.components {
145
let observers =
146
cache
147
.component_observers
148
.entry(component)
149
.or_insert_with(|| {
150
if let Some(flag) = Observers::is_archetype_cached(event_key) {
151
archetypes.update_flags(component, flag, true);
152
}
153
CachedComponentObservers::default()
154
});
155
if descriptor.entities.is_empty() {
156
// Register for all triggers targeting the component
157
observers
158
.global_observers
159
.insert(observer_entity, observer_state.runner);
160
} else {
161
// Register for each watched entity
162
for &watched_entity in &descriptor.entities {
163
let map = observers
164
.entity_component_observers
165
.entry(watched_entity)
166
.or_default();
167
map.insert(observer_entity, observer_state.runner);
168
}
169
}
170
}
171
}
172
}
173
}
174
175
/// Remove the observer from the cache, called when an observer gets despawned
176
pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
177
let archetypes = &mut self.archetypes;
178
let observers = &mut self.observers;
179
180
for &event_key in &descriptor.event_keys {
181
let cache = observers.get_observers_mut(event_key);
182
if descriptor.components.is_empty() && descriptor.entities.is_empty() {
183
cache.global_observers.remove(&entity);
184
} else if descriptor.components.is_empty() {
185
for watched_entity in &descriptor.entities {
186
// This check should be unnecessary since this observer hasn't been unregistered yet
187
let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
188
continue;
189
};
190
observers.remove(&entity);
191
if observers.is_empty() {
192
cache.entity_observers.remove(watched_entity);
193
}
194
}
195
} else {
196
for component in &descriptor.components {
197
let Some(observers) = cache.component_observers.get_mut(component) else {
198
continue;
199
};
200
if descriptor.entities.is_empty() {
201
observers.global_observers.remove(&entity);
202
} else {
203
for watched_entity in &descriptor.entities {
204
let Some(map) =
205
observers.entity_component_observers.get_mut(watched_entity)
206
else {
207
continue;
208
};
209
map.remove(&entity);
210
if map.is_empty() {
211
observers.entity_component_observers.remove(watched_entity);
212
}
213
}
214
}
215
216
if observers.global_observers.is_empty()
217
&& observers.entity_component_observers.is_empty()
218
{
219
cache.component_observers.remove(component);
220
if let Some(flag) = Observers::is_archetype_cached(event_key)
221
&& let Some(by_component) = archetypes.by_component.get(component)
222
{
223
for archetype in by_component.keys() {
224
let archetype = &mut archetypes.archetypes[archetype.index()];
225
if archetype.contains(*component) {
226
let no_longer_observed = archetype
227
.iter_components()
228
.all(|id| !cache.component_observers.contains_key(&id));
229
230
if no_longer_observed {
231
archetype.flags.set(flag, false);
232
}
233
}
234
}
235
}
236
}
237
}
238
}
239
}
240
}
241
}
242
243
#[cfg(test)]
244
mod tests {
245
use alloc::{vec, vec::Vec};
246
use core::any::type_name;
247
248
use bevy_ptr::OwningPtr;
249
250
use crate::{
251
archetype::{Archetype, ArchetypeId},
252
change_detection::MaybeLocation,
253
error::Result,
254
event::{EntityComponentsTrigger, Event, GlobalTrigger},
255
hierarchy::ChildOf,
256
observer::{Observer, Replace},
257
prelude::*,
258
world::DeferredWorld,
259
};
260
261
#[derive(Component)]
262
struct A;
263
264
#[derive(Component)]
265
struct B;
266
267
#[derive(Component)]
268
#[component(storage = "SparseSet")]
269
struct S;
270
271
#[derive(Event)]
272
struct EventA;
273
274
#[derive(EntityEvent)]
275
struct EntityEventA(Entity);
276
277
#[derive(EntityEvent)]
278
#[entity_event(trigger = EntityComponentsTrigger<'a>)]
279
struct EntityComponentsEvent(Entity);
280
281
#[derive(Event)]
282
struct EventWithData {
283
counter: usize,
284
}
285
286
#[derive(Resource, Default)]
287
struct Order(Vec<&'static str>);
288
289
impl Order {
290
#[track_caller]
291
fn observed(&mut self, name: &'static str) {
292
self.0.push(name);
293
}
294
}
295
296
#[derive(Component, EntityEvent)]
297
#[entity_event(propagate, auto_propagate)]
298
struct EventPropagating(Entity);
299
300
#[test]
301
fn observer_order_spawn_despawn() {
302
let mut world = World::new();
303
world.init_resource::<Order>();
304
305
world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
306
world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
307
world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
308
res.observed("replace");
309
});
310
world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
311
312
let entity = world.spawn(A).id();
313
world.despawn(entity);
314
assert_eq!(
315
vec!["add", "insert", "replace", "remove"],
316
world.resource::<Order>().0
317
);
318
}
319
320
#[test]
321
fn observer_order_insert_remove() {
322
let mut world = World::new();
323
world.init_resource::<Order>();
324
325
world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
326
world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
327
world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
328
res.observed("replace");
329
});
330
world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
331
332
let mut entity = world.spawn_empty();
333
entity.insert(A);
334
entity.remove::<A>();
335
entity.flush();
336
assert_eq!(
337
vec!["add", "insert", "replace", "remove"],
338
world.resource::<Order>().0
339
);
340
}
341
342
#[test]
343
fn observer_order_insert_remove_sparse() {
344
let mut world = World::new();
345
world.init_resource::<Order>();
346
347
world.add_observer(|_: On<Add, S>, mut res: ResMut<Order>| res.observed("add"));
348
world.add_observer(|_: On<Insert, S>, mut res: ResMut<Order>| res.observed("insert"));
349
world.add_observer(|_: On<Replace, S>, mut res: ResMut<Order>| {
350
res.observed("replace");
351
});
352
world.add_observer(|_: On<Remove, S>, mut res: ResMut<Order>| res.observed("remove"));
353
354
let mut entity = world.spawn_empty();
355
entity.insert(S);
356
entity.remove::<S>();
357
entity.flush();
358
assert_eq!(
359
vec!["add", "insert", "replace", "remove"],
360
world.resource::<Order>().0
361
);
362
}
363
364
#[test]
365
fn observer_order_replace() {
366
let mut world = World::new();
367
world.init_resource::<Order>();
368
369
let entity = world.spawn(A).id();
370
371
world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
372
world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
373
world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
374
res.observed("replace");
375
});
376
world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
377
378
let mut entity = world.entity_mut(entity);
379
entity.insert(A);
380
entity.flush();
381
assert_eq!(vec!["replace", "insert"], world.resource::<Order>().0);
382
}
383
384
#[test]
385
fn observer_order_recursive() {
386
let mut world = World::new();
387
world.init_resource::<Order>();
388
world.add_observer(
389
|add: On<Add, A>, mut res: ResMut<Order>, mut commands: Commands| {
390
res.observed("add_a");
391
commands.entity(add.entity).insert(B);
392
},
393
);
394
world.add_observer(
395
|remove: On<Remove, A>, mut res: ResMut<Order>, mut commands: Commands| {
396
res.observed("remove_a");
397
commands.entity(remove.entity).remove::<B>();
398
},
399
);
400
401
world.add_observer(
402
|add: On<Add, B>, mut res: ResMut<Order>, mut commands: Commands| {
403
res.observed("add_b");
404
commands.entity(add.entity).remove::<A>();
405
},
406
);
407
world.add_observer(|_: On<Remove, B>, mut res: ResMut<Order>| {
408
res.observed("remove_b");
409
});
410
411
let entity = world.spawn(A).flush();
412
let entity = world.get_entity(entity).unwrap();
413
assert!(!entity.contains::<A>());
414
assert!(!entity.contains::<B>());
415
assert_eq!(
416
vec!["add_a", "add_b", "remove_a", "remove_b"],
417
world.resource::<Order>().0
418
);
419
}
420
421
#[test]
422
fn observer_trigger_ref() {
423
let mut world = World::new();
424
425
world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
426
world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
427
world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
428
429
let mut event = EventWithData { counter: 0 };
430
world.trigger_ref(&mut event);
431
assert_eq!(7, event.counter);
432
}
433
434
#[test]
435
fn observer_multiple_listeners() {
436
let mut world = World::new();
437
world.init_resource::<Order>();
438
439
world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
440
world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));
441
442
world.spawn(A).flush();
443
assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
444
// we have one A entity and two observers
445
assert_eq!(world.query::<&A>().query(&world).count(), 1);
446
assert_eq!(world.query::<&Observer>().query(&world).count(), 2);
447
}
448
449
#[test]
450
fn observer_multiple_events() {
451
let mut world = World::new();
452
world.init_resource::<Order>();
453
let on_remove = world.register_event_key::<Remove>();
454
world.spawn(
455
// SAFETY: Add and Remove are both unit types, so this is safe
456
unsafe {
457
Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
458
res.observed("add/remove");
459
})
460
.with_event_key(on_remove)
461
},
462
);
463
464
let entity = world.spawn(A).id();
465
world.despawn(entity);
466
assert_eq!(
467
vec!["add/remove", "add/remove"],
468
world.resource::<Order>().0
469
);
470
}
471
472
#[test]
473
fn observer_multiple_components() {
474
let mut world = World::new();
475
world.init_resource::<Order>();
476
world.register_component::<A>();
477
world.register_component::<B>();
478
479
world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
480
res.observed("add_ab");
481
});
482
483
let entity = world.spawn(A).id();
484
world.entity_mut(entity).insert(B);
485
assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
486
}
487
488
#[test]
489
fn observer_despawn() {
490
let mut world = World::new();
491
492
let system: fn(On<Add, A>) = |_| {
493
panic!("Observer triggered after being despawned.");
494
};
495
let observer = world.add_observer(system).id();
496
world.despawn(observer);
497
world.spawn(A).flush();
498
}
499
500
// Regression test for https://github.com/bevyengine/bevy/issues/14961
501
#[test]
502
fn observer_despawn_archetype_flags() {
503
let mut world = World::new();
504
world.init_resource::<Order>();
505
506
let entity = world.spawn((A, B)).flush();
507
508
world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| {
509
res.observed("remove_a");
510
});
511
512
let system: fn(On<Remove, B>) = |_: On<Remove, B>| {
513
panic!("Observer triggered after being despawned.");
514
};
515
516
let observer = world.add_observer(system).flush();
517
world.despawn(observer);
518
519
world.despawn(entity);
520
521
assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
522
}
523
524
#[test]
525
fn observer_multiple_matches() {
526
let mut world = World::new();
527
world.init_resource::<Order>();
528
529
world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
530
res.observed("add_ab");
531
});
532
533
world.spawn((A, B)).flush();
534
assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
535
}
536
537
#[test]
538
fn observer_entity_routing() {
539
let mut world = World::new();
540
world.init_resource::<Order>();
541
542
let system: fn(On<EntityEventA>) = |_| {
543
panic!("Trigger routed to non-targeted entity.");
544
};
545
546
world.spawn_empty().observe(system);
547
let entity = world
548
.spawn_empty()
549
.observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
550
.id();
551
world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
552
assert_eq!(event.event_target(), entity);
553
res.observed("a_2");
554
});
555
556
world.trigger(EntityEventA(entity));
557
assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
558
}
559
560
#[test]
561
fn observer_multiple_targets() {
562
#[derive(Resource, Default)]
563
struct R(i32);
564
565
let mut world = World::new();
566
let component_a = world.register_component::<A>();
567
let component_b = world.register_component::<B>();
568
world.init_resource::<R>();
569
570
// targets (entity_1, A)
571
let entity_1 = world
572
.spawn_empty()
573
.observe(|_: On<EntityComponentsEvent, A>, mut res: ResMut<R>| res.0 += 1)
574
.id();
575
// targets (entity_2, B)
576
let entity_2 = world
577
.spawn_empty()
578
.observe(|_: On<EntityComponentsEvent, B>, mut res: ResMut<R>| res.0 += 10)
579
.id();
580
// targets any entity or component
581
world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
582
// targets any entity, and components A or B
583
world
584
.add_observer(|_: On<EntityComponentsEvent, (A, B)>, mut res: ResMut<R>| res.0 += 1000);
585
// test all tuples
586
world.add_observer(
587
|_: On<EntityComponentsEvent, (A, B, (A, B))>, mut res: ResMut<R>| res.0 += 10000,
588
);
589
world.add_observer(
590
|_: On<EntityComponentsEvent, (A, B, (A, B), ((A, B), (A, B)))>, mut res: ResMut<R>| {
591
res.0 += 100000;
592
},
593
);
594
world.add_observer(
595
|_: On<EntityComponentsEvent, (A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>,
596
mut res: ResMut<R>| res.0 += 1000000,
597
);
598
599
// trigger for an entity and a component
600
world.trigger_with(
601
EntityComponentsEvent(entity_1),
602
EntityComponentsTrigger {
603
components: &[component_a],
604
old_archetype: None,
605
new_archetype: None,
606
},
607
);
608
// only observer that doesn't trigger is the one only watching entity_2
609
assert_eq!(1111101, world.resource::<R>().0);
610
world.resource_mut::<R>().0 = 0;
611
612
// trigger for both entities, but no components: trigger once per entity target
613
world.trigger_with(
614
EntityComponentsEvent(entity_1),
615
EntityComponentsTrigger {
616
components: &[],
617
old_archetype: None,
618
new_archetype: None,
619
},
620
);
621
world.trigger_with(
622
EntityComponentsEvent(entity_2),
623
EntityComponentsTrigger {
624
components: &[],
625
old_archetype: None,
626
new_archetype: None,
627
},
628
);
629
630
// only the observer that doesn't require components triggers - once per entity
631
assert_eq!(200, world.resource::<R>().0);
632
world.resource_mut::<R>().0 = 0;
633
634
// trigger for both entities and both components: trigger once per entity target
635
// we only get 2222211 because a given observer can trigger only once per entity target
636
world.trigger_with(
637
EntityComponentsEvent(entity_1),
638
EntityComponentsTrigger {
639
components: &[component_a, component_b],
640
old_archetype: None,
641
new_archetype: None,
642
},
643
);
644
world.trigger_with(
645
EntityComponentsEvent(entity_2),
646
EntityComponentsTrigger {
647
components: &[component_a, component_b],
648
old_archetype: None,
649
new_archetype: None,
650
},
651
);
652
assert_eq!(2222211, world.resource::<R>().0);
653
world.resource_mut::<R>().0 = 0;
654
}
655
656
#[test]
657
fn observer_dynamic_component() {
658
let mut world = World::new();
659
world.init_resource::<Order>();
660
661
let component_id = world.register_component::<A>();
662
world.spawn(
663
Observer::new(|_: On<Add>, mut res: ResMut<Order>| res.observed("event_a"))
664
.with_component(component_id),
665
);
666
667
let mut entity = world.spawn_empty();
668
OwningPtr::make(A, |ptr| {
669
// SAFETY: we registered `component_id` above.
670
unsafe { entity.insert_by_id(component_id, ptr) };
671
});
672
673
assert_eq!(vec!["event_a"], world.resource::<Order>().0);
674
}
675
676
#[test]
677
fn observer_dynamic_trigger() {
678
let mut world = World::new();
679
world.init_resource::<Order>();
680
let event_a = world.register_event_key::<EventA>();
681
682
// SAFETY: we registered `event_a` above and it matches the type of EventA
683
let observe = unsafe {
684
Observer::with_dynamic_runner(
685
|mut world, _observer, _trigger_context, _event, _trigger| {
686
world.resource_mut::<Order>().observed("event_a");
687
},
688
)
689
.with_event_key(event_a)
690
};
691
world.spawn(observe);
692
693
world.commands().queue(move |world: &mut World| {
694
// SAFETY: we registered `event_a` above and it matches the type of EventA
695
unsafe {
696
DeferredWorld::from(world).trigger_raw(
697
event_a,
698
&mut EventA,
699
&mut GlobalTrigger,
700
MaybeLocation::caller(),
701
);
702
}
703
});
704
world.flush();
705
assert_eq!(vec!["event_a"], world.resource::<Order>().0);
706
}
707
708
#[test]
709
fn observer_propagating() {
710
let mut world = World::new();
711
world.init_resource::<Order>();
712
713
let parent = world.spawn_empty().id();
714
let child = world.spawn(ChildOf(parent)).id();
715
716
world.entity_mut(parent).observe(
717
move |event: On<EventPropagating>, mut res: ResMut<Order>| {
718
res.observed("parent");
719
720
assert_eq!(event.event_target(), parent);
721
assert_eq!(event.original_event_target(), child);
722
},
723
);
724
725
world.entity_mut(child).observe(
726
move |event: On<EventPropagating>, mut res: ResMut<Order>| {
727
res.observed("child");
728
assert_eq!(event.event_target(), child);
729
assert_eq!(event.original_event_target(), child);
730
},
731
);
732
733
world.trigger(EventPropagating(child));
734
735
assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
736
}
737
738
#[test]
739
fn observer_propagating_redundant_dispatch_same_entity() {
740
let mut world = World::new();
741
world.init_resource::<Order>();
742
743
let parent = world
744
.spawn_empty()
745
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
746
res.observed("parent");
747
})
748
.id();
749
750
let child = world
751
.spawn(ChildOf(parent))
752
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
753
res.observed("child");
754
})
755
.id();
756
757
world.trigger(EventPropagating(child));
758
world.trigger(EventPropagating(child));
759
760
assert_eq!(
761
vec!["child", "parent", "child", "parent"],
762
world.resource::<Order>().0
763
);
764
}
765
766
#[test]
767
fn observer_propagating_redundant_dispatch_parent_child() {
768
let mut world = World::new();
769
world.init_resource::<Order>();
770
771
let parent = world
772
.spawn_empty()
773
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
774
res.observed("parent");
775
})
776
.id();
777
778
let child = world
779
.spawn(ChildOf(parent))
780
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
781
res.observed("child");
782
})
783
.id();
784
785
world.trigger(EventPropagating(child));
786
world.trigger(EventPropagating(parent));
787
788
assert_eq!(
789
vec!["child", "parent", "parent"],
790
world.resource::<Order>().0
791
);
792
}
793
794
#[test]
795
fn observer_propagating_halt() {
796
let mut world = World::new();
797
world.init_resource::<Order>();
798
799
let parent = world
800
.spawn_empty()
801
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
802
res.observed("parent");
803
})
804
.id();
805
806
let child = world
807
.spawn(ChildOf(parent))
808
.observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
809
res.observed("child");
810
event.propagate(false);
811
})
812
.id();
813
814
world.trigger(EventPropagating(child));
815
816
assert_eq!(vec!["child"], world.resource::<Order>().0);
817
}
818
819
#[test]
820
fn observer_propagating_join() {
821
let mut world = World::new();
822
world.init_resource::<Order>();
823
824
let parent = world
825
.spawn_empty()
826
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
827
res.observed("parent");
828
})
829
.id();
830
831
let child_a = world
832
.spawn(ChildOf(parent))
833
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
834
res.observed("child_a");
835
})
836
.id();
837
838
let child_b = world
839
.spawn(ChildOf(parent))
840
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
841
res.observed("child_b");
842
})
843
.id();
844
845
world.trigger(EventPropagating(child_a));
846
world.trigger(EventPropagating(child_b));
847
848
assert_eq!(
849
vec!["child_a", "parent", "child_b", "parent"],
850
world.resource::<Order>().0
851
);
852
}
853
854
#[test]
855
fn observer_propagating_no_next() {
856
let mut world = World::new();
857
world.init_resource::<Order>();
858
859
let entity = world
860
.spawn_empty()
861
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
862
res.observed("event");
863
})
864
.id();
865
866
world.trigger(EventPropagating(entity));
867
assert_eq!(vec!["event"], world.resource::<Order>().0);
868
}
869
870
#[test]
871
fn observer_propagating_parallel_propagation() {
872
let mut world = World::new();
873
world.init_resource::<Order>();
874
875
let parent_a = world
876
.spawn_empty()
877
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
878
res.observed("parent_a");
879
})
880
.id();
881
882
let child_a = world
883
.spawn(ChildOf(parent_a))
884
.observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
885
res.observed("child_a");
886
event.propagate(false);
887
})
888
.id();
889
890
let parent_b = world
891
.spawn_empty()
892
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
893
res.observed("parent_b");
894
})
895
.id();
896
897
let child_b = world
898
.spawn(ChildOf(parent_b))
899
.observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
900
res.observed("child_b");
901
})
902
.id();
903
904
world.trigger(EventPropagating(child_a));
905
world.trigger(EventPropagating(child_b));
906
907
assert_eq!(
908
vec!["child_a", "child_b", "parent_b"],
909
world.resource::<Order>().0
910
);
911
}
912
913
#[test]
914
fn observer_propagating_world() {
915
let mut world = World::new();
916
world.init_resource::<Order>();
917
918
world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
919
res.observed("event");
920
});
921
922
let grandparent = world.spawn_empty().id();
923
let parent = world.spawn(ChildOf(grandparent)).id();
924
let child = world.spawn(ChildOf(parent)).id();
925
926
world.trigger(EventPropagating(child));
927
928
assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
929
}
930
931
#[test]
932
fn observer_propagating_world_skipping() {
933
let mut world = World::new();
934
world.init_resource::<Order>();
935
936
world.add_observer(
937
|event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
938
if query.get(event.event_target()).is_ok() {
939
res.observed("event");
940
}
941
},
942
);
943
944
let grandparent = world.spawn(A).id();
945
let parent = world.spawn(ChildOf(grandparent)).id();
946
let child = world.spawn((A, ChildOf(parent))).id();
947
948
world.trigger(EventPropagating(child));
949
950
assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
951
}
952
953
// Originally for https://github.com/bevyengine/bevy/issues/18452
954
#[test]
955
fn observer_modifies_relationship() {
956
fn on_add(add: On<Add, A>, mut commands: Commands) {
957
commands
958
.entity(add.entity)
959
.with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
960
rsc.spawn_empty();
961
});
962
}
963
964
let mut world = World::new();
965
world.add_observer(on_add);
966
world.spawn(A);
967
}
968
969
// Regression test for https://github.com/bevyengine/bevy/issues/14467
970
// Fails prior to https://github.com/bevyengine/bevy/pull/15398
971
#[test]
972
fn observer_on_remove_during_despawn_spawn_empty() {
973
let mut world = World::new();
974
975
// Observe the removal of A - this will run during despawn
976
world.add_observer(|_: On<Remove, A>, mut cmd: Commands| {
977
// Spawn a new entity - this reserves a new ID and requires a flush
978
// afterward before Entities::free can be called.
979
cmd.spawn_empty();
980
});
981
982
let ent = world.spawn(A).id();
983
984
// Despawn our entity, which runs the Remove observer and allocates a
985
// new Entity.
986
// Should not panic - if it does, then Entities was not flushed properly
987
// after the observer's spawn_empty.
988
world.despawn(ent);
989
}
990
991
#[test]
992
#[should_panic]
993
fn observer_invalid_params() {
994
#[derive(Resource)]
995
struct ResA;
996
997
#[derive(Resource)]
998
struct ResB;
999
1000
let mut world = World::new();
1001
// This fails because `ResA` is not present in the world
1002
world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
1003
commands.insert_resource(ResB);
1004
});
1005
world.trigger(EventA);
1006
}
1007
1008
#[test]
1009
fn observer_apply_deferred_from_param_set() {
1010
#[derive(Resource)]
1011
struct ResA;
1012
1013
let mut world = World::new();
1014
world.add_observer(
1015
|_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1016
params.p1().insert_resource(ResA);
1017
},
1018
);
1019
1020
world.trigger(EventA);
1021
world.flush();
1022
1023
assert!(world.get_resource::<ResA>().is_some());
1024
}
1025
1026
#[test]
1027
#[track_caller]
1028
fn observer_caller_location_event() {
1029
#[derive(Event)]
1030
struct EventA;
1031
1032
let caller = MaybeLocation::caller();
1033
let mut world = World::new();
1034
world.add_observer(move |event: On<EventA>| {
1035
assert_eq!(event.caller(), caller);
1036
});
1037
world.trigger(EventA);
1038
}
1039
1040
#[test]
1041
#[track_caller]
1042
fn observer_caller_location_command_archetype_move() {
1043
#[derive(Component)]
1044
struct Component;
1045
1046
let caller = MaybeLocation::caller();
1047
let mut world = World::new();
1048
world.add_observer(move |event: On<Add, Component>| {
1049
assert_eq!(event.caller(), caller);
1050
});
1051
world.add_observer(move |event: On<Remove, Component>| {
1052
assert_eq!(event.caller(), caller);
1053
});
1054
world.commands().spawn(Component).clear();
1055
}
1056
1057
#[test]
1058
fn observer_watch_entities() {
1059
let mut world = World::new();
1060
world.init_resource::<Order>();
1061
let entities = world
1062
.spawn_batch(core::iter::repeat_n((), 4))
1063
.collect::<Vec<_>>();
1064
let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1065
order.observed("a");
1066
});
1067
world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1068
1069
world.trigger(EntityEventA(entities[0]));
1070
world.trigger(EntityEventA(entities[1]));
1071
assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1072
world.trigger(EntityEventA(entities[2]));
1073
world.trigger(EntityEventA(entities[3]));
1074
assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1075
}
1076
1077
#[test]
1078
fn unregister_global_observer() {
1079
let mut world = World::new();
1080
let mut observer = world.add_observer(|_: On<EventA>| {});
1081
observer.remove::<Observer>();
1082
let id = observer.id();
1083
let event_key = world.event_key::<EventA>().unwrap();
1084
assert!(!world
1085
.observers
1086
.get_observers_mut(event_key)
1087
.global_observers
1088
.contains_key(&id));
1089
}
1090
1091
#[test]
1092
fn unregister_entity_observer() {
1093
let mut world = World::new();
1094
let entity = world.spawn_empty().id();
1095
let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1096
let mut observer = world.spawn(observer);
1097
observer.remove::<Observer>();
1098
let event_key = world.event_key::<EventA>().unwrap();
1099
assert!(!world
1100
.observers
1101
.get_observers_mut(event_key)
1102
.entity_observers
1103
.contains_key(&entity));
1104
}
1105
1106
#[test]
1107
fn unregister_component_observer() {
1108
let mut world = World::new();
1109
let a = world.register_component::<A>();
1110
let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1111
let mut observer = world.spawn(observer);
1112
observer.remove::<Observer>();
1113
let event_key = world.event_key::<EventA>().unwrap();
1114
assert!(!world
1115
.observers
1116
.get_observers_mut(event_key)
1117
.component_observers()
1118
.contains_key(&a));
1119
}
1120
1121
#[derive(Resource)]
1122
struct RunConditionFlag(bool);
1123
1124
#[test]
1125
fn observer_run_condition_true() {
1126
let mut world = World::new();
1127
world.insert_resource(RunConditionFlag(true));
1128
world.init_resource::<Order>();
1129
1130
world.add_observer(
1131
(|_: On<EventA>, mut order: ResMut<Order>| {
1132
order.observed("event");
1133
})
1134
.run_if(|flag: Res<RunConditionFlag>| flag.0),
1135
);
1136
1137
world.trigger(EventA);
1138
assert_eq!(vec!["event"], world.resource::<Order>().0);
1139
}
1140
1141
#[test]
1142
fn observer_run_condition_false() {
1143
let mut world = World::new();
1144
world.insert_resource(RunConditionFlag(false));
1145
world.init_resource::<Order>();
1146
1147
world.add_observer(
1148
(|_: On<EventA>, mut order: ResMut<Order>| {
1149
order.observed("event");
1150
})
1151
.run_if(|flag: Res<RunConditionFlag>| flag.0),
1152
);
1153
1154
world.trigger(EventA);
1155
assert!(world.resource::<Order>().0.is_empty());
1156
}
1157
1158
#[test]
1159
fn observer_run_condition_chained() {
1160
let mut world = World::new();
1161
world.insert_resource(RunConditionFlag(true));
1162
world.init_resource::<Order>();
1163
1164
#[derive(Resource)]
1165
struct SecondFlag(bool);
1166
world.insert_resource(SecondFlag(true));
1167
1168
world.add_observer(
1169
(|_: On<EventA>, mut order: ResMut<Order>| {
1170
order.observed("event");
1171
})
1172
.run_if(|flag: Res<RunConditionFlag>| flag.0)
1173
.run_if(|flag: Res<SecondFlag>| flag.0),
1174
);
1175
1176
world.trigger(EventA);
1177
assert_eq!(vec!["event"], world.resource::<Order>().0);
1178
1179
world.resource_mut::<Order>().0.clear();
1180
world.resource_mut::<SecondFlag>().0 = false;
1181
world.trigger(EventA);
1182
assert!(world.resource::<Order>().0.is_empty());
1183
}
1184
1185
#[test]
1186
fn observer_run_condition_re_evaluated() {
1187
let mut world = World::new();
1188
world.insert_resource(RunConditionFlag(false));
1189
world.init_resource::<Order>();
1190
1191
world.add_observer(
1192
(|_: On<EventA>, mut order: ResMut<Order>| {
1193
order.observed("event");
1194
})
1195
.run_if(|flag: Res<RunConditionFlag>| flag.0),
1196
);
1197
1198
world.trigger(EventA);
1199
assert!(world.resource::<Order>().0.is_empty());
1200
1201
world.resource_mut::<RunConditionFlag>().0 = true;
1202
world.trigger(EventA);
1203
assert_eq!(vec!["event"], world.resource::<Order>().0);
1204
}
1205
1206
#[test]
1207
fn observer_run_condition_result_bool() {
1208
let mut world = World::new();
1209
world.init_resource::<Order>();
1210
1211
world.add_observer(
1212
(|_: On<EventA>, mut order: ResMut<Order>| {
1213
order.observed("err");
1214
})
1215
.run_if(|| -> Result<bool> { Err(core::fmt::Error.into()) }),
1216
);
1217
world.add_observer(
1218
(|_: On<EventA>, mut order: ResMut<Order>| {
1219
order.observed("false");
1220
})
1221
.run_if(|| -> Result<bool> { Ok(false) }),
1222
);
1223
world.add_observer(
1224
(|_: On<EventA>, mut order: ResMut<Order>| {
1225
order.observed("true");
1226
})
1227
.run_if(|| -> Result<bool> { Ok(true) }),
1228
);
1229
1230
world.trigger(EventA);
1231
assert_eq!(vec!["true"], world.resource::<Order>().0);
1232
}
1233
1234
#[test]
1235
fn observer_conditions_and_change_detection() {
1236
#[derive(Resource, Default)]
1237
struct Bool2(pub bool);
1238
1239
let mut world = World::new();
1240
world.init_resource::<Order>();
1241
world.insert_resource(RunConditionFlag(false));
1242
world.insert_resource(Bool2(false));
1243
1244
world.add_observer(
1245
(|_: On<EventA>, mut order: ResMut<Order>| {
1246
order.observed("event");
1247
})
1248
.run_if(|res1: Res<RunConditionFlag>| res1.is_changed())
1249
.run_if(|res2: Res<Bool2>| res2.is_changed()),
1250
);
1251
1252
// both resources were just added.
1253
world.trigger(EventA);
1254
assert_eq!(vec!["event"], world.resource::<Order>().0);
1255
1256
// nothing has changed
1257
world.resource_mut::<Order>().0.clear();
1258
world.trigger(EventA);
1259
assert!(world.resource::<Order>().0.is_empty());
1260
1261
// RunConditionFlag has changed, but observer did not run
1262
world.resource_mut::<RunConditionFlag>().0 = true;
1263
world.trigger(EventA);
1264
assert!(world.resource::<Order>().0.is_empty());
1265
1266
// internal state for the Bool2 condition was updated in the
1267
// previous run, so observer still does not run
1268
world.resource_mut::<Bool2>().0 = true;
1269
world.trigger(EventA);
1270
assert!(world.resource::<Order>().0.is_empty());
1271
1272
// internal state for Bool2 was updated, so observer still does not run
1273
world.resource_mut::<RunConditionFlag>().0 = false;
1274
world.trigger(EventA);
1275
assert!(world.resource::<Order>().0.is_empty());
1276
1277
// now check that it works correctly changing Bool2 first and then RunConditionFlag
1278
world.resource_mut::<Bool2>().0 = false;
1279
world.resource_mut::<RunConditionFlag>().0 = true;
1280
world.trigger(EventA);
1281
assert_eq!(vec!["event"], world.resource::<Order>().0);
1282
}
1283
1284
#[test]
1285
fn entity_observer_with_run_condition() {
1286
let mut world = World::new();
1287
world.insert_resource(RunConditionFlag(true));
1288
world.init_resource::<Order>();
1289
1290
let entity = world
1291
.spawn_empty()
1292
.observe(
1293
(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1294
order.observed("entity_event");
1295
})
1296
.run_if(|flag: Res<RunConditionFlag>| flag.0),
1297
)
1298
.id();
1299
1300
world.trigger(EntityEventA(entity));
1301
assert_eq!(vec!["entity_event"], world.resource::<Order>().0);
1302
1303
world.resource_mut::<Order>().0.clear();
1304
world.resource_mut::<RunConditionFlag>().0 = false;
1305
world.trigger(EntityEventA(entity));
1306
assert!(world.resource::<Order>().0.is_empty());
1307
}
1308
1309
#[test]
1310
fn observer_builder_run_if() {
1311
let mut world = World::new();
1312
world.insert_resource(RunConditionFlag(true));
1313
world.init_resource::<Order>();
1314
1315
let observer = Observer::new(|_: On<EventA>, mut order: ResMut<Order>| {
1316
order.observed("event");
1317
})
1318
.run_if(|flag: Res<RunConditionFlag>| flag.0);
1319
1320
world.spawn(observer);
1321
1322
world.trigger(EventA);
1323
assert_eq!(vec!["event"], world.resource::<Order>().0);
1324
1325
world.resource_mut::<Order>().0.clear();
1326
world.resource_mut::<RunConditionFlag>().0 = false;
1327
world.trigger(EventA);
1328
assert!(world.resource::<Order>().0.is_empty());
1329
}
1330
1331
#[test]
1332
fn observer_new_old_archetypes() {
1333
#[derive(Resource, Default)]
1334
struct Changes(Vec<(&'static str, Option<ArchetypeId>, Option<ArchetypeId>)>);
1335
1336
let mut world = World::new();
1337
world.init_resource::<Changes>();
1338
1339
fn observer<E: for<'a> Event<Trigger<'a> = EntityComponentsTrigger<'a>>>(
1340
e: On<E, A>,
1341
mut c: ResMut<Changes>,
1342
) {
1343
c.0.push((
1344
type_name::<E>(),
1345
e.trigger().old_archetype.map(Archetype::id),
1346
e.trigger().new_archetype.map(Archetype::id),
1347
));
1348
}
1349
1350
let empty = world.spawn(()).archetype().id();
1351
let a = world.spawn(A).archetype().id();
1352
let ab = world.spawn((A, B)).archetype().id();
1353
1354
world.add_observer(observer::<Add>);
1355
world.add_observer(observer::<Insert>);
1356
world.add_observer(observer::<Replace>);
1357
world.add_observer(observer::<Remove>);
1358
world.add_observer(observer::<Despawn>);
1359
1360
let mut entity = world.spawn((A, B));
1361
entity.remove::<(A, B)>();
1362
entity.insert(A);
1363
entity.insert(A);
1364
entity.despawn();
1365
1366
assert_eq!(
1367
&world.resource_mut::<Changes>().0,
1368
&[
1369
("bevy_ecs::lifecycle::Add", None, Some(ab)),
1370
("bevy_ecs::lifecycle::Insert", None, Some(ab)),
1371
("bevy_ecs::lifecycle::Replace", Some(ab), Some(empty)),
1372
("bevy_ecs::lifecycle::Remove", Some(ab), Some(empty)),
1373
("bevy_ecs::lifecycle::Add", Some(empty), Some(a)),
1374
("bevy_ecs::lifecycle::Insert", Some(empty), Some(a)),
1375
("bevy_ecs::lifecycle::Replace", Some(a), Some(a)),
1376
("bevy_ecs::lifecycle::Insert", Some(a), Some(a)),
1377
("bevy_ecs::lifecycle::Despawn", Some(a), None),
1378
("bevy_ecs::lifecycle::Replace", Some(a), None),
1379
("bevy_ecs::lifecycle::Remove", Some(a), None),
1380
],
1381
);
1382
}
1383
}
1384
1385