Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animation Crate #482

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
872b7c7
first pass at animation
mcpar-land Sep 10, 2020
8f4b964
refactor into spline container struct from vec
mcpar-land Sep 10, 2020
fbc1de2
working example of Vec3 animation looping
mcpar-land Sep 10, 2020
a0acecc
animation_custom example
mcpar-land Sep 10, 2020
46d9228
removed unused imports
mcpar-land Sep 10, 2020
2acf7b5
massively simplified animation
mcpar-land Sep 11, 2020
520c653
removed unused import
mcpar-land Sep 11, 2020
6ba25c4
SplineGroup trait
mcpar-land Sep 12, 2020
4deda6b
lf line endings
mcpar-land Sep 12, 2020
3524f2e
cleaned up animation code
mcpar-land Sep 13, 2020
110a4cf
Merge remote-tracking branch 'upstream/master'
mcpar-land Sep 20, 2020
18024b6
Merge remote-tracking branch 'upstream/master'
mcpar-land Sep 21, 2020
39207e4
update bevy_animation to 0.2.1
mcpar-land Sep 21, 2020
e03a9a4
add code improvements
mcpar-land Sep 21, 2020
357c8a2
remove redundant closure
mcpar-land Sep 21, 2020
975fd99
Work in progress Quat animation
iwikal Oct 25, 2020
978dbbd
Remove shim now that it isn't needed
iwikal Nov 11, 2020
93a4a72
Add resampling extension to Spline
iwikal Nov 20, 2020
9586bf3
Merge remote-tracking branch 'upstream/master'
mcpar-land Nov 24, 2020
f74b687
fix rust_analyzer error:
mcpar-land Nov 24, 2020
3aba3ac
bevy_animation updated to 0.3.0
mcpar-land Nov 24, 2020
d65e0e9
formatting
mcpar-land Nov 24, 2020
c9443e2
Merge 'mcpar-land/master' into animation
iwikal Nov 26, 2020
0324d83
Format
iwikal Nov 26, 2020
71514a5
Error message for missing interpolation variants
iwikal Nov 26, 2020
6ece91e
Refactor and format animation example
iwikal Nov 26, 2020
378b38d
Enable impl-glam for splines
iwikal Nov 26, 2020
ab06147
Refactor away spline_key_times
iwikal Nov 30, 2020
a5fce5b
Fix some clippy warnings
iwikal Nov 30, 2020
a86e7cf
Merge pull request #1 from iwikal/animation
mcpar-land Nov 30, 2020
1184f1d
Merge branch 'master' into master
mcpar-land Nov 30, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ path = "examples/3d/texture.rs"
name = "z_sort_debug"
path = "examples/3d/z_sort_debug.rs"

[[example]]
name = "animation_2d"
path = "examples/animation/animation_2d.rs"

[[example]]
name = "animation_custom"
path = "examples/animation/animation_custom.rs"

[[example]]
name = "custom_loop"
path = "examples/app/custom_loop.rs"
Expand Down Expand Up @@ -359,4 +367,3 @@ icon = "@mipmap/ic_launcher"
build_targets = ["aarch64-linux-android", "armv7-linux-androideabi"]
min_sdk_version = 16
target_sdk_version = 29

24 changes: 24 additions & 0 deletions crates/bevy_animation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "bevy_animation"
version = "0.3.0"
edition = "2018"
authors = ["Bevy Contributors <bevyengine@gmail.com>", "Carter Anderson <mcanders1@gmail.com>"]
description = "Provides spline animation functionality for Bevy Engine"
homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy"
license = "MIT"
keywords = ["bevy"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bevy_core = { path = "../bevy_core", version = "0.3.0" }
bevy_math = { path = "../bevy_math", version = "0.3.0" }
bevy_app = { path = "../bevy_app", version = "0.3.0" }
bevy_utils = { path = "../bevy_utils", version = "0.3.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.3.0" }
bevy_transform = { path = "../bevy_transform", version = "0.3.0" }
bevy_render = { path = "../bevy_render", version = "0.3.0" }
bevy_property = { path = "../bevy_property", version = "0.3.0" }

splines = { version = "3.5.0", features = ["serialization", "impl-glam"] }
25 changes: 25 additions & 0 deletions crates/bevy_animation/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
pub mod plugin;
pub mod spline_group;
pub mod vec3_option;

pub mod spline_groups {
pub mod one;
pub mod three;
pub mod transform;
}

pub use plugin::AnimationPlugin;

pub mod prelude {
pub use crate::{
plugin::AnimationPlugin,
spline_group::{LoopStyle, SplineGroup},
spline_groups::{
one::AnimationSplineOne,
three::AnimationSplineThree,
transform::{AnimationSplineTransform, SplineQuatExt},
},
vec3_option::Vec3Option,
};
pub use splines::{Interpolate, Interpolation, Key, Spline};
}
55 changes: 55 additions & 0 deletions crates/bevy_animation/src/plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::{
spline_group::SplineGroup,
spline_groups::{
one::AnimationSplineOne, three::AnimationSplineThree, transform::AnimationSplineTransform,
},
};

use bevy_app::{AppBuilder, Plugin};
use bevy_core::Time;
use bevy_ecs::{IntoSystem, Query, Res};
use bevy_math::Vec3;
use bevy_transform::components::Transform;

#[derive(Default)]
pub struct AnimationPlugin;

impl Plugin for AnimationPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_system(advance_animation_spline)
.add_system(advance_animation_spline_three.system())
.add_system(advance_animation_transform.system());
}
}

fn advance_animation_spline(time: Res<Time>, mut q: Query<&mut AnimationSplineOne>) {
for mut animation_spline in q.iter_mut() {
animation_spline.advance(time.delta_seconds);
}
}

fn advance_animation_spline_three(time: Res<Time>, mut q: Query<&mut AnimationSplineThree>) {
for mut animation_spline in q.iter_mut() {
animation_spline.advance(time.delta_seconds);
}
}

fn advance_animation_transform(
time: Res<Time>,
mut q: Query<(&mut Transform, &mut AnimationSplineTransform)>,
) {
for (mut transform, mut splines) in q.iter_mut() {
let mut scale = transform.scale;
splines.advance(time.delta_seconds);
let sample = splines.current();
sample.translation.alter(&mut transform.translation);
if let Some(sample_scale) = sample.scale {
scale = Vec3::one() * sample_scale;
}
*transform = Transform::from_translation(transform.translation);
if let Some(rotation) = sample.rotation {
transform.rotation = rotation;
}
transform.apply_non_uniform_scale(scale);
}
}
127 changes: 127 additions & 0 deletions crates/bevy_animation/src/spline_group.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use core::time::Duration;
use splines::Spline;

pub(crate) trait SplineExt {
fn start_time(&self) -> Option<f32>;
fn end_time(&self) -> Option<f32>;
}

impl<V> SplineExt for Spline<f32, V> {
fn start_time(&self) -> Option<f32> {
self.keys().first().map(|k| k.t)
}

fn end_time(&self) -> Option<f32> {
self.keys().last().map(|k| k.t)
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LoopStyle {
Once,
Loop,
PingPong,
}

pub trait SplineGroup {
type Sample;

fn loop_style(&self) -> LoopStyle;
fn loop_style_mut(&mut self) -> &mut LoopStyle;

fn time(&self) -> f32;
fn time_mut(&mut self) -> &mut f32;

fn speed(&self) -> f32;
fn speed_mut(&mut self) -> &mut f32;

fn paused(&self) -> bool;
fn paused_mut(&mut self) -> &mut bool;

fn pong(&self) -> bool;
fn pong_mut(&mut self) -> &mut bool;

fn sample(&self, time: f32) -> Self::Sample;

fn current(&self) -> Self::Sample {
self.sample(self.time())
}

fn is_empty(&self) -> bool;

fn start_time(&self) -> Option<f32>;

fn end_time(&self) -> Option<f32>;

fn duration(&self) -> Option<Duration> {
self.start_time()
.zip(self.end_time())
.map(|(start, end)| (start - end).abs())
.map(Duration::from_secs_f32)
}

fn advance(&mut self, delta_time: f32) {
if self.is_empty() || self.paused() {
return;
}

let start = self.start_time().unwrap();
let end = self.end_time().unwrap();
let direction = self.speed().signum();
let reversed = direction < 0.0;
let past_boundary = match (reversed, self.pong()) {
(true, true) => end < self.time(),
(true, false) => start > self.time(),
(false, true) => start > self.time(),
(false, false) => end < self.time(),
};

let loop_time_start = if reversed { end } else { start };
let pong_signum = if self.pong() { -1.0 } else { 1.0 };

let speed = self.speed();
let loop_style = self.loop_style();
let pong = self.pong();
let time = self.time_mut();

let mut new_pong = pong;

match loop_style {
LoopStyle::Once => {
if !past_boundary {
*time += delta_time * speed;
}
}
LoopStyle::Loop => {
if !past_boundary {
*time += delta_time * speed;
} else {
*time = loop_time_start;
}
}
LoopStyle::PingPong => {
if !past_boundary {
*time += delta_time * speed * pong_signum;
} else {
new_pong = !pong;
*time = if new_pong { end } else { start };
}
}
};

*self.pong_mut() = new_pong;
}

fn pause(&mut self) {
*self.paused_mut() = true;
}

fn play(&mut self) {
*self.paused_mut() = false;
}

fn toggle_pause(&mut self) {
let paused = self.paused();
*self.paused_mut() = !paused;
}
}
84 changes: 84 additions & 0 deletions crates/bevy_animation/src/spline_groups/one.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use crate::spline_group::{LoopStyle, SplineExt, SplineGroup};
use splines::Spline;

pub struct AnimationSplineOne {
pub spline: Spline<f32, f32>,
pub loop_style: LoopStyle,
pub time: f32,
pub speed: f32,
pub paused: bool,
pub pong: bool,
}

impl Default for AnimationSplineOne {
fn default() -> Self {
Self {
spline: Spline::from_vec(vec![]),
loop_style: LoopStyle::Once,
time: 0.0,
speed: 1.0,
paused: false,
pong: false,
}
}
}

impl SplineGroup for AnimationSplineOne {
type Sample = Option<f32>;

fn is_empty(&self) -> bool {
self.spline.is_empty()
}

fn start_time(&self) -> Option<f32> {
self.spline.start_time()
}

fn end_time(&self) -> Option<f32> {
self.spline.end_time()
}

fn loop_style(&self) -> LoopStyle {
self.loop_style
}

fn loop_style_mut(&mut self) -> &mut LoopStyle {
&mut self.loop_style
}

fn time(&self) -> f32 {
self.time
}

fn time_mut(&mut self) -> &mut f32 {
&mut self.time
}

fn speed(&self) -> f32 {
self.speed
}

fn speed_mut(&mut self) -> &mut f32 {
&mut self.speed
}

fn paused(&self) -> bool {
self.paused
}

fn paused_mut(&mut self) -> &mut bool {
&mut self.paused
}

fn pong(&self) -> bool {
self.pong
}

fn pong_mut(&mut self) -> &mut bool {
&mut self.pong
}

fn sample(&self, time: f32) -> Self::Sample {
self.spline.sample(time)
}
}
Loading