Skip to main content

bevy_animation/
animation_event.rs

1pub use bevy_animation_macros::AnimationEvent;
2
3use bevy_ecs::{
4    entity::Entity,
5    event::{trigger_entity_internal, Event, Trigger},
6    observer::{CachedObservers, TriggerContext},
7    world::DeferredWorld,
8};
9
10/// An [`Event`] that an [`AnimationPlayer`](crate::AnimationPlayer) or an [`AnimationTargetId`](crate::AnimationTargetId) can trigger when playing an [`AnimationClip`](crate::AnimationClip).
11///
12/// - If you used [`AnimationClip::add_event`](crate::AnimationClip::add_event), this will be triggered by the [`AnimationPlayer`](crate::AnimationPlayer).
13/// - If you used [`AnimationClip::add_event_to_target`](crate::AnimationClip::add_event_to_target), this will be triggered by the [`AnimationTargetId`](crate::AnimationTargetId).
14///
15/// This trait can be derived.
16pub trait AnimationEvent: Clone + for<'a> Event<Trigger<'a> = AnimationEventTrigger> {}
17
18/// The [`Trigger`] implementation for [`AnimationEvent`]. This passes in either the [`AnimationPlayer`](crate::AnimationPlayer) or the [`AnimationTargetId`](crate::AnimationTargetId)
19/// context, and uses that to run any observers that target that entity. See [`AnimationEvent`] for when which entity is used.
20#[derive(#[automatically_derived]impl ::core::fmt::Debug for AnimationEventTrigger {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "AnimationEventTrigger", "target", &&self.target)
    }
}Debug)]
21pub struct AnimationEventTrigger {
22    /// The [`AnimationPlayer`](crate::AnimationPlayer) or the [`AnimationTargetId`](crate::AnimationTargetId) where this [`AnimationEvent`] occurred.
23    /// See [`AnimationEvent`] for when which entity is used.
24    pub target: Entity,
25}
26
27#[expect(
28    unsafe_code,
29    reason = "We must implement this trait to define a custom Trigger, which is required to be unsafe due to safety considerations within bevy_ecs."
30)]
31// SAFETY:
32// - `E`'s [`Event::Trigger`] is constrained to [`AnimationEventTrigger`]
33// - The implementation abides by the other safety constraints defined in [`Trigger`]
34unsafe impl<E: AnimationEvent + for<'a> Event<Trigger<'a> = AnimationEventTrigger>> Trigger<E>
35    for AnimationEventTrigger
36{
37    unsafe fn trigger(
38        &mut self,
39        world: DeferredWorld,
40        observers: &CachedObservers,
41        trigger_context: &TriggerContext,
42        event: &mut E,
43    ) {
44        let target = self.target;
45        // SAFETY:
46        // - `observers` come from `world` and match the event type `E`, enforced by the call to `trigger`
47        // - the passed in event pointer comes from `event`, which is an `Event`
48        // - `trigger` is a matching trigger type, as it comes from `self`, which is the Trigger for `E`
49        // - `trigger_context`'s event_key matches `E`, enforced by the call to `trigger`
50        // - this abides by the nuances defined in the `Trigger` safety docs
51        unsafe {
52            trigger_entity_internal(
53                world,
54                observers,
55                event.into(),
56                self.into(),
57                target,
58                trigger_context,
59            );
60        }
61    }
62}