Path: blob/main/crates/bevy_ecs/src/observer/system_param.rs
6849 views
//! System parameters for working with observers.12use crate::{3bundle::Bundle,4change_detection::MaybeLocation,5event::{Event, EventKey, PropagateEntityTrigger},6prelude::*,7traversal::Traversal,8};9use bevy_ptr::Ptr;10use core::{11fmt::Debug,12marker::PhantomData,13ops::{Deref, DerefMut},14};1516/// A [system parameter] used by an observer to process events. See [`Observer`] and [`Event`] for examples.17///18/// `On` contains the triggered [`Event`] data for a given run of an `Observer`. It also provides access to the19/// [`Trigger`](crate::event::Trigger), which for things like [`EntityEvent`] with a [`PropagateEntityTrigger`],20/// includes control over event propagation.21///22/// The generic `B: Bundle` is used to further specialize the events that this observer is interested in.23/// The entity involved *does not* have to have these components, but the observer will only be24/// triggered if the event matches the components in `B`.25///26/// This is used to to avoid providing a generic argument in your event, as is done for [`Add`]27/// and the other lifecycle events.28///29/// Providing multiple components in this bundle will cause this event to be triggered by any30/// matching component in the bundle,31/// [rather than requiring all of them to be present](https://github.com/bevyengine/bevy/issues/15325).32///33/// [system parameter]: crate::system::SystemParam34// SAFETY WARNING!35// this type must _never_ expose anything with the 'w lifetime36// See the safety discussion on `Trigger` for more details.37pub struct On<'w, 't, E: Event, B: Bundle = ()> {38observer: Entity,39// SAFETY WARNING: never expose this 'w lifetime40event: &'w mut E,41// SAFETY WARNING: never expose this 'w lifetime42trigger: &'w mut E::Trigger<'t>,43// SAFETY WARNING: never expose this 'w lifetime44trigger_context: &'w TriggerContext,45_marker: PhantomData<B>,46}4748/// Deprecated in favor of [`On`].49#[deprecated(since = "0.17.0", note = "Renamed to `On`.")]50pub type Trigger<'w, 't, E, B = ()> = On<'w, 't, E, B>;5152impl<'w, 't, E: Event, B: Bundle> On<'w, 't, E, B> {53/// Creates a new instance of [`On`] for the given triggered event.54pub fn new(55event: &'w mut E,56observer: Entity,57trigger: &'w mut E::Trigger<'t>,58trigger_context: &'w TriggerContext,59) -> Self {60Self {61event,62observer,63trigger,64trigger_context,65_marker: PhantomData,66}67}6869/// Returns the event type of this [`On`] instance.70pub fn event_key(&self) -> EventKey {71self.trigger_context.event_key72}7374/// Returns a reference to the triggered event.75pub fn event(&self) -> &E {76self.event77}7879/// Returns a mutable reference to the triggered event.80pub fn event_mut(&mut self) -> &mut E {81self.event82}8384/// Returns a pointer to the triggered event.85pub fn event_ptr(&self) -> Ptr<'_> {86Ptr::from(&self.event)87}8889/// Returns the [`Trigger`](crate::event::Trigger) context for this event.90pub fn trigger(&self) -> &E::Trigger<'t> {91self.trigger92}9394/// Returns the mutable [`Trigger`](crate::event::Trigger) context for this event.95pub fn trigger_mut(&mut self) -> &mut E::Trigger<'t> {96self.trigger97}9899/// Returns the [`Entity`] of the [`Observer`] of the triggered event.100/// This allows you to despawn the observer, ceasing observation.101///102/// # Examples103///104/// ```rust105/// # use bevy_ecs::prelude::*;106///107/// #[derive(EntityEvent)]108/// struct AssertEvent {109/// entity: Entity,110/// }111///112/// fn assert_observer(event: On<AssertEvent>) {113/// assert_eq!(event.observer(), event.entity);114/// }115///116/// let mut world = World::new();117/// let entity = world.spawn(Observer::new(assert_observer)).id();118///119/// world.trigger(AssertEvent { entity });120/// ```121pub fn observer(&self) -> Entity {122self.observer123}124125/// Returns the source code location that triggered this observer, if the `track_location` cargo feature is enabled.126pub fn caller(&self) -> MaybeLocation {127self.trigger_context.caller128}129}130131impl<'w, 't, E: EntityEvent, B: Bundle> On<'w, 't, E, B> {132/// A deprecated way to retrieve the entity that this [`EntityEvent`] targeted at.133///134/// Access the event via [`On::event`], then read the entity that the event was targeting.135/// Prefer using the field name directly for clarity,136/// but if you are working in a generic context, you can use [`EntityEvent::event_target`].137#[deprecated(138since = "0.17.0",139note = "Call On::event() to access the event, then read the target entity from the event directly."140)]141pub fn target(&self) -> Entity {142self.event.event_target()143}144}145146impl<147'w,148't,149const AUTO_PROPAGATE: bool,150E: EntityEvent + for<'a> Event<Trigger<'a> = PropagateEntityTrigger<AUTO_PROPAGATE, E, T>>,151B: Bundle,152T: Traversal<E>,153> On<'w, 't, E, B>154{155/// Returns the original [`Entity`] that this [`EntityEvent`] targeted via [`EntityEvent::event_target`] when it was _first_ triggered,156/// prior to any propagation logic.157pub fn original_event_target(&self) -> Entity {158self.trigger.original_event_target159}160161/// Enables or disables event propagation, allowing the same event to trigger observers on a chain of different entities.162///163/// The path an [`EntityEvent`] will propagate along is specified by the [`Traversal`] component defined in [`PropagateEntityTrigger`].164///165/// [`EntityEvent`] does not propagate by default. To enable propagation, you must:166/// + Enable propagation in [`EntityEvent`] using `#[entity_event(propagate)]`. See [`EntityEvent`] for details.167/// + Either call `propagate(true)` in the first observer or in the [`EntityEvent`] derive add `#[entity_event(auto_propagate)]`.168///169/// You can prevent an event from propagating further using `propagate(false)`. This will prevent the event from triggering on the next170/// [`Entity`] in the [`Traversal`], but note that all remaining observers for the _current_ entity will still run.171///172///173/// [`Traversal`]: crate::traversal::Traversal174pub fn propagate(&mut self, should_propagate: bool) {175self.trigger.propagate = should_propagate;176}177178/// Returns the value of the flag that controls event propagation. See [`propagate`] for more information.179///180/// [`propagate`]: On::propagate181pub fn get_propagate(&self) -> bool {182self.trigger.propagate183}184}185186impl<'w, 't, E: for<'a> Event<Trigger<'a>: Debug> + Debug, B: Bundle> Debug for On<'w, 't, E, B> {187fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {188f.debug_struct("On")189.field("event", &self.event)190.field("trigger", &self.trigger)191.field("_marker", &self._marker)192.finish()193}194}195196impl<'w, 't, E: Event, B: Bundle> Deref for On<'w, 't, E, B> {197type Target = E;198199fn deref(&self) -> &Self::Target {200self.event201}202}203204impl<'w, 't, E: Event, B: Bundle> DerefMut for On<'w, 't, E, B> {205fn deref_mut(&mut self) -> &mut Self::Target {206self.event207}208}209210/// Metadata about a specific [`Event`] that triggered an observer.211///212/// This information is exposed via methods on [`On`].213pub struct TriggerContext {214/// The [`EventKey`] the trigger targeted.215pub event_key: EventKey,216/// The location of the source code that triggered the observer.217pub caller: MaybeLocation,218}219220221