bevy_ecs/observer/runner.rs
1use crate::{
2 component::{ComponentHooks, ComponentId, StorageType},
3 observer::{ObserverDescriptor, ObserverTrigger},
4 prelude::*,
5 query::DebugCheckedUnwrap,
6 system::{IntoObserverSystem, ObserverSystem},
7 world::DeferredWorld,
8};
9use bevy_ptr::PtrMut;
10
11/// Contains [`Observer`] information. This defines how a given observer behaves. It is the
12/// "source of truth" for a given observer entity's behavior.
13pub struct ObserverState {
14 pub(crate) descriptor: ObserverDescriptor,
15 pub(crate) runner: ObserverRunner,
16 pub(crate) last_trigger_id: u32,
17 pub(crate) despawned_watched_entities: u32,
18}
19
20impl Default for ObserverState {
21 fn default() -> Self {
22 Self {
23 runner: |_, _, _| {},
24 last_trigger_id: 0,
25 despawned_watched_entities: 0,
26 descriptor: Default::default(),
27 }
28 }
29}
30
31impl ObserverState {
32 /// Observe the given `event`. This will cause the [`Observer`] to run whenever an event with the given [`ComponentId`]
33 /// is triggered.
34 pub fn with_event(mut self, event: ComponentId) -> Self {
35 self.descriptor.events.push(event);
36 self
37 }
38
39 /// Observe the given event list. This will cause the [`Observer`] to run whenever an event with any of the given [`ComponentId`]s
40 /// is triggered.
41 pub fn with_events(mut self, events: impl IntoIterator<Item = ComponentId>) -> Self {
42 self.descriptor.events.extend(events);
43 self
44 }
45
46 /// Observe the given [`Entity`] list. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
47 /// for any [`Entity`] target in the list.
48 pub fn with_entities(mut self, entities: impl IntoIterator<Item = Entity>) -> Self {
49 self.descriptor.entities.extend(entities);
50 self
51 }
52
53 /// Observe the given [`ComponentId`] list. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
54 /// for any [`ComponentId`] target in the list.
55 pub fn with_components(mut self, components: impl IntoIterator<Item = ComponentId>) -> Self {
56 self.descriptor.components.extend(components);
57 self
58 }
59}
60
61impl Component for ObserverState {
62 const STORAGE_TYPE: StorageType = StorageType::SparseSet;
63
64 fn register_component_hooks(hooks: &mut ComponentHooks) {
65 hooks.on_add(|mut world, entity, _| {
66 world.commands().add(move |world: &mut World| {
67 world.register_observer(entity);
68 });
69 });
70 hooks.on_remove(|mut world, entity, _| {
71 let descriptor = std::mem::take(
72 &mut world
73 .entity_mut(entity)
74 .get_mut::<ObserverState>()
75 .unwrap()
76 .as_mut()
77 .descriptor,
78 );
79 world.commands().add(move |world: &mut World| {
80 world.unregister_observer(entity, descriptor);
81 });
82 });
83 }
84}
85
86/// Type for function that is run when an observer is triggered.
87/// Typically refers to the default runner that runs the system stored in the associated [`ObserverSystemComponent`],
88/// but can be overridden for custom behaviour.
89pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut);
90
91/// An [`Observer`] system. Add this [`Component`] to an [`Entity`] to turn it into an "observer".
92///
93/// Observers listen for a "trigger" of a specific [`Event`]. Events are triggered by calling [`World::trigger`] or [`World::trigger_targets`].
94///
95/// Note that "buffered" events sent using [`EventReader`] and [`EventWriter`] are _not_ automatically triggered. They must be triggered at a specific
96/// point in the schedule.
97///
98/// # Usage
99///
100/// The simplest usage
101/// of the observer pattern looks like this:
102///
103/// ```
104/// # use bevy_ecs::prelude::*;
105/// # let mut world = World::default();
106/// #[derive(Event)]
107/// struct Speak {
108/// message: String,
109/// }
110///
111/// world.observe(|trigger: Trigger<Speak>| {
112/// println!("{}", trigger.event().message);
113/// });
114///
115/// // Observers currently require a flush() to be registered. In the context of schedules,
116/// // this will generally be done for you.
117/// world.flush();
118///
119/// world.trigger(Speak {
120/// message: "Hello!".into(),
121/// });
122/// ```
123///
124/// Notice that we used [`World::observe`]. This is just a shorthand for spawning an [`Observer`] manually:
125///
126/// ```
127/// # use bevy_ecs::prelude::*;
128/// # let mut world = World::default();
129/// # #[derive(Event)]
130/// # struct Speak;
131/// // These are functionally the same:
132/// world.observe(|trigger: Trigger<Speak>| {});
133/// world.spawn(Observer::new(|trigger: Trigger<Speak>| {}));
134/// ```
135///
136/// Observers are systems. They can access arbitrary [`World`] data by adding [`SystemParam`]s:
137///
138/// ```
139/// # use bevy_ecs::prelude::*;
140/// # let mut world = World::default();
141/// # #[derive(Event)]
142/// # struct PrintNames;
143/// # #[derive(Component, Debug)]
144/// # struct Name;
145/// world.observe(|trigger: Trigger<PrintNames>, names: Query<&Name>| {
146/// for name in &names {
147/// println!("{name:?}");
148/// }
149/// });
150/// ```
151///
152/// Note that [`Trigger`] must always be the first parameter.
153///
154/// You can also add [`Commands`], which means you can spawn new entities, insert new components, etc:
155///
156/// ```
157/// # use bevy_ecs::prelude::*;
158/// # let mut world = World::default();
159/// # #[derive(Event)]
160/// # struct SpawnThing;
161/// # #[derive(Component, Debug)]
162/// # struct Thing;
163/// world.observe(|trigger: Trigger<SpawnThing>, mut commands: Commands| {
164/// commands.spawn(Thing);
165/// });
166/// ```
167///
168/// Observers can also trigger new events:
169///
170/// ```
171/// # use bevy_ecs::prelude::*;
172/// # let mut world = World::default();
173/// # #[derive(Event)]
174/// # struct A;
175/// # #[derive(Event)]
176/// # struct B;
177/// world.observe(|trigger: Trigger<A>, mut commands: Commands| {
178/// commands.trigger(B);
179/// });
180/// ```
181///
182/// When the commands are flushed (including these "nested triggers") they will be
183/// recursively evaluated until there are no commands left, meaning nested triggers all
184/// evaluate at the same time!
185///
186/// Events can be triggered for entities, which will be passed to the [`Observer`]:
187///
188/// ```
189/// # use bevy_ecs::prelude::*;
190/// # let mut world = World::default();
191/// # let entity = world.spawn_empty().id();
192/// #[derive(Event)]
193/// struct Explode;
194///
195/// world.observe(|trigger: Trigger<Explode>, mut commands: Commands| {
196/// println!("Entity {:?} goes BOOM!", trigger.entity());
197/// commands.entity(trigger.entity()).despawn();
198/// });
199///
200/// world.flush();
201///
202/// world.trigger_targets(Explode, entity);
203/// ```
204///
205/// You can trigger multiple entities at once:
206///
207/// ```
208/// # use bevy_ecs::prelude::*;
209/// # let mut world = World::default();
210/// # let e1 = world.spawn_empty().id();
211/// # let e2 = world.spawn_empty().id();
212/// # #[derive(Event)]
213/// # struct Explode;
214/// world.trigger_targets(Explode, [e1, e2]);
215/// ```
216///
217/// Observers can also watch _specific_ entities, which enables you to assign entity-specific logic:
218///
219/// ```
220/// # use bevy_ecs::prelude::*;
221/// # #[derive(Component, Debug)]
222/// # struct Name(String);
223/// # let mut world = World::default();
224/// # let e1 = world.spawn_empty().id();
225/// # let e2 = world.spawn_empty().id();
226/// # #[derive(Event)]
227/// # struct Explode;
228/// world.entity_mut(e1).observe(|trigger: Trigger<Explode>, mut commands: Commands| {
229/// println!("Boom!");
230/// commands.entity(trigger.entity()).despawn();
231/// });
232///
233/// world.entity_mut(e2).observe(|trigger: Trigger<Explode>, mut commands: Commands| {
234/// println!("The explosion fizzles! This entity is immune!");
235/// });
236/// ```
237///
238/// If all entities watched by a given [`Observer`] are despawned, the [`Observer`] entity will also be despawned.
239/// This protects against observer "garbage" building up over time.
240///
241/// The examples above calling [`EntityWorldMut::observe`] to add entity-specific observer logic are (once again)
242/// just shorthand for spawning an [`Observer`] directly:
243///
244/// ```
245/// # use bevy_ecs::prelude::*;
246/// # let mut world = World::default();
247/// # let entity = world.spawn_empty().id();
248/// # #[derive(Event)]
249/// # struct Explode;
250/// let mut observer = Observer::new(|trigger: Trigger<Explode>| {});
251/// observer.watch_entity(entity);
252/// world.spawn(observer);
253/// ```
254///
255/// Note that the [`Observer`] component is not added to the entity it is observing. Observers should always be their own entities!
256///
257/// You can call [`Observer::watch_entity`] more than once, which allows you to watch multiple entities with the same [`Observer`].
258///
259/// When first added, [`Observer`] will also create an [`ObserverState`] component, which registers the observer with the [`World`] and
260/// serves as the "source of truth" of the observer.
261///
262/// [`SystemParam`]: crate::system::SystemParam
263pub struct Observer<T: 'static, B: Bundle> {
264 system: BoxedObserverSystem<T, B>,
265 descriptor: ObserverDescriptor,
266}
267
268impl<E: Event, B: Bundle> Observer<E, B> {
269 /// Creates a new [`Observer`], which defaults to a "global" observer. This means it will run whenever the event `E` is triggered
270 /// for _any_ entity (or no entity).
271 pub fn new<M>(system: impl IntoObserverSystem<E, B, M>) -> Self {
272 Self {
273 system: Box::new(IntoObserverSystem::into_system(system)),
274 descriptor: Default::default(),
275 }
276 }
277
278 /// Observe the given `entity`. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
279 /// for the `entity`.
280 pub fn with_entity(mut self, entity: Entity) -> Self {
281 self.descriptor.entities.push(entity);
282 self
283 }
284
285 /// Observe the given `entity`. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
286 /// for the `entity`.
287 /// Note that if this is called _after_ an [`Observer`] is spawned, it will produce no effects.
288 pub fn watch_entity(&mut self, entity: Entity) {
289 self.descriptor.entities.push(entity);
290 }
291
292 /// Observe the given `component`. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
293 /// with the given component target.
294 pub fn with_component(mut self, component: ComponentId) -> Self {
295 self.descriptor.components.push(component);
296 self
297 }
298
299 /// Observe the given `event`. This will cause the [`Observer`] to run whenever an event with the given [`ComponentId`]
300 /// is triggered.
301 /// # Safety
302 /// The type of the `event` [`ComponentId`] _must_ match the actual value
303 /// of the event passed into the observer system.
304 pub unsafe fn with_event(mut self, event: ComponentId) -> Self {
305 self.descriptor.events.push(event);
306 self
307 }
308}
309
310impl<E: Event, B: Bundle> Component for Observer<E, B> {
311 const STORAGE_TYPE: StorageType = StorageType::SparseSet;
312 fn register_component_hooks(hooks: &mut ComponentHooks) {
313 hooks.on_add(|mut world, entity, _| {
314 world.commands().add(move |world: &mut World| {
315 let event_type = world.init_component::<E>();
316 let mut components = Vec::new();
317 B::component_ids(&mut world.components, &mut world.storages, &mut |id| {
318 components.push(id);
319 });
320 let mut descriptor = ObserverDescriptor {
321 events: vec![event_type],
322 components,
323 ..Default::default()
324 };
325
326 // Initialize System
327 let system: *mut dyn ObserverSystem<E, B> =
328 if let Some(mut observe) = world.get_mut::<Self>(entity) {
329 descriptor.merge(&observe.descriptor);
330 &mut *observe.system
331 } else {
332 return;
333 };
334 // SAFETY: World reference is exclusive and initialize does not touch system, so references do not alias
335 unsafe {
336 (*system).initialize(world);
337 }
338
339 {
340 let mut entity = world.entity_mut(entity);
341 if let crate::world::Entry::Vacant(entry) = entity.entry::<ObserverState>() {
342 entry.insert(ObserverState {
343 descriptor,
344 runner: observer_system_runner::<E, B>,
345 ..Default::default()
346 });
347 }
348 }
349 });
350 });
351 }
352}
353
354/// Equivalent to [`BoxedSystem`](crate::system::BoxedSystem) for [`ObserverSystem`].
355pub type BoxedObserverSystem<E = (), B = ()> = Box<dyn ObserverSystem<E, B>>;
356
357fn observer_system_runner<E: Event, B: Bundle>(
358 mut world: DeferredWorld,
359 observer_trigger: ObserverTrigger,
360 ptr: PtrMut,
361) {
362 let world = world.as_unsafe_world_cell();
363 // SAFETY: Observer was triggered so must still exist in world
364 let observer_cell = unsafe {
365 world
366 .get_entity(observer_trigger.observer)
367 .debug_checked_unwrap()
368 };
369 // SAFETY: Observer was triggered so must have an `ObserverState`
370 let mut state = unsafe {
371 observer_cell
372 .get_mut::<ObserverState>()
373 .debug_checked_unwrap()
374 };
375
376 // TODO: Move this check into the observer cache to avoid dynamic dispatch
377 // SAFETY: We only access world metadata
378 let last_trigger = unsafe { world.world_metadata() }.last_trigger_id();
379 if state.last_trigger_id == last_trigger {
380 return;
381 }
382 state.last_trigger_id = last_trigger;
383
384 // SAFETY: Caller ensures `ptr` is castable to `&mut T`
385 let trigger: Trigger<E, B> = Trigger::new(unsafe { ptr.deref_mut() }, observer_trigger);
386 // SAFETY: the static lifetime is encapsulated in Trigger / cannot leak out.
387 // Additionally, IntoObserverSystem is only implemented for functions starting
388 // with for<'a> Trigger<'a>, meaning users cannot specify Trigger<'static> manually,
389 // allowing the Trigger<'static> to be moved outside of the context of the system.
390 // This transmute is obviously not ideal, but it is safe. Ideally we can remove the
391 // static constraint from ObserverSystem, but so far we have not found a way.
392 let trigger: Trigger<'static, E, B> = unsafe { std::mem::transmute(trigger) };
393 // SAFETY: Observer was triggered so must have an `ObserverSystemComponent`
394 let system = unsafe {
395 &mut observer_cell
396 .get_mut::<Observer<E, B>>()
397 .debug_checked_unwrap()
398 .system
399 };
400
401 system.update_archetype_component_access(world);
402
403 // SAFETY:
404 // - `update_archetype_component_access` was just called
405 // - there are no outstanding references to world except a private component
406 // - system is an `ObserverSystem` so won't mutate world beyond the access of a `DeferredWorld`
407 // - system is the same type erased system from above
408 unsafe {
409 system.run_unsafe(trigger, world);
410 system.queue_deferred(world.into_deferred());
411 }
412}