1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
use ;
use ;
use *;
use crate::;
/// A Bevy event emitted when an animation reaches a point of interest:
/// - When a clip repetition ends
/// - When a clip ends (if the clip repeats multiple times, this only occurs at the end of the last repetition)
/// - When an animation repetition ends
/// - When an animation ends (if the animation repeats multiple times, this only occurs at the end of the last repetition)
/// - When an [animation marker](Marker) is hit
///
/// # Example
///
/// You can use those events to be notified of a clip/animation ending.
///
/// ```
/// # use bevy::prelude::*;
/// # use bevy_spritesheet_animation::prelude::*;
/// #[derive(Resource)]
/// struct MyDeathAnimation(Handle<Animation>);
///
/// fn create_death_animation(
/// mut commands: Commands,
/// # animation_handle: Handle<Animation>
/// ) {
/// // ... omitted: create an animated sprite
///
/// // To use this animation from another system, you might want to keep it around.
/// // For example, you could store it in a resource.
///
/// commands.insert_resource(MyDeathAnimation(animation_handle));
/// }
///
/// fn explode_on_death(
/// mut messages: MessageReader<AnimationEvent>,
/// my_death_animation: Res<MyDeathAnimation>,
/// ) {
/// for message in messages.read() {
/// match message {
/// // Some animation just ended and it was the main character's death animation
/// AnimationEvent::AnimationEnd { animation, .. } if *animation == my_death_animation.0 => {
/// # fn explode() {}
/// explode();
/// }
///
/// // Ignore other events
/// _ => (),
/// }
/// }
/// }
/// ```
///
/// # Example
///
/// You can also add markers to specific frames of a clip to be notified of an animation reaching points of interest.
///
/// ```
/// # use bevy::prelude::*;
/// # use bevy_spritesheet_animation::prelude::*;
/// #[derive(Resource)]
/// struct ShootMarker(Marker);
///
/// fn create_animated_sprite(
/// mut commands: Commands,
/// assets: Res<AssetServer>,
/// ) {
/// let image = assets.load("character.png");
///
/// let spritesheet = Spritesheet::new(&image, 8, 4);
///
/// // Let's create a marker to be notified when the exact frame (5) where the character shoots their gun is played
///
/// let bullet_goes_out_marker = Marker::new();
///
/// let animation = spritesheet
/// .create_animation()
/// .add_row(2)
/// .add_clip_marker(bullet_goes_out_marker, 5)
/// .build();
///
/// // To use this marker from another system, you might want to keep it around.
/// // For example, you could store it in a resource.
///
/// commands.insert_resource(ShootMarker(bullet_goes_out_marker));
///
/// // ... omitted: create an animated sprite
/// }
///
/// #[derive(Resource)]
/// struct MyMarker(Marker);
///
/// // We can watch events from any system and react to them
/// fn spawn_bullets(
/// mut messages: MessageReader<AnimationEvent>,
/// shoot_marker: Res<ShootMarker>,
///) {
/// for message in messages.read() {
/// match message {
/// // Some marker was just hit and it was our "bullet goes out" marker
/// AnimationEvent::MarkerHit { marker, .. } if *marker == shoot_marker.0 => {
/// // ... omitted: spawn a bullet entity
/// }
///
/// // Ignore other events
/// _ => (),
/// }
/// }
/// }
/// ```
/// A marker that designates a point of interest in an animation.
///
/// [MarkerHit](AnimationEvent::MarkerHit) events containing this marker are emitted when the corresponding frame is played.
///
/// Add markers to a clip with [AnimationBuilder::add_clip_marker()](crate::prelude::AnimationBuilder::add_clip_marker).
static NEXT_MARKER: AtomicUsize = new;