Fix animation bug
The solution was to put all animations into one graph! That way they can play together well.main
parent
44008a5b89
commit
4f5117f424
@ -0,0 +1,178 @@
|
||||
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<String, AnimationNodeIndex>,
|
||||
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<Assets<AnimationClip>>,
|
||||
mut graphs: ResMut<Assets<AnimationGraph>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let mut animation_store = AnimationStore::default();
|
||||
|
||||
let mut animation_graph = AnimationGraph::new();
|
||||
|
||||
let targets: Vec<AnimationTargetId> = 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::<u8>::new(0, 3).for_each(|x| {
|
||||
RangeInclusive::<u8>::new(0, 3).for_each(|y| {
|
||||
let a = Vec3::new(-400.0, -200.0, 0.0);
|
||||
let b = play::card_placement(&play::PlayLocation { x, y });
|
||||
let c = Vec3::new(400.0, -200.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<OnInsert, Selected>,
|
||||
mut query: Query<&mut AnimationPlayer>,
|
||||
store: Res<AnimationStore>,
|
||||
) {
|
||||
let ai = store.store.get("rotate".into()).unwrap();
|
||||
query
|
||||
.get_mut(trigger.entity())
|
||||
.unwrap()
|
||||
.play(ai.clone())
|
||||
.repeat();
|
||||
}
|
||||
|
||||
pub(crate) fn stop_selected_animation(
|
||||
trigger: Trigger<OnRemove, Selected>,
|
||||
mut query: Query<(&mut Transform, &mut AnimationPlayer)>,
|
||||
) {
|
||||
let (mut t, mut ap) = query.get_mut(trigger.entity()).unwrap();
|
||||
ap.stop_all();
|
||||
t.rotation = Quat::default();
|
||||
}
|
||||
|
||||
fn delayed_animation(
|
||||
mut query: Query<(Entity, &mut DelayedAnimation, &mut AnimationPlayer), With<AnimationTarget>>,
|
||||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
query
|
||||
.iter_mut()
|
||||
.for_each(|(entity, mut delayed_animation, mut animation_player)| {
|
||||
delayed_animation.delay.tick(time.delta());
|
||||
if delayed_animation.delay.just_finished() {
|
||||
info!("Playing delayed animation for {:?}", entity);
|
||||
animation_player.play(delayed_animation.animation_index);
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(delayed_animation.graph.clone())
|
||||
.remove::<DelayedAnimation>();
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue