naviz_animator/
timeline.rs

1//! A [Timeline] which contains multiple [Keyframe]s and allows interpolating between them.
2//!
3//! A [Keyframe]'s [value][Keyframe::value] will start at the [Keyframe]'s [time][Keyframe::time].
4//! It will then interpolate for the [Keyframe]'s specified [duration][Keyframe::duration],
5//! after which it will be held until the next [Keyframe].
6//! If a new [Keyframe] starts while another one would be interpolating,
7//! the new [Keyframe] will take precedence
8//! (which leads to a jump to the previous [Keyframe]'s [value][Keyframe::value]
9//! at the start of the new [Keyframe]).
10
11use ordered_float::OrderedFloat;
12
13use crate::interpolator::InterpolationFunction;
14
15pub type Time = OrderedFloat<f32>;
16
17// Something which can represent a duration
18pub trait Duration {
19    /// Convert this duration to [f32]
20    fn as_f32(&self) -> f32;
21}
22
23impl Duration for f32 {
24    fn as_f32(&self) -> f32 {
25        *self
26    }
27}
28
29impl Duration for () {
30    fn as_f32(&self) -> f32 {
31        0.
32    }
33}
34
35/// A single keyframe.
36///
37/// Keyframes are ordered only by their time.
38pub struct Keyframe<A, T, Dur: Duration> {
39    /// The start-time of this keyframe
40    pub time: Time,
41    /// The duration this keyframe will interpolate for
42    pub duration: Dur,
43    /// Additional data for the interpolator
44    pub argument: A,
45    /// The value this keyframe will interpolate to
46    pub value: T,
47}
48
49impl<A, T, Dur: Duration> Keyframe<A, T, Dur> {
50    /// The start-time of this keyframe
51    pub fn time(&self) -> &Time {
52        &self.time
53    }
54
55    /// The duration this keyframe will interpolate for
56    pub fn duration(&self) -> f32 {
57        self.duration.as_f32()
58    }
59
60    /// The value this keyframe will interpolate to
61    pub fn value(&self) -> &T {
62        &self.value
63    }
64
65    /// The argument of this keyframe (used for interpolation)
66    pub fn argument(&self) -> &A {
67        &self.argument
68    }
69}
70
71impl<A, T, Dur: Duration> PartialEq for Keyframe<A, T, Dur> {
72    fn eq(&self, other: &Self) -> bool {
73        self.time.eq(&other.time)
74    }
75}
76
77impl<A, T, Dur: Duration> Eq for Keyframe<A, T, Dur> {}
78
79impl<A, T, Dur: Duration> PartialOrd for Keyframe<A, T, Dur> {
80    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
81        Some(self.cmp(other))
82    }
83}
84
85impl<A, T, Dur: Duration> Ord for Keyframe<A, T, Dur> {
86    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
87        self.time.cmp(&other.time)
88    }
89}
90
91impl<T> From<(Time, T)> for Keyframe<(), T, ()> {
92    fn from((time, value): (Time, T)) -> Self {
93        Self {
94            time,
95            duration: (),
96            argument: (),
97            value,
98        }
99    }
100}
101
102impl<T> From<(f32, T)> for Keyframe<(), T, ()> {
103    fn from((time, value): (f32, T)) -> Self {
104        Self::from((OrderedFloat::from(time), value))
105    }
106}
107
108impl<T, Dur: Duration> From<(Time, Dur, T)> for Keyframe<(), T, Dur> {
109    fn from((time, duration, value): (Time, Dur, T)) -> Self {
110        Self {
111            time,
112            duration,
113            value,
114            argument: (),
115        }
116    }
117}
118
119impl<T, Dur: Duration> From<(f32, Dur, T)> for Keyframe<(), T, Dur> {
120    fn from((time, duration, value): (f32, Dur, T)) -> Self {
121        Self::from((OrderedFloat::from(time), duration, value))
122    }
123}
124
125impl<A, T, Dur: Duration> From<(Time, Dur, A, T)> for Keyframe<A, T, Dur> {
126    fn from((time, duration, argument, value): (Time, Dur, A, T)) -> Self {
127        Self {
128            time,
129            duration,
130            value,
131            argument,
132        }
133    }
134}
135
136impl<A, T, Dur: Duration> From<(f32, Dur, A, T)> for Keyframe<A, T, Dur> {
137    fn from((time, duration, argument, value): (f32, Dur, A, T)) -> Self {
138        Self::from((OrderedFloat::from(time), duration, argument, value))
139    }
140}
141
142/// A timeline which holds many keyframes and specifies the used interpolation function.
143pub struct Timeline<A: Copy, T: Copy, Dur: Duration, I: InterpolationFunction<A, T>> {
144    /// The keyframes of this functions.
145    /// This vector is expected to be ordered at any time.
146    keyframes: Vec<Keyframe<A, T, Dur>>,
147    /// The default value, which is valid from `-Inf` until the first keyframe
148    default: T,
149    /// The used interpolation function
150    interpolation_function: I,
151}
152
153impl<A: Copy, T: Copy + Default, Dur: Duration, I: InterpolationFunction<A, T> + Default> Default
154    for Timeline<A, T, Dur, I>
155{
156    fn default() -> Self {
157        Self {
158            keyframes: Vec::new(),
159            default: T::default(),
160            interpolation_function: Default::default(),
161        }
162    }
163}
164
165impl<A: Copy, T: Copy, Dur: Duration, I: InterpolationFunction<A, T> + Default>
166    Timeline<A, T, Dur, I>
167{
168    /// Creates a new [Timeline] with the passed `default`-value
169    /// and the default interpolation parameters
170    pub fn new(default: T) -> Self {
171        Self {
172            keyframes: Vec::new(),
173            default,
174            interpolation_function: Default::default(),
175        }
176    }
177}
178
179impl<A: Copy, T: Copy, Dur: Duration, I: InterpolationFunction<A, T>> Timeline<A, T, Dur, I> {
180    /// Creates a new [Timeline] with the passed `default`-value
181    /// and the specified interpolation parameters
182    pub fn new_with_interpolation(default: T, interpolation_function: I) -> Self {
183        Self {
184            keyframes: Vec::new(),
185            default,
186            interpolation_function,
187        }
188    }
189
190    /// Searches the keyframes for the index of the passed time.
191    /// See [slice::binary_search] for more information on the return type.
192    fn search_time(&self, time: Time) -> Result<usize, usize> {
193        self.keyframes.binary_search_by_key(&&time, Keyframe::time)
194    }
195
196    /// Gets the index where a keyframe with the passed time may be inserted
197    fn get_idx(&self, time: Time) -> usize {
198        match self.search_time(time) {
199            Ok(idx) => idx,
200            Err(idx) => idx,
201        }
202    }
203
204    /// Finds the index for the keyframe that is active during the passed time.
205    /// This does not take the keyframe's duration into account,
206    /// meaning that the keyframe may already be finished
207    /// (though no other keyframe would be active in that case).
208    fn find_idx(&self, time: Time) -> Option<usize> {
209        match self.search_time(time) {
210            Ok(idx) => Some(idx),
211            Err(idx) => {
212                if idx > 0 {
213                    Some(idx - 1)
214                } else {
215                    None
216                }
217            }
218        }
219    }
220
221    /// Gets the value at the passed time.
222    /// Will interpolate the keyframe.
223    pub fn get(&self, time: Time) -> T {
224        let idx = self.find_idx(time);
225        if let Some(idx) = idx {
226            let keyframe = &self.keyframes[idx];
227            let to = keyframe.value;
228            let from = idx
229                .checked_sub(1)
230                .map(|i| &self.keyframes[i])
231                .map(|k| I::ENDPOINT.get(self.default, k.value))
232                .unwrap_or(self.default);
233            let duration = keyframe.duration.as_f32().into();
234            let keyframe_relative_time = time - keyframe.time; // time inside keyframe
235            if keyframe_relative_time >= duration {
236                // outside of keyframe: return endpoint
237                return I::ENDPOINT.get(from, to);
238            }
239            let fraction = keyframe_relative_time / duration;
240            self.interpolation_function
241                .interpolate(fraction, keyframe.argument, from, to)
242        } else {
243            self.default
244        }
245    }
246
247    /// Adds a keyframe into this [Timeline]
248    pub fn add(&mut self, keyframe: impl Into<Keyframe<A, T, Dur>>) -> &mut Self {
249        let keyframe = keyframe.into();
250        self.keyframes.insert(self.get_idx(keyframe.time), keyframe);
251        self
252    }
253
254    /// Adds multiple keyframes into this [Timeline]
255    pub fn add_all(
256        &mut self,
257        keyframes: impl IntoIterator<Item = impl Into<Keyframe<A, T, Dur>>>,
258    ) -> &mut Self {
259        self.keyframes.extend(keyframes.into_iter().map(Into::into));
260        self.keyframes.sort();
261        self
262    }
263}