Skip to content

Commit 4357539

Browse files
authored
Add most common interpolations (#15675)
# Objective - Followup for #14788 - Support most usual ease function ## Solution - Use the crate [`interpolation`](https://docs.rs/interpolation/0.3.0/interpolation/trait.Ease.html) which has them all - it's already used by bevy_easings, bevy_tweening, be_tween, bevy_tweening_captured, bevy_enoki, kayak_ui in the Bevy ecosystem for various easing/tweening/interpolation
1 parent 0a150b0 commit 4357539

File tree

2 files changed

+131
-6
lines changed

2 files changed

+131
-6
lines changed

crates/bevy_math/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ rand = { version = "0.8", features = [
2121
], default-features = false, optional = true }
2222
rand_distr = { version = "0.4.3", optional = true }
2323
smallvec = { version = "1.11" }
24+
interpolation = "0.3"
2425

2526
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [
2627
"glam",

crates/bevy_math/src/curve/easing.rs

Lines changed: 130 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
ops::{self, FloatPow},
66
VectorSpace,
77
};
8+
use interpolation::Ease;
89

910
use super::{Curve, FunctionCurve, Interval};
1011

@@ -84,6 +85,51 @@ where
8485
}
8586

8687
impl EasingCurve<f32, FunctionCurve<f32, fn(f32) -> f32>> {
88+
/// A [`Curve`] mapping the [unit interval] to itself.
89+
///
90+
/// [unit interval]: `Interval::UNIT`
91+
pub fn ease(function: EaseFunction) -> Self {
92+
Self {
93+
start: 0.0,
94+
end: 1.0,
95+
easing: FunctionCurve::new(
96+
Interval::UNIT,
97+
match function {
98+
EaseFunction::QuadraticIn => Ease::quadratic_in,
99+
EaseFunction::QuadraticOut => Ease::quadratic_out,
100+
EaseFunction::QuadraticInOut => Ease::quadratic_in_out,
101+
EaseFunction::CubicIn => Ease::cubic_in,
102+
EaseFunction::CubicOut => Ease::cubic_out,
103+
EaseFunction::CubicInOut => Ease::cubic_in_out,
104+
EaseFunction::QuarticIn => Ease::quartic_in,
105+
EaseFunction::QuarticOut => Ease::quartic_out,
106+
EaseFunction::QuarticInOut => Ease::quartic_in_out,
107+
EaseFunction::QuinticIn => Ease::quintic_in,
108+
EaseFunction::QuinticOut => Ease::quintic_out,
109+
EaseFunction::QuinticInOut => Ease::quintic_in_out,
110+
EaseFunction::SineIn => Ease::sine_in,
111+
EaseFunction::SineOut => Ease::sine_out,
112+
EaseFunction::SineInOut => Ease::sine_in_out,
113+
EaseFunction::CircularIn => Ease::circular_in,
114+
EaseFunction::CircularOut => Ease::circular_out,
115+
EaseFunction::CircularInOut => Ease::circular_in_out,
116+
EaseFunction::ExponentialIn => Ease::exponential_in,
117+
EaseFunction::ExponentialOut => Ease::exponential_out,
118+
EaseFunction::ExponentialInOut => Ease::exponential_in_out,
119+
EaseFunction::ElasticIn => Ease::elastic_in,
120+
EaseFunction::ElasticOut => Ease::elastic_out,
121+
EaseFunction::ElasticInOut => Ease::elastic_in_out,
122+
EaseFunction::BackIn => Ease::back_in,
123+
EaseFunction::BackOut => Ease::back_out,
124+
EaseFunction::BackInOut => Ease::back_in_out,
125+
EaseFunction::BounceIn => Ease::bounce_in,
126+
EaseFunction::BounceOut => Ease::bounce_out,
127+
EaseFunction::BounceInOut => Ease::bounce_in_out,
128+
},
129+
),
130+
}
131+
}
132+
87133
/// A [`Curve`] mapping the [unit interval] to itself.
88134
///
89135
/// Quadratic easing functions can have exactly one critical point. This is a point on the function
@@ -92,7 +138,7 @@ impl EasingCurve<f32, FunctionCurve<f32, fn(f32) -> f32>> {
92138
///
93139
/// It uses the function `f(t) = t²`
94140
///
95-
/// [unit domain]: `Interval::UNIT`
141+
/// [unit interval]: `Interval::UNIT`
96142
/// [`t = 1`]: `Self::quadratic_ease_out`
97143
pub fn quadratic_ease_in() -> Self {
98144
Self {
@@ -110,7 +156,7 @@ impl EasingCurve<f32, FunctionCurve<f32, fn(f32) -> f32>> {
110156
///
111157
/// It uses the function `f(t) = 1 - (1 - t)²`
112158
///
113-
/// [unit domain]: `Interval::UNIT`
159+
/// [unit interval]: `Interval::UNIT`
114160
/// [`t = 0`]: `Self::quadratic_ease_in`
115161
pub fn quadratic_ease_out() -> Self {
116162
fn f(t: f32) -> f32 {
@@ -132,7 +178,7 @@ impl EasingCurve<f32, FunctionCurve<f32, fn(f32) -> f32>> {
132178
///
133179
/// It uses the function `f(t) = t² * (3 - 2t)`
134180
///
135-
/// [unit domain]: `Interval::UNIT`
181+
/// [unit interval]: `Interval::UNIT`
136182
/// [sigmoid function]: https://en.wikipedia.org/wiki/Sigmoid_function
137183
/// [smoothstep function]: https://en.wikipedia.org/wiki/Smoothstep
138184
pub fn smoothstep() -> Self {
@@ -150,7 +196,7 @@ impl EasingCurve<f32, FunctionCurve<f32, fn(f32) -> f32>> {
150196
///
151197
/// It uses the function `f(t) = t`
152198
///
153-
/// [unit domain]: `Interval::UNIT`
199+
/// [unit interval]: `Interval::UNIT`
154200
pub fn identity() -> Self {
155201
Self {
156202
start: 0.0,
@@ -219,7 +265,7 @@ where
219265
/// - for `n >= 2` the curve has a start segment and an end segment of length `1 / (2 * n)` and in
220266
/// between there are `n - 1` segments of length `1 / n`
221267
///
222-
/// [unit domain]: `Interval::UNIT`
268+
/// [unit interval]: `Interval::UNIT`
223269
/// [`constant_curve(Interval::UNIT, 0.0)`]: `crate::curve::constant_curve`
224270
#[derive(Clone, Debug)]
225271
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
@@ -265,7 +311,7 @@ impl StepCurve {
265311
///
266312
/// parametrized by `omega`
267313
///
268-
/// [unit domain]: `Interval::UNIT`
314+
/// [unit interval]: `Interval::UNIT`
269315
/// [smoothstep function]: https://en.wikipedia.org/wiki/Smoothstep
270316
/// [spring-mass-system]: https://notes.yvt.jp/Graphics/Easing-Functions/#elastic-easing
271317
#[derive(Clone, Debug)]
@@ -296,3 +342,81 @@ impl ElasticCurve {
296342
Self { omega }
297343
}
298344
}
345+
346+
/// Curve functions over the [unit interval], commonly used for easing transitions.
347+
///
348+
/// [unit interval]: `Interval::UNIT`
349+
#[derive(Debug, Copy, Clone, PartialEq)]
350+
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
351+
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
352+
pub enum EaseFunction {
353+
/// `f(t) = t²`
354+
QuadraticIn,
355+
/// `f(t) = -(t * (t - 2.0))`
356+
QuadraticOut,
357+
/// Behaves as `EaseFunction::QuadraticIn` for t < 0.5 and as `EaseFunction::QuadraticOut` for t >= 0.5
358+
QuadraticInOut,
359+
360+
/// `f(t) = t³`
361+
CubicIn,
362+
/// `f(t) = (t - 1.0)³ + 1.0`
363+
CubicOut,
364+
/// Behaves as `EaseFunction::CubicIn` for t < 0.5 and as `EaseFunction::CubicOut` for t >= 0.5
365+
CubicInOut,
366+
367+
/// `f(t) = t⁴`
368+
QuarticIn,
369+
/// `f(t) = (t - 1.0)³ * (1.0 - t) + 1.0`
370+
QuarticOut,
371+
/// Behaves as `EaseFunction::QuarticIn` for t < 0.5 and as `EaseFunction::QuarticOut` for t >= 0.5
372+
QuarticInOut,
373+
374+
/// `f(t) = t⁵`
375+
QuinticIn,
376+
/// `f(t) = (t - 1.0)⁵ + 1.0`
377+
QuinticOut,
378+
/// Behaves as `EaseFunction::QuinticIn` for t < 0.5 and as `EaseFunction::QuinticOut` for t >= 0.5
379+
QuinticInOut,
380+
381+
/// `f(t) = sin((t - 1.0) * π / 2.0) + 1.0`
382+
SineIn,
383+
/// `f(t) = sin(t * π / 2.0)`
384+
SineOut,
385+
/// Behaves as `EaseFunction::SineIn` for t < 0.5 and as `EaseFunction::SineOut` for t >= 0.5
386+
SineInOut,
387+
388+
/// `f(t) = 1.0 - sqrt(1.0 - t²)`
389+
CircularIn,
390+
/// `f(t) = sqrt((2.0 - t) * t)`
391+
CircularOut,
392+
/// Behaves as `EaseFunction::CircularIn` for t < 0.5 and as `EaseFunction::CircularOut` for t >= 0.5
393+
CircularInOut,
394+
395+
/// `f(t) = 2.0.powf(10.0 * (t - 1.0))`
396+
ExponentialIn,
397+
/// `f(t) = 1.0 - 2.0.powf(-10.0 * t)`
398+
ExponentialOut,
399+
/// Behaves as `EaseFunction::ExponentialIn` for t < 0.5 and as `EaseFunction::ExponentialOut` for t >= 0.5
400+
ExponentialInOut,
401+
402+
/// `f(t) = sin(13.0 * π / 2.0 * t) * 2.0.powf(10.0 * (t - 1.0))`
403+
ElasticIn,
404+
/// `f(t) = sin(-13.0 * π / 2.0 * (t + 1.0)) * 2.0.powf(-10.0 * t) + 1.0`
405+
ElasticOut,
406+
/// Behaves as `EaseFunction::ElasticIn` for t < 0.5 and as `EaseFunction::ElasticOut` for t >= 0.5
407+
ElasticInOut,
408+
409+
/// `f(t) = t³ - t * sin(t * π)`
410+
BackIn,
411+
/// `f(t) = 1.0 - (1.0 - t)³ - t * sin((1.0 - t) * π))`
412+
BackOut,
413+
/// Behaves as `EaseFunction::BackIn` for t < 0.5 and as `EaseFunction::BackOut` for t >= 0.5
414+
BackInOut,
415+
416+
/// bouncy at the start!
417+
BounceIn,
418+
/// bouncy at the end!
419+
BounceOut,
420+
/// Behaves as `EaseFunction::BounceIn` for t < 0.5 and as `EaseFunction::BounceOut` for t >= 0.5
421+
BounceInOut,
422+
}

0 commit comments

Comments
 (0)