Path: blob/main/crates/bevy_ecs/src/observer/system_param.rs
6604 views
//! System parameters for working with observers.12use crate::{3bundle::Bundle,4change_detection::MaybeLocation,5event::{Event, PropagateEntityTrigger},6prelude::*,7traversal::Traversal,8};9use bevy_ptr::Ptr;10use core::{11fmt::Debug,12marker::PhantomData,13ops::{Deref, DerefMut},14};1516/// Type containing triggered [`Event`] information for a given run of an [`Observer`]. This contains the17/// [`Event`] data itself. It also provides access to the [`Trigger`](crate::event::Trigger), which for things like18/// [`EntityEvent`] with a [`PropagateEntityTrigger`], includes control over event propagation.19///20/// The generic `B: Bundle` is used to modify the further specialize the events that this observer is interested in.21/// The entity involved *does not* have to have these components, but the observer will only be22/// triggered if the event matches the components in `B`.23///24/// This is used to to avoid providing a generic argument in your event, as is done for [`Add`]25/// and the other lifecycle events.26///27/// Providing multiple components in this bundle will cause this event to be triggered by any28/// matching component in the bundle,29/// [rather than requiring all of them to be present](https://github.com/bevyengine/bevy/issues/15325).30// SAFETY WARNING!31// this type must _never_ expose anything with the 'w lifetime32// See the safety discussion on `Trigger` for more details.33pub struct On<'w, 't, E: Event, B: Bundle = ()> {34observer: Entity,35// SAFETY WARNING: never expose this 'w lifetime36event: &'w mut E,37// SAFETY WARNING: never expose this 'w lifetime38trigger: &'w mut E::Trigger<'t>,39// SAFETY WARNING: never expose this 'w lifetime40pub(crate) trigger_context: &'w TriggerContext,41_marker: PhantomData<B>,42}4344/// Deprecated in favor of [`On`].45#[deprecated(since = "0.17.0", note = "Renamed to `On`.")]46pub type Trigger<'w, 't, E, B = ()> = On<'w, 't, E, B>;4748impl<'w, 't, E: Event, B: Bundle> On<'w, 't, E, B> {49/// Creates a new instance of [`On`] for the given triggered event.50pub fn new(51event: &'w mut E,52observer: Entity,53trigger: &'w mut E::Trigger<'t>,54trigger_context: &'w TriggerContext,55) -> Self {56Self {57event,58observer,59trigger,60trigger_context,61_marker: PhantomData,62}63}6465/// Returns the event type of this [`On`] instance.66pub fn event_key(&self) -> EventKey {67self.trigger_context.event_key68}6970/// Returns a reference to the triggered event.71pub fn event(&self) -> &E {72self.event73}7475/// Returns a mutable reference to the triggered event.76pub fn event_mut(&mut self) -> &mut E {77self.event78}7980/// Returns a pointer to the triggered event.81pub fn event_ptr(&self) -> Ptr<'_> {82Ptr::from(&self.event)83}8485/// Returns the [`Trigger`](crate::event::Trigger) context for this event.86pub fn trigger(&self) -> &E::Trigger<'t> {87self.trigger88}8990/// Returns the mutable [`Trigger`](crate::event::Trigger) context for this event.91pub fn trigger_mut(&mut self) -> &mut E::Trigger<'t> {92self.trigger93}9495/// Returns the [`Entity`] of the [`Observer`] of the triggered event.96/// This allows you to despawn the observer, ceasing observation.97///98/// # Examples99///100/// ```rust101/// # use bevy_ecs::prelude::*;102///103/// #[derive(EntityEvent)]104/// struct AssertEvent {105/// entity: Entity,106/// }107///108/// fn assert_observer(event: On<AssertEvent>) {109/// assert_eq!(event.observer(), event.entity);110/// }111///112/// let mut world = World::new();113/// let entity = world.spawn(Observer::new(assert_observer)).id();114///115/// world.trigger(AssertEvent { entity });116/// ```117pub fn observer(&self) -> Entity {118self.observer119}120121/// Returns the source code location that triggered this observer, if the `track_location` cargo feature is enabled.122pub fn caller(&self) -> MaybeLocation {123self.trigger_context.caller124}125}126127impl<128'w,129't,130const AUTO_PROPAGATE: bool,131E: EntityEvent + for<'a> Event<Trigger<'a> = PropagateEntityTrigger<AUTO_PROPAGATE, E, T>>,132B: Bundle,133T: Traversal<E>,134> On<'w, 't, E, B>135{136/// A deprecated way to retrieve the entity that this [`EntityEvent`] targeted at.137///138/// Access the event via [`On::event`], then read the entity that the event was targeting.139/// Prefer using the field name directly for clarity,140/// but if you are working in a generic context, you can use [`EntityEvent::event_target`].141#[deprecated(142since = "0.17.0",143note = "Call On::event() to access the event, then read the target entity from the event directly."144)]145pub fn target(&self) -> Entity {146self.event.event_target()147}148149/// Returns the original [`Entity`] that this [`EntityEvent`] targeted via [`EntityEvent::event_target`] when it was _first_ triggered,150/// prior to any propagation logic.151pub fn original_event_target(&self) -> Entity {152self.trigger.original_event_target153}154155/// Enables or disables event propagation, allowing the same event to trigger observers on a chain of different entities.156///157/// The path an [`EntityEvent`] will propagate along is specified by the [`Traversal`] component defined in [`PropagateEntityTrigger`].158///159/// [`EntityEvent`] does not propagate by default. To enable propagation, you must:160/// + Enable propagation in [`EntityEvent`] using `#[entity_event(propagate)]`. See [`EntityEvent`] for details.161/// + Either call `propagate(true)` in the first observer or in the [`EntityEvent`] derive add `#[entity_event(auto_propagate)]`.162///163/// You can prevent an event from propagating further using `propagate(false)`. This will prevent the event from triggering on the next164/// [`Entity`] in the [`Traversal`], but note that all remaining observers for the _current_ entity will still run.165///166///167/// [`Traversal`]: crate::traversal::Traversal168pub fn propagate(&mut self, should_propagate: bool) {169self.trigger.propagate = should_propagate;170}171172/// Returns the value of the flag that controls event propagation. See [`propagate`] for more information.173///174/// [`propagate`]: On::propagate175pub fn get_propagate(&self) -> bool {176self.trigger.propagate177}178}179180impl<'w, 't, E: for<'a> Event<Trigger<'a>: Debug> + Debug, B: Bundle> Debug for On<'w, 't, E, B> {181fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {182f.debug_struct("On")183.field("event", &self.event)184.field("trigger", &self.trigger)185.field("_marker", &self._marker)186.finish()187}188}189190impl<'w, 't, E: Event, B: Bundle> Deref for On<'w, 't, E, B> {191type Target = E;192193fn deref(&self) -> &Self::Target {194self.event195}196}197198impl<'w, 't, E: Event, B: Bundle> DerefMut for On<'w, 't, E, B> {199fn deref_mut(&mut self) -> &mut Self::Target {200self.event201}202}203204/// Metadata about a specific [`Event`] that triggered an observer.205///206/// This information is exposed via methods on [`On`].207pub struct TriggerContext {208/// The [`EventKey`] the trigger targeted.209pub event_key: EventKey,210/// The location of the source code that triggered the observer.211pub caller: MaybeLocation,212}213214215