1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
use crate::*;

use std::iter::FromIterator;

/// Category of animation sequence error
pub enum AnimationSequenceError {
	/// An attempt was made to insert a keyframe into the sequence when another keyframe already exists with the same start time
	TimeCollision(f64)
}

/// A collection of keyframes that can be played back in sequence
pub struct AnimationSequence<T: CanTween + Copy> where Keyframe<T>: Default {
	pub(crate) sequence: Vec<Keyframe<T>>,

	// Current item we're animating
	keyframe: Option<usize>,
	// Current time
	time: f64
} 

impl<T: CanTween + Copy> AnimationSequence<T> where Keyframe<T>: Default {
	/// Creates a new empty animation sequence
	#[inline]
	pub fn new() -> Self { 	
		AnimationSequence::<T> {
			sequence: Vec::new(),
			keyframe: None,

			time: 0.0
		}
	}

	fn update_current_keyframe(&mut self) {
		// Common cases, reversing/wrapping
		if self.sequence.len() > 0 && self.time == 0.0 {
			self.keyframe = Some(0);
			return;
		}
		if self.sequence.len() > 0 && self.time == self.duration() {
			self.keyframe = Some(self.sequence.len() - 1);
			return;
		}

		if let Some(k) = self.keyframe {
			if self.keyframes() <= k {
				self.keyframe = None;
			}

			if self.sequence[k].time() > self.time {
				for i in (0..self.keyframe.unwrap_or(0)).rev() {
					if self.sequence[i].time <= self.time { 
						self.keyframe = Some(i);
						return;
					}

					self.keyframe = None;
				}
			}
			else {
				let copy = self.keyframe;
				self.keyframe = None;	
							
				for i in copy.unwrap_or(0)..self.keyframes() {
					if self.sequence[i].time > self.time { break } else { self.keyframe = Some(i) }
				}
			}
		}
		else if self.keyframes() > 0 {
			self.keyframe = Some(0);
			self.update_current_keyframe();
		}
	}

	fn insert_into_vec(&mut self, keyframe: Keyframe<T>) -> Result<(), AnimationSequenceError> {
		if self.has_keyframe_at(keyframe.time()) { 
			Err(AnimationSequenceError::TimeCollision(keyframe.time()))
		}
		else {
			self.sequence.push(keyframe);
			Ok(())
		}
	}

	/// Inserts a new keyframe into the animation sequence
	pub fn insert(&mut self, keyframe: Keyframe<T>) -> Result<(), AnimationSequenceError> {
		if self.has_keyframe_at(keyframe.time()) { 
			Err(AnimationSequenceError::TimeCollision(keyframe.time()))
		}
		else {
			if keyframe.time() > self.sequence.last().unwrap_or(&Keyframe::default()).time() {
				self.sequence.insert(self.sequence.len(), keyframe);
			} 
			else if keyframe.time() < self.sequence.first().unwrap_or(&Keyframe::default()).time() {
				self.sequence.insert(0, keyframe);
			}
			else {
				self.sequence.push(keyframe);

				// Gives us the following guarantees:
				// * the item that comes next also has a later time
				// * the first item has the earliest time
				// * the last item has the last time (useful for remove_at)
				self.sequence.sort_unstable_by(|k, k2| k.time.partial_cmp(&k2.time).unwrap_or(std::cmp::Ordering::Equal));
			}

			self.update_current_keyframe();
			Ok(())
		}
	}

	/// Inserts several keyframes from an iterator all at once. 
	/// This is faster because sorting only needs to be done after all the keyframes have been inserted.
	pub fn insert_many(&mut self, keyframes: impl IntoIterator<Item = impl Into<Keyframe<T>>>) -> Result<(), AnimationSequenceError> {
		for k in keyframes { self.insert_into_vec(k.into())?; }
		self.sequence.sort_unstable_by(|k, k2| k.time.partial_cmp(&k2.time).unwrap_or(std::cmp::Ordering::Equal));
		self.update_current_keyframe();
		Ok(())
	}	

	/// Removes the keyframe from the sequence at the specified time. Returns true if a keyframe was actually removed
	pub fn remove(&mut self, timestamp: f64) -> bool { self.retain(|t| t != timestamp) }
	/// Removes all keyframes from this sequence
	pub fn clear(&mut self) { self.retain(|_| false); }

	/// Retains only the keyframes specified by the predicate. Works the same as `Vec::retain`.
	/// Returns true only if a keyframe was actually removed.
	pub fn retain<F: FnMut(f64) -> bool>(&mut self, mut f: F) -> bool {
		let old_len = self.keyframes();
		self.sequence.retain(|k| f(k.time()));

		if old_len != self.keyframes() {
			if self.time > self.duration() {
				self.time = self.duration();
			}
			self.update_current_keyframe();
			true
		}
		else { false }
	}

	/// If this sequence has a keyframe at the exact timestamp
	#[inline]
	pub fn has_keyframe_at(&self, timestamp: f64) -> bool { self.into_iter().any(|k| k.time() == timestamp) }

	/// The number of keyframes in this sequence
	#[inline]
	pub fn keyframes(&self) -> usize { self.sequence.len() }

	/// The current pair of keyframes that are being animated (current, next)
	/// 
	/// # Note
	/// 
	/// The following applies if:
	/// * There are no keyframes in this sequence: (`None`, `None`) is returned
	/// * The sequence has not reached the first keyframe: (`None`, current) is returned
	/// * There is only one keyframe in this sequence and the sequence has reached it: (current, `None`) is returned
	/// * The sequence has finished: (current, `None`) is returned
	pub fn pair(&self) -> (Option<&Keyframe<T>>, Option<&Keyframe<T>>) {
		match self.keyframe {
			Some(c) if c == self.sequence.len() - 1 => (Some(&self.sequence[c]), None), 
			Some(c) => (Some(&self.sequence[c]), Some(&self.sequence[c + 1])),
			None if self.sequence.len() > 0 => (None, Some(&self.sequence[0])),
			None => (None, None)
		}
	}

	/// The current value of this sequence
	pub fn now(&self) -> T {
		match self.pair() {
			(Some(s1), Some(s2)) => s1.tween_to(s2, self.time),
			(Some(s1), None) => s1.value(),
			(None, Some(s2)) => Keyframe::default().tween_to(s2, self.time),
			(None, None) => Keyframe::default().value()
		}
	}

	/// Advances this sequence by the duration specified.
	/// 
	/// Returns the remaining time (i.e. the amount that the specified duration went outside the bounds of the total duration of this sequence)
	/// after the operation has completed. 
	/// 
	/// A value over 0 indicates the sequence is at the finish point. 
	/// A value under 0 indicates this sequence is at the start point. 
	pub fn advance_by(&mut self, duration: f64) -> f64 {
		self.advance_to(self.time() + duration)
	}

	/// Advances this sequence by the duration specified.
	/// If the duration causes the sequence to go out of bounds it will reverse and return `true`. 
	pub fn advance_and_maybe_reverse(&mut self, duration: f64) -> bool {
		match self.advance_by(duration) {
			time if time == 0.0 => false,
			time => {
				self.reverse();
				if time < 0.0 {
					self.advance_to(self.duration());
				}
				self.advance_and_maybe_reverse(time);
				
				true
			}
		}
	}

	/// Advances this sequence by the duration specified.
	/// If the duration causes the sequence to go out of bounds it will wrap around and return `true`. 
	pub fn advance_and_maybe_wrap(&mut self, duration: f64) -> bool {
		match self.advance_by(duration) {
			time if time == 0.0 => false,
			time => {
				self.advance_to(if time < 0.0 { self.duration() } else { 0.0 });
				self.advance_and_maybe_wrap(time);
				
				true
			}
		}
	}

	/// Advances this sequence to the exact timestamp. 
	/// 
	/// Returns the remaining time (i.e. the amount that the specified timestamp went outside the bounds of the total duration of this sequence)
	/// after the operation has completed. 
	/// 
	/// A value over 0 indicates the sequence is at the finish point. 
	/// A value under 0 indicates this sequence is at the start point. 
	/// 
	/// # Note
	/// 
	/// The following applies if:
	/// * The timestamp is negative: the sequence is set to `0.0`
	/// * The timestamp is after the duration of the sequence: the sequence is set to `duration()`
	pub fn advance_to(&mut self, timestamp: f64) -> f64 {
		self.time = match timestamp {
			_ if timestamp < 0.0 => 0.0,
			_ if timestamp > self.duration() => self.duration(),
			_ => timestamp
		};

		self.update_current_keyframe();
		timestamp - self.time
	}

	/// The length in seconds of this sequence
	#[inline]
	pub fn duration(&self) -> f64 { 
		// Keyframe::default means that if we don't have any items in this collection (meaning - 1 is out of bounds) the maximum time will be 0.0
		self.sequence.get(self.sequence.len().saturating_sub(1)).unwrap_or(&Keyframe::default()).time 
	}

	/// The current progression of this sequence in seconds
	#[inline]
	pub fn time(&self) -> f64 { self.time }

	/// The current progression of this sequence as a percentage
	#[inline]
	pub fn progress(&self) -> f64 { 
		if self.duration() == 0.0 { 0.0 } else { self.time / self.duration() }
	}

	/// If this sequence has finished and is at the end. 
	/// It can be reset with `advance_to(0.0)`.
	#[inline]
	pub fn finished(&self) -> bool { self.time == self.duration() }

	/// Reverses the order of all keyframes in this sequence
	pub fn reverse(&mut self) {
		let max_time = self.duration();
		let mut reversed_vector = Vec::new();

		for i in (0..self.sequence.len()).rev() {
			let mut k = self.sequence.remove(i);
			k.time = max_time - k.time;
			reversed_vector.push(k);
		}

		self.sequence = reversed_vector;
		self.advance_to(0.0);
	}
}

impl<T: Float + CanTween + Copy> AnimationSequence<T> where Keyframe<T>: Default {
	/// Consumes this sequence and creates a normalized easing function which controls the 2D curve according to the keyframes in this sequence
	/// 
	/// # Note
	/// 
	/// This function is only implemented for one-dimensional float types, since each value corresponds to a Y position
	pub fn to_easing_function(self) -> Keyframes { Keyframes::from_easing_function(self) }
}

impl<T: CanTween + Copy> From<Vec<Keyframe<T>>> for AnimationSequence<T> where Keyframe<T>: Default {
	/// Creates a new animation sequence from a vector of keyframes
	fn from(vec: Vec<Keyframe<T>>) -> Self {
		let mut me = AnimationSequence::<T> {
			sequence: vec,
			keyframe: None,

			time: 0.0
		};

		me.sequence.sort_unstable_by(|k, k2| k.time.partial_cmp(&k2.time).unwrap_or(std::cmp::Ordering::Equal));
		me.sequence.dedup_by_key(|k| k.time());
		me.update_current_keyframe();

		me
	}
}

impl<T: CanTween + Copy> Default for AnimationSequence<T> where Keyframe<T>: Default {
	#[inline]
	fn default() -> Self { Self::new() }
}

impl<T: CanTween + Copy, I: Into<Keyframe<T>>> FromIterator<I> for AnimationSequence<T> where Keyframe<T>: Default {
	/// Creates a new animation sequence from an iterator
	fn from_iter<I2: IntoIterator<Item = I>>(iter: I2) -> Self {
		let mut me = Self::new();
		me.insert_many(iter).ok(); // Ignore errors, collisions will be discarded
		me
	}
}

impl<'a, T: CanTween + Copy> IntoIterator for &'a AnimationSequence<T> where Keyframe<T>: Default {
	type Item = &'a Keyframe<T>;
	type IntoIter = std::slice::Iter<'a, Keyframe<T>>;

	#[inline]
	fn into_iter(self) -> Self::IntoIter {
		self.sequence.as_slice().into_iter()
	}
}

/// Creates an animation sequence containing any arguments that can be made into keyframes
/// 
/// # Note
/// 
/// While this macro can be used with [`Keyframe::new`](struct.Keyframe.html#method.new) it's recommended to specify your keyframes with tuples (for shorter code) like this: 
/// ```ignore
/// keyframes![(0.0, 0.0), (0.5, 1.0), (1.0, 2.0), (1.5, 3.0, EaseOut), (2.0, 4.0)]
/// ```
#[macro_export]
macro_rules! keyframes {
	() => (AnimationSequence::default());
	($($k: expr),*) => {{
		let mut vec = Vec::new();
		$( vec.push($k.into()); )*
		AnimationSequence::from(vec)
	}};
}