use std::ops::{Add, Mul, Sub}; pub fn raw_lerp(a: T, b: T, t: f64) -> T where T: Copy + Add + Sub + Mul, { a + (b - a) * t } pub enum TimingFunction { Lerp, } pub struct KeyFrame { // We could make a TimeType generic (I initially did), however it's safe to assume we use a 64-bit float for this pub time: f64, pub val: ValueType, } impl KeyFrame { pub fn new(time: f64, val: ValueType) -> KeyFrame { KeyFrame { time, val } } } impl< ValueType: PartialOrd + Copy + Add + Sub + Mul, > KeyFrame { /** Simply passes the data to the timing function involved. Does not do bounding. */ pub fn raw_value_at( from: &KeyFrame, to: &KeyFrame, time: f64, timing_function: TimingFunction, ) -> ValueType { // Order them so `from` is always the lower bound let (from, to) = if from.time < to.time { (from, to) } else { (to, from) }; let length = to.time - from.time; let position = (time - from.time) / length; match timing_function { TimingFunction::Lerp => raw_lerp(from.val, to.val, position), } } }