
# Objective Add support for events that can be triggered from animation clips. This is useful when you need something to happen at a specific time in an animation. For example, playing a sound every time a characters feet hits the ground when walking. Closes #15494 ## Solution Added a new field to `AnimationClip`: `events`, which contains a list of `AnimationEvent`s. These are automatically triggered in `animate_targets` and `trigger_untargeted_animation_events`. ## Testing Added a couple of tests and example (`animation_events.rs`) to make sure events are triggered when expected. --- ## Showcase `Events` need to also implement `AnimationEvent` and `Reflect` to be used with animations. ```rust #[derive(Event, AnimationEvent, Reflect)] struct SomeEvent; ``` Events can be added to an `AnimationClip` by specifying a time and event. ```rust // trigger an event after 1.0 second animation_clip.add_event(1.0, SomeEvent); ``` And optionally, providing a target id. ```rust let id = AnimationTargetId::from_iter(["shoulder", "arm", "hand"]); animation_clip.add_event_to_target(id, 1.0, HandEvent); ``` I modified the `animated_fox` example to show off the feature.  --------- Co-authored-by: Matty <weatherleymatthew@gmail.com> Co-authored-by: Chris Biscardi <chris@christopherbiscardi.com> Co-authored-by: François Mockers <francois.mockers@vleue.com>
30 lines
1.1 KiB
Rust
30 lines
1.1 KiB
Rust
//! Derive macros for `bevy_animation`.
|
|
|
|
extern crate proc_macro;
|
|
|
|
use bevy_macro_utils::BevyManifest;
|
|
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::{parse_macro_input, DeriveInput};
|
|
|
|
/// Used to derive `AnimationEvent` for a type.
|
|
#[proc_macro_derive(AnimationEvent)]
|
|
pub fn derive_animation_event(input: TokenStream) -> TokenStream {
|
|
let ast = parse_macro_input!(input as DeriveInput);
|
|
let name = ast.ident;
|
|
let manifest = BevyManifest::default();
|
|
let bevy_animation_path = manifest.get_path("bevy_animation");
|
|
let bevy_ecs_path = manifest.get_path("bevy_ecs");
|
|
let animation_event_path = quote! { #bevy_animation_path::animation_event };
|
|
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
|
// TODO: This could derive Event as well.
|
|
quote! {
|
|
impl #impl_generics #animation_event_path::AnimationEvent for #name #ty_generics #where_clause {
|
|
fn trigger(&self, _time: f32, _weight: f32, entity: #bevy_ecs_path::entity::Entity, world: &mut #bevy_ecs_path::world::World) {
|
|
world.entity_mut(entity).trigger(Clone::clone(self));
|
|
}
|
|
}
|
|
}
|
|
.into()
|
|
}
|