use chrono::Duration;
use flo_curves::{bezier::Curve, BezierCurve};
use num_traits::Float;
use crate::vector::VectorND;
#[derive(Debug, Clone)]
pub struct MultiVariableAnimation<Prim, const STATES: usize>
where
Prim: Float + Into<f64>,
{
curve: Curve<VectorND<Prim, STATES>>,
duration: Duration,
}
impl<Prim, const STATES: usize> MultiVariableAnimation<Prim, STATES>
where
Prim: Float + Into<f64>,
{
pub fn new(
start: [Prim; STATES],
control_1: [Prim; STATES],
control_2: [Prim; STATES],
end: [Prim; STATES],
duration: Duration,
) -> Self {
Self {
curve: Curve {
start_point: VectorND(start),
end_point: VectorND(end),
control_points: (VectorND(control_1), VectorND(control_2)),
},
duration,
}
}
pub fn t_for_time(&self, time: Duration) -> f64 {
time.num_milliseconds() as f64 / self.duration.num_milliseconds() as f64
}
pub fn time_for_t(&self, t: f64) -> Duration {
Duration::milliseconds((t * self.duration.num_milliseconds() as f64) as i64)
}
pub fn sample(&self, time: Duration) -> [Prim; STATES] {
self.curve.point_at_pos(self.t_for_time(time)).into()
}
pub fn sample_at_t(&self, t: f64) -> [Prim; STATES] {
self.curve.point_at_pos(t).into()
}
pub fn time_for_output(&self, output: [Prim; STATES]) -> Option<Duration> {
self.curve
.t_for_point(&VectorND(output))
.map(|t| self.time_for_t(t))
}
pub fn start(&self) -> [Prim; STATES] {
self.curve.start_point.into()
}
pub fn end(&self) -> [Prim; STATES] {
self.curve.end_point.into()
}
pub fn control_points(&self) -> ([Prim; STATES], [Prim; STATES]) {
(
self.curve.control_points.0.into(),
self.curve.control_points.1.into(),
)
}
}