use std::time::Duration;
use super::{AnimationTrack, Lerp};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(
serialize = "T: serde::Serialize",
deserialize = "T: serde::Deserialize<'de>",
))
)]
pub enum AnimatedValue<T: Lerp> {
Static(T),
Track(AnimationTrack<T>),
}
impl<T: Lerp> AnimatedValue<T> {
pub fn value_at(&self, t: Duration) -> T {
match self {
AnimatedValue::Static(v) => v.clone(),
AnimatedValue::Track(track) => track.value_at(t),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::animation::{Easing, Keyframe};
#[test]
fn animated_value_static_should_return_constant_at_any_time() {
let v: AnimatedValue<f64> = AnimatedValue::Static(42.0);
assert!(
(v.value_at(Duration::ZERO) - 42.0).abs() < f64::EPSILON,
"expected 42.0 at t=0"
);
assert!(
(v.value_at(Duration::from_secs(9999)) - 42.0).abs() < f64::EPSILON,
"expected 42.0 at t=9999s"
);
}
#[test]
fn animated_value_track_should_delegate_to_track() {
let track = AnimationTrack::new()
.push(Keyframe::new(Duration::ZERO, 0.0_f64, Easing::Linear))
.push(Keyframe::new(
Duration::from_secs(1),
1.0_f64,
Easing::Linear,
));
let v: AnimatedValue<f64> = AnimatedValue::Track(track);
let mid = v.value_at(Duration::from_millis(500));
assert!(
(mid - 0.5).abs() < 1e-9,
"expected 0.5 at midpoint, got {mid}"
);
}
}