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}