You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
6.2 KiB
Rust
178 lines
6.2 KiB
Rust
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(-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<OnInsert, Selected>,
|
|
mut query: Query<&mut AnimationPlayer>,
|
|
store: Res<AnimationStore>,
|
|
) {
|
|
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<OnRemove, Selected>,
|
|
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<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() {
|
|
animation_player.start(delayed_animation.animation_index);
|
|
commands
|
|
.entity(entity)
|
|
.insert(delayed_animation.graph.clone())
|
|
.remove::<DelayedAnimation>();
|
|
}
|
|
});
|
|
}
|