use std::{f32::consts::PI, ops::RangeInclusive}; use bevy::{ animation::{animated_field, AnimationTarget, AnimationTargetId}, prelude::*, utils::HashMap, }; use crate::{ deck::Deck, play::{self, Selected}, }; pub struct AnimationPlugin; impl Plugin for AnimationPlugin { fn build(&self, app: &mut App) { app.add_systems(Update, delayed_animation); } } #[derive(Event, Clone)] struct AnimationComplete; #[derive(Resource, Default)] pub(crate) struct AnimationStore { pub store: HashMap, pub graph: AnimationGraphHandle, } #[derive(Component)] pub(crate) struct DelayedAnimation { pub graph: AnimationGraphHandle, pub animation_index: AnimationNodeIndex, pub delay: Timer, } pub(crate) fn setup_animations( mut clips: ResMut>, mut graphs: ResMut>, mut commands: Commands, ) { let mut animation_store = AnimationStore::default(); let mut animation_graph = AnimationGraph::new(); let targets: Vec = Deck::iter_cards() .map(|c| Name::new(format!("{}", c))) .map(|n| AnimationTargetId::from_name(&n)) .collect(); // Rotation Animation { let mut animation = AnimationClip::default(); targets.iter().for_each(|target| { let curve = AnimatableCurve::new( animated_field!(Transform::rotation), AnimatableKeyframeCurve::new([0.0, 5.0, 10.0, 15.0, 20.0].into_iter().zip([ Quat::IDENTITY, Quat::from_axis_angle(Vec3::Z, PI / 2.), Quat::from_axis_angle(Vec3::Z, PI / 2. * 2.), Quat::from_axis_angle(Vec3::Z, PI / 2. * 3.), Quat::IDENTITY, ])) .expect("Rotation animation"), ); animation.add_curve_to_target(*target, curve); }); let animation_handle = clips.add(animation); let animation_index = animation_graph.add_clip(animation_handle, 1.0, animation_graph.root); animation_store .store .insert("rotate".into(), animation_index); } { // For each spot on board RangeInclusive::::new(0, 3).for_each(|x| { RangeInclusive::::new(0, 3).for_each(|y| { let a = Vec3::new(-200.0, 0.0, 0.0); let b = play::card_placement(&play::PlayLocation { x, y }); let c = Vec3::new(200.0, 0.0, 0.0); // Serve Deck -> Spot Animation { let mut animation = AnimationClip::default(); targets.iter().for_each(|target| { let curve = AnimatableCurve::new( animated_field!(Transform::translation), AnimatableKeyframeCurve::new([0.0, 1.0].into_iter().zip([a, b])) .expect("Serve Card animation"), ); animation.add_curve_to_target(*target, curve); }); animation.set_duration(1.0); animation.add_event(1.0, AnimationComplete); let animation_handle = clips.add(animation); let animation_index = animation_graph.add_clip(animation_handle, 1.0, animation_graph.root); animation_store .store .insert(format!("deck->{:?}", (x, y)), animation_index); } // Spot -> Discard Animation { let mut animation = AnimationClip::default(); targets.iter().for_each(|target| { let curve = AnimatableCurve::new( animated_field!(Transform::translation), AnimatableKeyframeCurve::new([0.0, 1.0].into_iter().zip([b, c])) .expect("Serve Card animation"), ); animation.add_curve_to_target(*target, curve); }); animation.set_duration(1.0); animation.add_event(1.0, AnimationComplete); let animation_handle = clips.add(animation); let animation_index = animation_graph.add_clip(animation_handle, 1.0, animation_graph.root); animation_store .store .insert(format!("{:?}->discard", (x, y)), animation_index); } }); }); } animation_store.graph = AnimationGraphHandle(graphs.add(animation_graph)); commands.insert_resource(animation_store); // TODO: (example: https://bevyengine.org/examples/animation/animated-transform/) // Button Animations: // active_button_animation = AnimationClip::default() // color and size } pub(crate) fn play_selected_animation( trigger: Trigger, mut query: Query<&mut AnimationPlayer>, store: Res, ) { let ai = store.store.get("rotate".into()).unwrap(); query .get_mut(trigger.entity()) .unwrap() .start(ai.clone()) .repeat(); } pub(crate) fn stop_selected_animation( trigger: Trigger, mut query: Query<(&mut Transform, &mut AnimationPlayer)>, ) { let (mut t, mut ap) = query.get_mut(trigger.entity()).unwrap(); ap.rewind_all().stop_all(); t.rotation = Quat::default(); } fn delayed_animation( mut query: Query<(Entity, &mut DelayedAnimation, &mut AnimationPlayer), With>, mut commands: Commands, time: Res