use crate::{ GameState, character::CharacterAnimations, head::ActiveHead, heads_database::HeadsDatabase, }; use bevy::{animation::RepeatAnimation, ecs::query::QueryData, prelude::*}; use std::time::Duration; pub fn plugin(app: &mut App) { app.register_type::(); app.add_systems( Update, update_animation.run_if(in_state(GameState::Playing)), ); } #[derive(Component, Default, Reflect)] #[reflect(Component)] pub struct AnimationFlags { pub any_direction: bool, pub jumping: bool, pub just_jumped: bool, pub shooting: bool, pub restart_shooting: bool, pub hit: bool, } #[derive(QueryData)] #[query_data(mutable)] pub struct AnimationController { pub transitions: &'static mut AnimationTransitions, pub player: &'static mut AnimationPlayer, } impl AnimationController { pub fn play_inner( player: &mut AnimationPlayer, transitions: &mut AnimationTransitions, animation: AnimationNodeIndex, transition: Duration, repeat: RepeatAnimation, ) { transitions .play(player, animation, transition) .set_repeat(repeat); } } impl AnimationControllerItem<'_> { pub fn play( &mut self, animation: AnimationNodeIndex, transition: Duration, repeat: RepeatAnimation, ) { AnimationController::play_inner( &mut self.player, &mut self.transitions, animation, transition, repeat, ); } pub fn is_playing(&self, index: AnimationNodeIndex) -> bool { self.player.is_playing_animation(index) } } const DEFAULT_TRANSITION_DURATION: Duration = Duration::ZERO; fn update_animation( mut animated: Query<( AnimationController, &CharacterAnimations, &mut AnimationFlags, )>, character: Query<&ActiveHead>, headdb: Res, ) { for (mut controller, anims, mut flags) in animated.iter_mut() { let head = character.get(anims.of_character).unwrap(); let head = headdb.head_stats(head.0); let is_playing_shoot = anims.shoot.is_some() && controller.is_playing(anims.shoot.unwrap()) && !controller .player .animation(anims.shoot.unwrap()) .unwrap() .is_finished(); let is_playing_run_shoot = anims.run_shoot.is_some() && controller.is_playing(anims.run_shoot.unwrap()) && !controller .player .animation(anims.run_shoot.unwrap()) .unwrap() .is_finished(); let wait_for_shoot = !head.interrupt_shoot && (is_playing_shoot || is_playing_run_shoot); if wait_for_shoot { return; } else if flags.shooting && flags.any_direction && anims.run_shoot.is_some() { if !controller.is_playing(anims.run_shoot.unwrap()) { controller.play( anims.run_shoot.unwrap(), DEFAULT_TRANSITION_DURATION, RepeatAnimation::Never, ); } if controller .player .animation(anims.run_shoot.unwrap()) .unwrap() .is_finished() || flags.restart_shooting { controller .player .animation_mut(anims.run_shoot.unwrap()) .unwrap() .replay(); flags.restart_shooting = false; } } else if flags.shooting && anims.shoot.is_some() { if !controller.is_playing(anims.shoot.unwrap()) { controller.play( anims.shoot.unwrap(), DEFAULT_TRANSITION_DURATION, RepeatAnimation::Never, ); } if controller .player .animation(anims.shoot.unwrap()) .unwrap() .is_finished() || flags.restart_shooting { controller .player .animation_mut(anims.shoot.unwrap()) .unwrap() .replay(); flags.restart_shooting = false; } } else if flags.hit { if !controller.is_playing(anims.hit) { controller.play( anims.hit, DEFAULT_TRANSITION_DURATION, RepeatAnimation::Never, ); } } else if flags.jumping { if !controller.is_playing(anims.jump) || flags.just_jumped { controller.play( anims.jump, DEFAULT_TRANSITION_DURATION, RepeatAnimation::Never, ); flags.just_jumped = false; } } else if flags.any_direction { if !controller.player.is_playing_animation(anims.run) { controller.play( anims.run, DEFAULT_TRANSITION_DURATION, RepeatAnimation::Forever, ); } } else if !controller.is_playing(anims.idle) { controller.play( anims.idle, DEFAULT_TRANSITION_DURATION, RepeatAnimation::Forever, ); } } }