use bevy::prelude::*;
use crate::*;
#[derive(Debug, Default)]
pub struct AnimationsPlugin {
pub pixels_per_meter: f32,
}
impl Plugin for AnimationsPlugin {
fn build(&self, app: &mut App) {
app
.insert_resource(AnimationsConfig {
pixels_per_meter: self.pixels_per_meter,
})
.add_event::<AnimationEvent>()
.add_event::<ResetAnimationEvent>()
.add_event::<FXAnimationEvent>()
.insert_resource(Animations::default())
.insert_resource(EntitesToRemove::default())
.add_systems(Update, (
catch_fx_animation_events,
catch_animation_events,
catch_reset_events,
remove_entites
).chain())
;
}
}
fn catch_animation_events(
time: Res<Time>,
mut query: Query<(
&mut Handle<TextureAtlas>,
&mut TextureAtlasSprite,
&mut Transform,
&AnimationDirection
)>,
mut animations: ResMut<Animations>,
mut entities_to_remove: ResMut<EntitesToRemove>,
config: Res<AnimationsConfig>,
mut animation_events: EventReader<AnimationEvent>
) {
for event in animation_events.read() {
let animating_entity = animations.entities.get_mut(&event.1).expect(format!("Entity Not Found in Map For {} animation make sure your adding every necessary component to the entity i.e `AnimationDirection`", event.0).as_str());
let (mut texture_atlas, mut sprite, _, direction) = match query.get_mut(animating_entity.entity) {
Ok(handle) => handle,
Err(_) => {
entities_to_remove.0.push(event.1);
continue;
}
};
if animating_entity.curr_animation.lock().unwrap().get_name() != event.0 {
let new_animation_arc = animating_entity.animations.get(event.0).expect(format!("No Animation Found For `{}` make sure the name matches your configuration", event.0).as_str());
let mut new_animation = new_animation_arc.lock().unwrap();
let mut blocking = false;
let mut new_priority = 0;
let mut sprite_index = 0;
if let Some(new_timed_animation) = new_animation.timed_animation() {
blocking = new_timed_animation.blocking;
new_priority = new_timed_animation.blocking_priority;
sprite_index = new_timed_animation.sprite_index(&animating_entity.last_valid_direction);
}
else if let Some(new_singe_frame_animation) = new_animation.single_frame_animation() {
blocking = new_singe_frame_animation.blocking;
new_priority = new_singe_frame_animation.blocking_priority;
}
else if let Some(new_transform_animation) = new_animation.transform_animation() {
sprite_index = new_transform_animation.sprite_index(&animating_entity.last_valid_direction);
}
if animating_entity.in_blocking_animation {
let mut curr_animation = animating_entity.curr_animation.lock().unwrap();
if let Some(curr_timed_animation) = curr_animation.timed_animation() {
if curr_timed_animation.blocking_priority > new_priority {
continue;
}
}
else if let Some(curr_single_frame_animation) = curr_animation.single_frame_animation() {
if curr_single_frame_animation.blocking_priority > new_priority && !curr_single_frame_animation.blocking_finished {
continue;
}
}
else {
continue;
}
}
animating_entity.curr_animation.lock().unwrap().reset_animation();
animating_entity.curr_animation = new_animation_arc.clone();
animating_entity.in_blocking_animation = blocking;
sprite.index = sprite_index;
*texture_atlas = new_animation.get_atlas();
}
animating_entity.curr_animation_called = true;
if animating_entity.curr_direction != *direction {
animating_entity.curr_direction = direction.clone();
if *direction != AnimationDirection::Still {
animating_entity.last_valid_direction = direction.clone();
}
}
}
for (entity, animation_entity) in animations.entities.iter_mut() {
let (_, sprite, transform, _) = match query.get_mut(*entity) {
Ok(query) => query,
Err(_) => {
entities_to_remove.0.push(*entity);
continue;
}
};
let mut curr_animation = animation_entity.curr_animation.lock().unwrap();
if !animation_entity.curr_animation_called {
continue;
}
if let Some(transform_animation) = curr_animation.transform_animation() {
if animation_entity.in_blocking_animation {
continue;
}
if let None = transform_animation.cycle_animation(
sprite,
&animation_entity.last_valid_direction,
transform,
config.pixels_per_meter) {
animation_entity.curr_animation_called = false;
}
}
else if let Some(timed_animation) = curr_animation.timed_animation() {
if let None = timed_animation.cycle_animation(sprite, &animation_entity.last_valid_direction, time.delta()) {
animation_entity.in_blocking_animation = false;
animation_entity.curr_animation_called = false;
}
}
else if let Some(linear_timed_animation) = curr_animation.linear_timed_animation() {
if let None = linear_timed_animation.cycle_animation(sprite, time.delta()) {
animation_entity.in_blocking_animation = false;
animation_entity.curr_animation_called = false;
}
}
else if let Some(linear_transform_animation) = curr_animation.linear_transform_animation() {
if let None = linear_transform_animation.cycle_animation(
sprite,
&animation_entity.last_valid_direction,
transform,
config.pixels_per_meter) {
animation_entity.curr_animation_called = false;
}
}
else if let Some(single_frame_animation) = curr_animation.single_frame_animation() {
single_frame_animation.cycle_animation(sprite, &animation_entity.last_valid_direction, time.delta())
}
else {
panic!("Something Went Terribly Wrong Animating {} Check Your Configurations", curr_animation.get_name());
}
}
}
fn catch_reset_events(
mut query: Query<(
&mut TextureAtlasSprite,
&AnimationDirection
)>,
mut animations: ResMut<Animations>,
mut entities_to_remove: ResMut<EntitesToRemove>,
mut animation_events: EventReader<ResetAnimationEvent>
) {
for event in animation_events.read() {
let (sprite, direction) = match query.get_mut(event.0) {
Ok(q) => q,
Err(_) => {
entities_to_remove.0.push(event.0);
continue;
}
};
let mut curr_animation = animations.entities
.get_mut(&event.0)
.expect("Entity Not Found from `ResetAnimationEvent`")
.curr_animation
.lock()
.unwrap()
;
if let Some(timed_animation) = curr_animation.timed_animation() {
timed_animation.reset_animation(Some(sprite), Some(direction));
}
else if let Some(transform_animation) = curr_animation.transform_animation() {
transform_animation.reset_animation(Some(sprite), Some(direction));
}
else if let Some(linear_timed_animation) = curr_animation.linear_timed_animation() {
linear_timed_animation.reset_animation(Some(sprite));
}
else if let Some(linear_transform_animation) = curr_animation.linear_transform_animation() {
linear_transform_animation.reset_animation(Some(sprite), Some(direction));
}
else {
panic!("Something went terribly wrong getting the current animation");
}
}
}
fn catch_fx_animation_events(
mut event_reader: EventReader<FXAnimationEvent>,
mut commands: Commands,
mut animations: ResMut<Animations>
) {
for event in event_reader.read() {
let _ = animations.start_fx_animation(event.0, &mut commands, event.1);
}
}
fn remove_entites(
mut animations: ResMut<Animations>,
mut entities_to_remove: ResMut<EntitesToRemove>
) {
for entity in entities_to_remove.0.iter() {
animations.entities.remove(&entity);
}
entities_to_remove.0.clear();
}