animation_events/
animation_events.rs

1//! Demonstrate how to use animation events.
2
3use bevy::{
4    animation::AnimationEvent,
5    color::palettes::css::{ALICE_BLUE, BLACK, CRIMSON},
6    post_process::bloom::Bloom,
7    prelude::*,
8};
9
10fn main() {
11    App::new()
12        .add_plugins(DefaultPlugins)
13        .add_systems(Startup, setup)
14        .add_systems(Update, animate_text_opacity)
15        .add_observer(on_set_message)
16        .run();
17}
18
19#[derive(Component)]
20struct MessageText;
21
22#[derive(AnimationEvent, Clone)]
23struct SetMessage {
24    value: String,
25    color: Color,
26}
27
28fn on_set_message(
29    set_message: On<SetMessage>,
30    text: Single<(&mut Text2d, &mut TextColor), With<MessageText>>,
31) {
32    let (mut text, mut color) = text.into_inner();
33    text.0 = set_message.value.clone();
34    color.0 = set_message.color;
35}
36
37fn setup(
38    mut commands: Commands,
39    mut animations: ResMut<Assets<AnimationClip>>,
40    mut graphs: ResMut<Assets<AnimationGraph>>,
41) {
42    // Camera
43    commands.spawn((
44        Camera2d,
45        Camera {
46            clear_color: ClearColorConfig::Custom(BLACK.into()),
47            ..Default::default()
48        },
49        Bloom {
50            intensity: 0.4,
51            ..Bloom::NATURAL
52        },
53    ));
54
55    // The text that will be changed by animation events.
56    commands.spawn((
57        MessageText,
58        Text2d::default(),
59        TextFont {
60            font_size: 119.0,
61            ..default()
62        },
63        TextColor(Color::NONE),
64    ));
65
66    // Create a new animation clip.
67    let mut animation = AnimationClip::default();
68
69    // This is only necessary if you want the duration of the
70    // animation to be longer than the last event in the clip.
71    animation.set_duration(2.0);
72
73    // Add events at the specified time.
74    animation.add_event(
75        0.0,
76        SetMessage {
77            value: "HELLO".into(),
78            color: ALICE_BLUE.into(),
79        },
80    );
81    animation.add_event(
82        1.0,
83        SetMessage {
84            value: "BYE".into(),
85            color: CRIMSON.into(),
86        },
87    );
88
89    // Create the animation graph.
90    let (graph, animation_index) = AnimationGraph::from_clip(animations.add(animation));
91    let mut player = AnimationPlayer::default();
92    player.play(animation_index).repeat();
93
94    commands.spawn((AnimationGraphHandle(graphs.add(graph)), player));
95}
96
97// Slowly fade out the text opacity.
98fn animate_text_opacity(mut colors: Query<&mut TextColor>, time: Res<Time>) {
99    for mut color in &mut colors {
100        let a = color.0.alpha();
101        color.0.set_alpha(a - time.delta_secs());
102    }
103}