Easing curves for tuples (#16945)

# Objective

Make it so that users can ease between tuples of easeable values. 

## Solution

Use `variadics_please`'s `all_tuples_enumerated` macro to generate code
that creates these trait implementations. For two elements, the result
looks like this:
```rust
impl<T0: Ease, T1: Ease> Ease for (T0, T1) {
    fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
        let curve_tuple = (
            <T0 as Ease>::interpolating_curve_unbounded(start.0, end.0),
            <T1 as Ease>::interpolating_curve_unbounded(start.1, end.1),
        );
        FunctionCurve::new(Interval::EVERYWHERE, move |t| {
            (
                curve_tuple.0.sample_unchecked(t),
                curve_tuple.1.sample_unchecked(t),
            )
        })
    }
}
```

## Testing

It compiles, and I futzed about with some manual examples, which seem to
work as expected.

---

## Showcase

Easing curves now support easing tuples of values that can themselves be
eased. For example:
```rust
// Easing between two `(Vec3, Quat)` values:
let easing_curve = EasingCurve::new(
    (vec3(0.0, 0.0, 0.0), Quat::from_rotation_z(-FRAC_PI_2)),
    (vec3(1.0, 1.0, 1.0), Quat::from_rotation_z(FRAC_PI_2)),
    EaseFunction::ExponentialInOut
);
```
This commit is contained in:
Matty Weatherley 2024-12-24 13:06:08 -05:00 committed by GitHub
parent a7ae0807ac
commit 43d5472fda
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -8,6 +8,8 @@ use crate::{
Curve, Dir2, Dir3, Dir3A, Quat, Rot2, VectorSpace,
};
use variadics_please::all_tuples_enumerated;
// TODO: Think about merging `Ease` with `StableInterpolate`
/// A type whose values can be eased between.
@ -72,6 +74,38 @@ impl Ease for Dir3A {
}
}
macro_rules! impl_ease_tuple {
($(#[$meta:meta])* $(($n:tt, $T:ident)),*) => {
$(#[$meta])*
impl<$($T: Ease),*> Ease for ($($T,)*) {
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
let curve_tuple =
(
$(
<$T as Ease>::interpolating_curve_unbounded(start.$n, end.$n),
)*
);
FunctionCurve::new(Interval::EVERYWHERE, move |t|
(
$(
curve_tuple.$n.sample_unchecked(t),
)*
)
)
}
}
};
}
all_tuples_enumerated!(
#[doc(fake_variadic)]
impl_ease_tuple,
1,
11,
T
);
/// A [`Curve`] that is defined by
///
/// - an initial `start` sample value at `t = 0`