1use std::{
2 collections::HashMap,
3 sync::{Arc, Mutex},
4 time::Duration,
5};
6
7use bevy::prelude::*;
8
9mod animations;
10mod plugins;
11mod types;
12
13pub use animations::*;
14pub use plugins::*;
15pub use types::*;
16
17pub mod prelude {
18 pub use crate::animations::{
19 LinearTimedAnimation, LinearTransformAnimation, SingleFrameAnimation, TimedAnimation,
20 TransformAnimation,
21 };
22 pub use crate::plugins::AnimationsPlugin;
23 pub use crate::types::{
24 Animation, AnimationDirection, AnimationDirectionIndexes, AnimationEvent, AnimationName,
25 AnimationType, Animator, FXAnimationEvent, FXBasedDirection, FlipBasedDirection,
26 IndexBasedDirection, NewAnimation, ResetAnimationEvent, YIndex,
27 };
28 pub use crate::{Animations, AnimationsConfig};
29}
30
31#[derive(Component, Clone)]
32struct FXAnimation;
33
34#[derive(Debug, Resource, Default)]
35pub struct AnimationsConfig {
36 pixels_per_meter: f32,
37}
38
39#[derive(Debug, Resource, Default)]
40pub struct EntitesToRemove(Vec<Entity>);
41
42#[derive(Component, Deref, DerefMut, Clone, Debug, Default)]
43pub struct AnimationTimer(pub Timer);
44
45#[derive(Debug)]
46pub struct AnimatingEntity {
47 pub entity: Entity,
48 pub in_blocking_animation: bool,
49 pub animations: HashMap<AnimationName, Arc<Mutex<AnimationType>>>,
50 pub curr_animation: Arc<Mutex<AnimationType>>,
51 pub curr_direction: AnimationDirection,
52 pub last_valid_direction: AnimationDirection,
53 pub curr_animation_called: bool,
54 pub fx_animation: bool,
55}
56
57#[derive(Default, Resource, Debug)]
58pub struct Animations {
59 entities: HashMap<Entity, AnimatingEntity>,
60 animations: HashMap<AnimationName, Animation>,
61 fx_animations: HashMap<AnimationName, Animation>,
62}
63
64impl Animations {
65 pub fn insert_animation(
72 &mut self,
73 animation: NewAnimation,
74 entity: Option<Entity>,
75 ) -> &mut Self {
76 let name = animation.animation.get_name();
77 let animation = Animation {
78 handles: animation.handles,
79 animation: Arc::new(Mutex::new(animation.animation)),
80 };
81 let new_animation = Arc::clone(&animation.animation);
82 let animation = animation;
83 if self.animations.get_mut(&name).is_none() {
84 self.animations.insert(name, animation);
85 }
86 if let Some(entity) = entity {
87 if let Some(animating_entity) = self.entities.get_mut(&entity) {
88 animating_entity
89 .animations
90 .insert(name, Arc::clone(&new_animation));
91 } else {
92 let mut map = HashMap::new();
93 map.insert(name, Arc::clone(&new_animation));
94 self.entities.insert(
95 entity,
96 AnimatingEntity {
97 entity,
98 animations: map,
99 curr_animation: new_animation,
100 curr_direction: AnimationDirection::Still,
101 last_valid_direction: AnimationDirection::default(),
102 in_blocking_animation: false,
103 curr_animation_called: false,
104 fx_animation: false,
105 },
106 );
107 }
108 }
109 self
110 }
111
112 pub fn insert_entity(&mut self, entity: Entity) -> Result<(), String> {
116 if self.entities.contains_key(&entity) {
117 return Err(format!(
118 "Entity {:?} already exists in `Animations`",
119 entity
120 ));
121 }
122 self.entities.insert(
123 entity,
124 AnimatingEntity {
125 entity,
126 animations: HashMap::new(),
127 curr_animation: Arc::new(Mutex::new(AnimationType::default())),
128 curr_direction: AnimationDirection::Still,
129 last_valid_direction: AnimationDirection::default(),
130 in_blocking_animation: false,
131 curr_animation_called: false,
132 fx_animation: false,
133 },
134 );
135 Ok(())
136 }
137
138 pub fn add_animation_to_entity(
142 &mut self,
143 animation_name: AnimationName,
144 entity: Entity,
145 ) -> Result<(), String> {
146 if let Some(animation) = self.animations.get_mut(&animation_name) {
147 let ac_animation = Arc::new(Mutex::new(animation.animation.lock().unwrap().clone()));
148 if let Some(entity) = self.entities.get_mut(&entity) {
149 if entity.animations.contains_key(&animation_name) {
150 return Err(format!(
151 "Animation {:?} already exists on entity {:?}",
152 animation_name, entity.entity
153 ));
154 }
155 if entity.curr_animation.lock().unwrap().is_none() {
156 entity.curr_animation = Arc::clone(&ac_animation);
157 }
158 entity.animations.insert(animation_name, ac_animation);
159 } else {
160 let mut map = HashMap::new();
161 map.insert(animation_name, Arc::clone(&ac_animation));
162 self.entities.insert(
163 entity,
164 AnimatingEntity {
165 entity,
166 animations: map,
167 curr_animation: ac_animation,
168 curr_direction: AnimationDirection::Still,
169 last_valid_direction: AnimationDirection::default(),
170 in_blocking_animation: false,
171 curr_animation_called: false,
172 fx_animation: false,
173 },
174 );
175 }
176 }
177 Ok(())
178 }
179
180 pub fn get_handles(&self, animation_name: AnimationName) -> Option<Handles> {
182 if let Some(animation) = self.animations.get(&animation_name) {
183 return Some(animation.handles.clone());
184 }
185 None
186 }
187
188 pub fn get_fx_handles(
192 &self,
193 animation_name: AnimationName,
194 ) -> Option<Handles> {
195 if let Some(animation) = self.fx_animations.get(&animation_name) {
196 return Some(animation.handles.clone());
197 }
198 None
199 }
200
201 pub fn get_entity(&mut self, entity: &Entity) -> Option<&mut AnimatingEntity> {
205 if let Some(animating_entity) = self.entities.get_mut(entity) {
206 return Some(animating_entity);
207 }
208 None
209 }
210
211 pub fn is_new_animation(&self, animation_name: AnimationName, entity: &Entity) -> Option<bool> {
215 if let Some(animating_entity) = self.entities.get(entity) {
216 if animating_entity.curr_animation.lock().unwrap().get_name() != animation_name {
217 return Some(true);
218 }
219 return Some(false);
220 }
221 None
222 }
223
224 pub fn has_entity(&self, entity: &Entity) -> bool {
226 if self.entities.contains_key(entity) {
227 return true;
228 }
229 false
230 }
231
232 pub fn insert_fx_animation(&mut self, value: NewAnimation) -> &mut Self {
234 let key = value.animation.get_name();
235 if self.fx_animations.contains_key(key) {
236 self
237 } else {
238 let animation = Animation {
239 handles: value.handles,
240 animation: Arc::new(Mutex::new(value.animation)),
241 };
242 self.fx_animations.insert(key, animation);
243 self
244 }
245 }
246
247 pub fn start_fx_animation(
253 &mut self,
254 key: Entity,
255 animation: AnimationName,
256 pos: Vec3,
257 ) -> Result<(SpriteBundle, TextureAtlas), ()> {
258 let name = animation;
259 let Some(animation) = self.fx_animations.get(animation) else {
260 return Err(());
261 };
262 let mut animation = animation.animation.lock().unwrap().clone();
263
264 let index = if let Some(timed_animation) = animation.timed_animation() {
265 timed_animation.sprite_index(&AnimationDirection::default())
266 } else if let Some(transform_animation) = animation.transform_animation() {
267 transform_animation.sprite_index(&AnimationDirection::default())
268 } else if let Some(linear_timed_animation) = animation.linear_timed_animation() {
269 linear_timed_animation.sprite_index(&AnimationDirection::default())
270 } else if let Some(linear_transform_animation) = animation.linear_transform_animation() {
271 linear_transform_animation.sprite_index(&AnimationDirection::default())
272 } else if let Some(single_frame_animation) = animation.single_frame_animation() {
273 single_frame_animation.sprite_index(&AnimationDirection::default())
274 } else {
275 panic!("Something Went Terribly Wrong Starting FX Animation");
276 };
277
278 let handles: Handles = self
280 .get_fx_handles(name)
281 .unwrap_or_else(|| panic!("There was a problem starting FX animation {}", name))
282 .into();
283 let texture_atlas = TextureAtlas {
284 layout: handles.layout().clone(),
285 index
286 };
287 self.entities.insert(
289 key,
290 AnimatingEntity {
291 entity: key,
292 in_blocking_animation: false,
293 animations: HashMap::new(),
294 curr_animation: Arc::new(Mutex::new(animation)),
295 curr_direction: AnimationDirection::default(),
296 last_valid_direction: AnimationDirection::default(),
297 curr_animation_called: true,
298 fx_animation: true,
299 },
300 );
301 Ok((
302 SpriteBundle {
303 transform: Transform::from_translation(pos),
304 texture: handles.image().clone(),
305 ..Default::default()
306 },
307 texture_atlas
308 ))
309 }
315
316 pub fn has_animation(&self, animation_name: AnimationName) -> bool {
318 if self.animations.contains_key(animation_name) {
319 return true;
320 }
321 false
322 }
323
324 pub fn entity_has_animation(
330 &self,
331 animation_name: &AnimationName,
332 entity: Entity,
333 ) -> Option<()> {
334 if let Some(animating_entity) = self.entities.get(&entity) {
335 if animating_entity.animations.contains_key(animation_name) {
336 return Some(());
337 }
338 return None;
339 }
340 None
341 }
342
343 pub fn in_blocking_animation(&self, entity: Entity) -> Option<bool> {
349 self.entities
350 .get(&entity)
351 .map(|animating_entity| animating_entity.in_blocking_animation)
352 }
353
354 pub fn in_animation(&self, entity: Entity) -> Option<bool> {
360 self.entities
361 .get(&entity)
362 .map(|animating_entity| animating_entity.curr_animation_called)
363 }
364
365 pub fn doing_animation(&self, entity: Entity, animation_name: AnimationName) -> Option<bool> {
371 self.entities.get(&entity).map(|animating_entity| {
372 animating_entity.curr_animation_called
373 && animating_entity.curr_animation.lock().unwrap().get_name() == animation_name
374 })
375 }
376
377 pub fn is_inserted(&self, key: &Entity) -> bool {
379 if self.entities.contains_key(key) {
380 return true;
381 }
382 false
383 }
384
385 pub fn get_mut_map(&mut self) -> &mut HashMap<Entity, AnimatingEntity> {
387 &mut self.entities
388 }
389
390 pub fn get_map(&self) -> &HashMap<Entity, AnimatingEntity> {
392 &self.entities
393 }
394}