use core::panic;
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 TextureAtlas,
&mut Handle<Image>,
&mut Sprite,
&mut Transform,
&Animator,
)>,
mut animations: ResMut<Animations>,
mut entities_to_remove: ResMut<EntitesToRemove>,
config: Res<AnimationsConfig>,
mut animation_events: EventReader<AnimationEvent>,
mut commands: Commands,
) {
for event in animation_events.read() {
if !animations.has_entity(&event.1) {
panic!("Entity Not Found in Map For {} animation make sure your adding every necessary component to the entity i.e `Animator`", event.0);
}
if !animations.has_animation(event.0) {
panic!("Animation {} not found", event.0);
}
let (mut texture_atlas, mut texture, _, _, animator) =
match query.get_mut(event.1) {
Ok(handle) => handle,
Err(_) => {
entities_to_remove.0.push(event.1);
continue;
}
};
let direction = animator.get_direction();
if animations
.is_new_animation(event.0, &event.1)
.unwrap_or_else(|| {
panic!(
"Something Went Terribly Wrong Getting New Animation For {}",
event.0
)
})
{
let new_animation_handles = animations.get_handles(event.0).unwrap_or_else(|| {
panic!(
"Something Went Terribly Wrong Getting Animation For {}",
event.0
)
});
let animating_entity = animations.get_entity(&event.1).unwrap_or_else(|| panic!("Entity Not Found in Map For {} animation make sure your adding every necessary component to the entity i.e `AnimationDirection`", event.0));
let Some(new_animation_arc) = animating_entity.animations.get(event.0) else {
panic!("Animation `{}` not found for {:?} make sure the name matches your configuration", event.0, animating_entity.entity);
};
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;
sprite_index =
new_singe_frame_animation.sprite_index(&animating_entity.last_valid_direction);
}
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;
texture_atlas.index = sprite_index;
texture_atlas.layout = new_animation_handles.layout();
*texture = new_animation_handles.image();
}
let animating_entity = animations.get_entity(&event.1).unwrap_or_else(|| panic!("Entity Not Found in Map For {} animation make sure your adding every necessary component to the entity i.e `AnimationDirection`", event.0));
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 (texture_atlas, _, sprite, transform, _) =
match query.get_mut(*entity) {
Ok(query) => query,
Err(_) => {
if !animation_entity.fx_animation {
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 transform_animation.cycle_animation(
sprite,
texture_atlas,
&animation_entity.last_valid_direction,
transform,
config.pixels_per_meter,
).is_none() {
if animation_entity.fx_animation {
entities_to_remove.0.push(*entity);
commands.entity(*entity).despawn_recursive();
}
animation_entity.curr_animation_called = false;
}
}
else if let Some(timed_animation) = curr_animation.timed_animation() {
if timed_animation.cycle_animation(
sprite,
texture_atlas,
&animation_entity.last_valid_direction,
time.delta(),
).is_none() {
if animation_entity.fx_animation {
entities_to_remove.0.push(*entity);
commands.entity(*entity).despawn_recursive();
}
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 linear_timed_animation.cycle_animation(texture_atlas, time.delta()).is_none() {
if animation_entity.fx_animation {
entities_to_remove.0.push(*entity);
commands.entity(*entity).despawn_recursive();
}
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 linear_transform_animation.cycle_animation(
texture_atlas,
transform,
config.pixels_per_meter,
).is_none() {
if animation_entity.fx_animation {
entities_to_remove.0.push(*entity);
commands.entity(*entity).despawn_recursive();
}
animation_entity.curr_animation_called = false;
}
}
else if let Some(single_frame_animation) = curr_animation.single_frame_animation() {
single_frame_animation.cycle_animation(
sprite,
texture_atlas,
&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 Sprite, &mut TextureAtlas, &Animator)>,
mut animations: ResMut<Animations>,
mut entities_to_remove: ResMut<EntitesToRemove>,
mut animation_events: EventReader<ResetAnimationEvent>,
) {
for event in animation_events.read() {
let (sprite, texture_atlas, animator) = match query.get_mut(event.0) {
Ok(q) => q,
Err(_) => {
entities_to_remove.0.push(event.0);
continue;
}
};
let direction = animator.get_direction();
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(texture_atlas), Some(direction));
}
else if let Some(transform_animation) = curr_animation.transform_animation() {
transform_animation.reset_animation(Some(sprite), Some(texture_atlas), Some(direction));
}
else if let Some(linear_timed_animation) = curr_animation.linear_timed_animation() {
linear_timed_animation.reset_animation(Some(texture_atlas));
}
else if let Some(linear_transform_animation) = curr_animation.linear_transform_animation()
{
linear_transform_animation.reset_animation(Some(texture_atlas));
}
else if let Some(single_frame_animation) = curr_animation.single_frame_animation() {
single_frame_animation.reset_animation(Some(sprite), Some(direction));
} else {
panic!("Something went terribly wrong resetting 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 entity = commands.spawn(Animator::default()).id();
let Ok(sprite_sheet_bundle) = animations.start_fx_animation(entity, event.0, event.1)
else {
warn!("There was a problem spawning your FXAnimation {}", event.0);
continue;
};
commands
.entity(entity)
.insert(sprite_sheet_bundle)
.insert(FXAnimation)
.insert(Name::new("FX Animation"));
}
}
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();
}