1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
//! A simple library for animation in Rust
//!
//! ## Usage
//!
//! Tweening between two values is done with [`ease(function, from, to, time)`](fn.ease.html).
//! `from` and `to` can be any type that implements [`CanTween`], such as `f64` or `mint::Vector2`, while `time` needs to be a floating-point value between zero and one.
//! `function` specifies the transition between `from` and `to` and is any type that implements [`EasingFunction`].
//!
//! [`AnimationSequence`] can be used to create more complex animations that keep track of keyframes, time, etc.
//! You can create animation sequences with the [`keyframes![...]`](macro.keyframes.html) macro, from an iterator or from a vector.
//!
//! ## Embedded
//!
//! This library is embedded compatible. As default it uses the `alloc` crate for dynamic memory usage. So, if the `alloc` feature is turned off,
//! by setting `default-features = false`, this `crate` can be used without dynamic memory usage. Keep in mind that this will disable the feature `mint_types`
//! as well. This must be enabled by hand again.
//!
//! Disabled features:
//! - [`Keyframe`]
//! - [`AnimationSequence`]
//!
//!
//! ## Examples
//!
//! An example visualizer is included in `examples/`. Run `cargo run --example visualizer --release` to start it. (ggez is really slow in debug mode!)
//!
//! Tweening:
//!
//! ```rust
//! use keyframe::{ease, functions::EaseInOut};
//!
//! fn example() -> f64 {
//! let a = 0.0;
//! let b = 2.0;
//! let time = 0.5;
//!
//! ease(EaseInOut, a, b, time)
//! }
//! ```
//!
//! Animation sequences:
//!
//! ```rust
//! use keyframe::{keyframes, Keyframe, AnimationSequence, functions::Linear};
//!
//! fn example() {
//! // (value, time) or (value, time, function)
//! let mut sequence = keyframes![
//! (0.5, 0.0), // <-- EaseInOut used from 0.0 to 0.3
//! (1.5, 0.3, Linear), // <-- Linear used from 0.3 to 1.0
//! (2.5, 1.0) // <-- Easing function here is never used, since we're at the end
//! ];
//!
//! sequence.advance_by(0.65);
//!
//! assert_eq!(sequence.now(), 2.0);
//! assert_eq!(sequence.duration(), 1.0);
//! }
//! ```
//!
//! Custom structures:
//!
//! ```rust
//! use keyframe::mint::Point2;
//! // This macro works with any structure as long as it only consists of types that implement "CanTween"
//! use keyframe_derive::CanTween;
//!
//! #[derive(CanTween)]
//! struct MySubStructure {
//! a: f32
//! }
//!
//! #[derive(CanTween)]
//! struct MyStructure {
//! a: f64,
//! b: Point2<f64>,
//! c: f32,
//! d: [MySubStructure; N] // Array length matching is guaranteed by the type system
//! }
//!
//! // Also works with unnamed structures
//! #[derive(CanTween)]
//! struct UnnamedStructure(MyStructure, f64);
//! ```
#![no_std]
#[cfg(feature = "mint_types")]
pub use mint;
pub use num_traits;
#[cfg(feature = "mint_types")]
pub(crate) use mint::{Point2, Point3, Vector2, Vector3, Vector4};
pub(crate) use num_traits::Float;
#[cfg(feature = "alloc")]
extern crate alloc;
pub(crate) fn as_f64(value: impl Float) -> f64 {
value.to_f64().expect("Value not representable in f64")
}
pub(crate) fn as_t<T: Float>(value: f64) -> T {
match value {
_ if value > as_f64(T::max_value()) => T::max_value(),
_ if value < as_f64(T::min_value()) => T::min_value(),
#[cfg(feature = "alloc")]
_ => T::from(value).unwrap_or_else(|| panic!("{} not representable in chosen float type", value)),
#[cfg(not(feature = "alloc"))]
_ => T::from(value).expect("value not representable in chosen float type"),
}
}
/// Definitions for various easing functions
///
/// <div class="function-preview" data-function="t" data-struct="Linear"></div>
/// <div class="function-preview" data-function="Math.sin((t - 1) * Math.PI / 2) + 1" data-struct="EaseIn"></div>
/// <div class="function-preview" data-function="Math.sin(t * Math.PI / 2)" data-struct="EaseOut"></div>
/// <div class="function-preview" data-function=".5 * (1 - Math.cos(t * Math.PI))" data-struct="EaseInOut"></div>
pub mod functions;
use functions::*;
mod easing;
pub use easing::*;
#[cfg(feature = "alloc")]
mod keyframe;
#[cfg(feature = "alloc")]
pub use keyframe::*;
#[cfg(feature = "alloc")]
mod sequence;
#[cfg(feature = "alloc")]
pub use sequence::*;