Skip to content

Commit

Permalink
make sure EasingCurve has unit interval domain
Browse files Browse the repository at this point in the history
  • Loading branch information
RobWalt committed Sep 1, 2024
1 parent fcf5566 commit 772ca80
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
9 changes: 8 additions & 1 deletion crates/bevy_math/src/curve/easing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ where

#[inline]
fn sample_unchecked(&self, t: f32) -> T {
let domain = self.easing.domain();
let t = domain.start().lerp(domain.end(), t);
self.start.lerp(self.end, self.easing.sample_unchecked(t))
}
}
Expand All @@ -62,8 +64,13 @@ where
/// Create a new [`EasingCurve`] over the [unit interval] which transitions between a `start`
/// and an `end` value based on the provided [`Easing`] curve.
///
/// If the input curve's domain is not the unit interval, then the [`EasingCurve`] will ensure
/// that this invariant is guaranteed by internally [reparametrizing] the curve to the unit
/// interval.
///
/// [unit interval]: `Interval::UNIT`
pub fn new(start: T, end: T, easing: E) -> EasingCurve<T, E> {
/// [reparametrizing]: `Curve::reparametrize`
pub fn new(start: T, end: T, easing: E) -> Self {
Self { start, end, easing }
}
}
Expand Down
32 changes: 32 additions & 0 deletions crates/bevy_math/src/curve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,38 @@ mod tests {
});
}

#[test]
fn easing_curve_non_unit_domain() {
let start = Vec2::ZERO;
let end = Vec2::new(1.0, 2.0);

// even though the quadratic_ease_in input curve has the domain [0.0, 2.0], the easing
// curve correctly behaves as if its domain were [0.0, 1.0]
let curve = EasingCurve::new(
start,
end,
quadratic_ease_in().reparametrize(Interval::new(0.0, 2.0).unwrap(), |t| t / 2.0),
);

[
(-0.1, None),
(0.0, Some(start)),
(0.25, Some(Vec2::new(0.0625, 0.125))),
(0.5, Some(Vec2::new(0.25, 0.5))),
(1.0, Some(end)),
(1.1, None),
]
.into_iter()
.for_each(|(t, x)| {
let sample = curve.sample(t);
match (sample, x) {
(None, None) => assert_eq!(sample, x),
(Some(s), Some(x)) => assert!(s.abs_diff_eq(x, f32::EPSILON)),
_ => unreachable!(),
};
});
}

#[test]
fn mapping() {
let curve = function_curve(Interval::EVERYWHERE, |t| t * 3.0 + 1.0);
Expand Down

0 comments on commit 772ca80

Please sign in to comment.