1use crate::{
2 macros::{impl_animated_data_insert, impl_data_type_ops, impl_sample_for_animated_data},
3 time_data_map::TimeDataMapControl,
4 *,
5};
6use anyhow::Result;
7use core::num::NonZeroU16;
8use enum_dispatch::enum_dispatch;
9use smallvec::SmallVec;
10use std::hash::Hasher;
11
12#[enum_dispatch(AnimatedDataOps)]
18#[derive(Debug, Clone, PartialEq, Eq)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20pub enum AnimatedData {
21 Boolean(TimeDataMap<Boolean>),
23 Integer(TimeDataMap<Integer>),
25 Real(TimeDataMap<Real>),
27 String(TimeDataMap<String>),
29 Color(TimeDataMap<Color>),
31 #[cfg(feature = "vector2")]
33 Vector2(TimeDataMap<Vector2>),
34 #[cfg(feature = "vector3")]
36 Vector3(TimeDataMap<Vector3>),
37 #[cfg(feature = "matrix3")]
39 Matrix3(TimeDataMap<Matrix3>),
40 #[cfg(feature = "normal3")]
42 Normal3(TimeDataMap<Normal3>),
43 #[cfg(feature = "point3")]
45 Point3(TimeDataMap<Point3>),
46 #[cfg(feature = "matrix4")]
48 Matrix4(TimeDataMap<Matrix4>),
49 BooleanVec(TimeDataMap<BooleanVec>),
51 IntegerVec(TimeDataMap<IntegerVec>),
53 RealVec(TimeDataMap<RealVec>),
55 ColorVec(TimeDataMap<ColorVec>),
57 StringVec(TimeDataMap<StringVec>),
59 #[cfg(all(feature = "vector2", feature = "vec_variants"))]
61 Vector2Vec(TimeDataMap<Vector2Vec>),
62 #[cfg(all(feature = "vector3", feature = "vec_variants"))]
64 Vector3Vec(TimeDataMap<Vector3Vec>),
65 #[cfg(all(feature = "matrix3", feature = "vec_variants"))]
67 Matrix3Vec(TimeDataMap<Matrix3Vec>),
68 #[cfg(all(feature = "normal3", feature = "vec_variants"))]
70 Normal3Vec(TimeDataMap<Normal3Vec>),
71 #[cfg(all(feature = "point3", feature = "vec_variants"))]
73 Point3Vec(TimeDataMap<Point3Vec>),
74 #[cfg(all(feature = "matrix4", feature = "vec_variants"))]
76 Matrix4Vec(TimeDataMap<Matrix4Vec>),
77}
78
79#[enum_dispatch]
81pub trait AnimatedDataOps {
82 fn len(&self) -> usize;
84 fn is_empty(&self) -> bool;
86 fn is_animated(&self) -> bool;
88}
89
90impl<T> AnimatedDataOps for TimeDataMap<T> {
91 fn len(&self) -> usize {
92 self.values.len()
93 }
94
95 fn is_empty(&self) -> bool {
96 self.values.is_empty()
97 }
98
99 fn is_animated(&self) -> bool {
100 self.values.len() > 1
101 }
102}
103
104impl_data_type_ops!(AnimatedData);
105
106impl AnimatedData {
107 pub fn times(&self) -> SmallVec<[Time; 10]> {
109 match self {
110 AnimatedData::Boolean(map) => map.iter().map(|(t, _)| *t).collect(),
111 AnimatedData::Integer(map) => map.iter().map(|(t, _)| *t).collect(),
112 AnimatedData::Real(map) => map.iter().map(|(t, _)| *t).collect(),
113 AnimatedData::String(map) => map.iter().map(|(t, _)| *t).collect(),
114 AnimatedData::Color(map) => map.iter().map(|(t, _)| *t).collect(),
115 #[cfg(feature = "vector2")]
116 AnimatedData::Vector2(map) => map.iter().map(|(t, _)| *t).collect(),
117 #[cfg(feature = "vector3")]
118 AnimatedData::Vector3(map) => map.iter().map(|(t, _)| *t).collect(),
119 #[cfg(feature = "matrix3")]
120 AnimatedData::Matrix3(map) => map.iter().map(|(t, _)| *t).collect(),
121 #[cfg(feature = "normal3")]
122 AnimatedData::Normal3(map) => map.iter().map(|(t, _)| *t).collect(),
123 #[cfg(feature = "point3")]
124 AnimatedData::Point3(map) => map.iter().map(|(t, _)| *t).collect(),
125 #[cfg(feature = "matrix4")]
126 AnimatedData::Matrix4(map) => map.iter().map(|(t, _)| *t).collect(),
127 AnimatedData::BooleanVec(map) => map.iter().map(|(t, _)| *t).collect(),
128 AnimatedData::IntegerVec(map) => map.iter().map(|(t, _)| *t).collect(),
129 AnimatedData::RealVec(map) => map.iter().map(|(t, _)| *t).collect(),
130 AnimatedData::ColorVec(map) => map.iter().map(|(t, _)| *t).collect(),
131 AnimatedData::StringVec(map) => map.iter().map(|(t, _)| *t).collect(),
132 #[cfg(all(feature = "vector2", feature = "vec_variants"))]
133 AnimatedData::Vector2Vec(map) => map.iter().map(|(t, _)| *t).collect(),
134 #[cfg(all(feature = "vector3", feature = "vec_variants"))]
135 AnimatedData::Vector3Vec(map) => map.iter().map(|(t, _)| *t).collect(),
136 #[cfg(all(feature = "matrix3", feature = "vec_variants"))]
137 AnimatedData::Matrix3Vec(map) => map.iter().map(|(t, _)| *t).collect(),
138 #[cfg(all(feature = "normal3", feature = "vec_variants"))]
139 AnimatedData::Normal3Vec(map) => map.iter().map(|(t, _)| *t).collect(),
140 #[cfg(all(feature = "point3", feature = "vec_variants"))]
141 AnimatedData::Point3Vec(map) => map.iter().map(|(t, _)| *t).collect(),
142 #[cfg(all(feature = "matrix4", feature = "vec_variants"))]
143 AnimatedData::Matrix4Vec(map) => map.iter().map(|(t, _)| *t).collect(),
144 }
145 }
146}
147
148impl From<(Time, Value)> for AnimatedData {
149 fn from((time, value): (Time, Value)) -> Self {
150 match value {
151 Value::Uniform(data) => AnimatedData::from((time, data)),
152 Value::Animated(animated_data) => {
153 animated_data
158 }
159 }
160 }
161}
162
163impl From<(Time, Data)> for AnimatedData {
164 fn from((time, data): (Time, Data)) -> Self {
165 match data {
166 Data::Boolean(v) => AnimatedData::Boolean(TimeDataMap::from((time, v))),
167 Data::Integer(v) => AnimatedData::Integer(TimeDataMap::from((time, v))),
168 Data::Real(v) => AnimatedData::Real(TimeDataMap::from((time, v))),
169 Data::String(v) => AnimatedData::String(TimeDataMap::from((time, v))),
170 Data::Color(v) => AnimatedData::Color(TimeDataMap::from((time, v))),
171 #[cfg(feature = "vector2")]
172 Data::Vector2(v) => AnimatedData::Vector2(TimeDataMap::from((time, v))),
173 #[cfg(feature = "vector3")]
174 Data::Vector3(v) => AnimatedData::Vector3(TimeDataMap::from((time, v))),
175 #[cfg(feature = "matrix3")]
176 Data::Matrix3(v) => AnimatedData::Matrix3(TimeDataMap::from((time, v))),
177 #[cfg(feature = "normal3")]
178 Data::Normal3(v) => AnimatedData::Normal3(TimeDataMap::from((time, v))),
179 #[cfg(feature = "point3")]
180 Data::Point3(v) => AnimatedData::Point3(TimeDataMap::from((time, v))),
181 #[cfg(feature = "matrix4")]
182 Data::Matrix4(v) => AnimatedData::Matrix4(TimeDataMap::from((time, v))),
183 Data::BooleanVec(v) => AnimatedData::BooleanVec(TimeDataMap::from((time, v))),
184 Data::IntegerVec(v) => AnimatedData::IntegerVec(TimeDataMap::from((time, v))),
185 Data::RealVec(v) => AnimatedData::RealVec(TimeDataMap::from((time, v))),
186 Data::ColorVec(v) => AnimatedData::ColorVec(TimeDataMap::from((time, v))),
187 Data::StringVec(v) => AnimatedData::StringVec(TimeDataMap::from((time, v))),
188 #[cfg(all(feature = "vector2", feature = "vec_variants"))]
189 Data::Vector2Vec(v) => AnimatedData::Vector2Vec(TimeDataMap::from((time, v))),
190 #[cfg(all(feature = "vector3", feature = "vec_variants"))]
191 Data::Vector3Vec(v) => AnimatedData::Vector3Vec(TimeDataMap::from((time, v))),
192 #[cfg(all(feature = "matrix3", feature = "vec_variants"))]
193 Data::Matrix3Vec(v) => AnimatedData::Matrix3Vec(TimeDataMap::from((time, v))),
194 #[cfg(all(feature = "normal3", feature = "vec_variants"))]
195 Data::Normal3Vec(v) => AnimatedData::Normal3Vec(TimeDataMap::from((time, v))),
196 #[cfg(all(feature = "point3", feature = "vec_variants"))]
197 Data::Point3Vec(v) => AnimatedData::Point3Vec(TimeDataMap::from((time, v))),
198 #[cfg(all(feature = "matrix4", feature = "vec_variants"))]
199 Data::Matrix4Vec(v) => AnimatedData::Matrix4Vec(TimeDataMap::from((time, v))),
200 }
201 }
202}
203
204impl_animated_data_insert!(
205 insert_boolean, Boolean, Boolean;
206 insert_integer, Integer, Integer;
207 insert_real, Real, Real;
208 insert_string, String, String;
209 insert_color, Color, Color;
210);
211
212#[cfg(feature = "vector2")]
213impl_animated_data_insert!(
214 insert_vector2, Vector2, Vector2;
215);
216
217#[cfg(feature = "vector3")]
218impl_animated_data_insert!(
219 insert_vector3, Vector3, Vector3;
220);
221
222#[cfg(feature = "matrix3")]
223impl_animated_data_insert!(
224 insert_matrix3, Matrix3, Matrix3;
225);
226
227#[cfg(feature = "normal3")]
228impl_animated_data_insert!(
229 insert_normal3, Normal3, Normal3;
230);
231
232#[cfg(feature = "point3")]
233impl_animated_data_insert!(
234 insert_point3, Point3, Point3;
235);
236
237#[cfg(feature = "matrix4")]
238impl_animated_data_insert!(
239 insert_matrix4, Matrix4, Matrix4;
240);
241
242impl AnimatedData {
243 #[named]
246 pub fn try_insert(&mut self, time: Time, value: Data) -> Result<()> {
247 match (self, value) {
248 (AnimatedData::Boolean(map), Data::Boolean(v)) => {
249 map.insert(time, v);
250 Ok(())
251 }
252 (AnimatedData::Integer(map), Data::Integer(v)) => {
253 map.insert(time, v);
254 Ok(())
255 }
256 (AnimatedData::Real(map), Data::Real(v)) => {
257 map.insert(time, v);
258 Ok(())
259 }
260 (AnimatedData::String(map), Data::String(v)) => {
261 map.insert(time, v);
262 Ok(())
263 }
264 (AnimatedData::Color(map), Data::Color(v)) => {
265 map.insert(time, v);
266 Ok(())
267 }
268 #[cfg(feature = "vector2")]
269 (AnimatedData::Vector2(map), Data::Vector2(v)) => {
270 map.insert(time, v);
271 Ok(())
272 }
273 #[cfg(feature = "vector3")]
274 (AnimatedData::Vector3(map), Data::Vector3(v)) => {
275 map.insert(time, v);
276 Ok(())
277 }
278 #[cfg(feature = "matrix3")]
279 (AnimatedData::Matrix3(map), Data::Matrix3(v)) => {
280 map.insert(time, v);
281 Ok(())
282 }
283 #[cfg(feature = "normal3")]
284 (AnimatedData::Normal3(map), Data::Normal3(v)) => {
285 map.insert(time, v);
286 Ok(())
287 }
288 #[cfg(feature = "point3")]
289 (AnimatedData::Point3(map), Data::Point3(v)) => {
290 map.insert(time, v);
291 Ok(())
292 }
293 #[cfg(feature = "matrix4")]
294 (AnimatedData::Matrix4(map), Data::Matrix4(v)) => {
295 map.insert(time, v);
296 Ok(())
297 }
298 (AnimatedData::BooleanVec(map), Data::BooleanVec(v)) => {
299 map.insert(time, v);
300 Ok(())
301 }
302 (AnimatedData::IntegerVec(map), Data::IntegerVec(v)) => {
303 map.insert(time, v);
304 Ok(())
305 }
306 (AnimatedData::RealVec(map), Data::RealVec(v)) => {
307 map.insert(time, v);
308 Ok(())
309 }
310 (AnimatedData::ColorVec(map), Data::ColorVec(v)) => {
311 map.insert(time, v);
312 Ok(())
313 }
314 (AnimatedData::StringVec(map), Data::StringVec(v)) => {
315 map.insert(time, v);
316 Ok(())
317 }
318 #[cfg(all(feature = "vector2", feature = "vec_variants"))]
319 (AnimatedData::Vector2Vec(map), Data::Vector2Vec(v)) => {
320 map.insert(time, v);
321 Ok(())
322 }
323 #[cfg(all(feature = "vector3", feature = "vec_variants"))]
324 (AnimatedData::Vector3Vec(map), Data::Vector3Vec(v)) => {
325 map.insert(time, v);
326 Ok(())
327 }
328 #[cfg(all(feature = "matrix3", feature = "vec_variants"))]
329 (AnimatedData::Matrix3Vec(map), Data::Matrix3Vec(v)) => {
330 map.insert(time, v);
331 Ok(())
332 }
333 #[cfg(all(feature = "normal3", feature = "vec_variants"))]
334 (AnimatedData::Normal3Vec(map), Data::Normal3Vec(v)) => {
335 map.insert(time, v);
336 Ok(())
337 }
338 #[cfg(all(feature = "point3", feature = "vec_variants"))]
339 (AnimatedData::Point3Vec(map), Data::Point3Vec(v)) => {
340 map.insert(time, v);
341 Ok(())
342 }
343 #[cfg(all(feature = "matrix4", feature = "vec_variants"))]
344 (AnimatedData::Matrix4Vec(map), Data::Matrix4Vec(v)) => {
345 map.insert(time, v);
346 Ok(())
347 }
348 (s, v) => Err(anyhow!(
349 "{}: type mismatch: {:?} variant does not match {:?} type",
350 function_name!(),
351 s.data_type(),
352 v.data_type()
353 )),
354 }
355 }
356
357 pub fn sample_at(&self, time: Time) -> Option<Data> {
358 match self {
359 AnimatedData::Boolean(map) => map.get(&time).map(|v| Data::Boolean(v.clone())),
360 AnimatedData::Integer(map) => map.get(&time).map(|v| Data::Integer(v.clone())),
361 AnimatedData::Real(map) => map.get(&time).map(|v| Data::Real(v.clone())),
362 AnimatedData::String(map) => map.get(&time).map(|v| Data::String(v.clone())),
363 AnimatedData::Color(map) => map.get(&time).map(|v| Data::Color(v.clone())),
364 #[cfg(feature = "vector2")]
365 AnimatedData::Vector2(map) => map.get(&time).map(|v| Data::Vector2(v.clone())),
366 #[cfg(feature = "vector3")]
367 AnimatedData::Vector3(map) => map.get(&time).map(|v| Data::Vector3(v.clone())),
368 #[cfg(feature = "matrix3")]
369 AnimatedData::Matrix3(map) => map.get(&time).map(|v| Data::Matrix3(v.clone())),
370 #[cfg(feature = "normal3")]
371 AnimatedData::Normal3(map) => map.get(&time).map(|v| Data::Normal3(v.clone())),
372 #[cfg(feature = "point3")]
373 AnimatedData::Point3(map) => map.get(&time).map(|v| Data::Point3(v.clone())),
374 #[cfg(feature = "matrix4")]
375 AnimatedData::Matrix4(map) => map.get(&time).map(|v| Data::Matrix4(v.clone())),
376 AnimatedData::BooleanVec(map) => map.get(&time).map(|v| Data::BooleanVec(v.clone())),
377 AnimatedData::IntegerVec(map) => map.get(&time).map(|v| Data::IntegerVec(v.clone())),
378 AnimatedData::RealVec(map) => map.get(&time).map(|v| Data::RealVec(v.clone())),
379 AnimatedData::ColorVec(map) => map.get(&time).map(|v| Data::ColorVec(v.clone())),
380 AnimatedData::StringVec(map) => map.get(&time).map(|v| Data::StringVec(v.clone())),
381 #[cfg(all(feature = "vector2", feature = "vec_variants"))]
382 AnimatedData::Vector2Vec(map) => map.get(&time).map(|v| Data::Vector2Vec(v.clone())),
383 #[cfg(all(feature = "vector3", feature = "vec_variants"))]
384 AnimatedData::Vector3Vec(map) => map.get(&time).map(|v| Data::Vector3Vec(v.clone())),
385 #[cfg(all(feature = "matrix3", feature = "vec_variants"))]
386 AnimatedData::Matrix3Vec(map) => map.get(&time).map(|v| Data::Matrix3Vec(v.clone())),
387 #[cfg(all(feature = "normal3", feature = "vec_variants"))]
388 AnimatedData::Normal3Vec(map) => map.get(&time).map(|v| Data::Normal3Vec(v.clone())),
389 #[cfg(all(feature = "point3", feature = "vec_variants"))]
390 AnimatedData::Point3Vec(map) => map.get(&time).map(|v| Data::Point3Vec(v.clone())),
391 #[cfg(all(feature = "matrix4", feature = "vec_variants"))]
392 AnimatedData::Matrix4Vec(map) => map.get(&time).map(|v| Data::Matrix4Vec(v.clone())),
393 }
394 }
395
396 pub fn interpolate(&self, time: Time) -> Data {
397 match self {
398 AnimatedData::Boolean(map) => Data::Boolean(map.closest_sample(time).clone()),
399 AnimatedData::Integer(map) => {
400 if TimeDataMapControl::is_animated(map) {
401 Data::Integer(map.interpolate(time))
402 } else {
403 Data::Integer(map.iter().next().unwrap().1.clone())
404 }
405 }
406 AnimatedData::Real(map) => {
407 if TimeDataMapControl::is_animated(map) {
408 Data::Real(map.interpolate(time))
409 } else {
410 Data::Real(map.iter().next().unwrap().1.clone())
411 }
412 }
413 AnimatedData::String(map) => Data::String(map.closest_sample(time).clone()),
414 AnimatedData::Color(map) => {
415 if TimeDataMapControl::is_animated(map) {
416 Data::Color(map.interpolate(time))
417 } else {
418 Data::Color(map.iter().next().unwrap().1.clone())
419 }
420 }
421 #[cfg(feature = "vector2")]
422 AnimatedData::Vector2(map) => {
423 if TimeDataMapControl::is_animated(map) {
424 Data::Vector2(map.interpolate(time))
425 } else {
426 Data::Vector2(map.iter().next().unwrap().1.clone())
427 }
428 }
429 #[cfg(feature = "vector3")]
430 AnimatedData::Vector3(map) => {
431 if TimeDataMapControl::is_animated(map) {
432 Data::Vector3(map.interpolate(time))
433 } else {
434 Data::Vector3(map.iter().next().unwrap().1.clone())
435 }
436 }
437 #[cfg(feature = "matrix3")]
438 AnimatedData::Matrix3(map) => {
439 if TimeDataMapControl::is_animated(map) {
440 Data::Matrix3(map.interpolate(time))
441 } else {
442 Data::Matrix3(map.iter().next().unwrap().1.clone())
443 }
444 }
445 #[cfg(feature = "normal3")]
446 AnimatedData::Normal3(map) => {
447 if TimeDataMapControl::is_animated(map) {
448 Data::Normal3(map.interpolate(time))
449 } else {
450 Data::Normal3(map.iter().next().unwrap().1.clone())
451 }
452 }
453 #[cfg(feature = "point3")]
454 AnimatedData::Point3(map) => {
455 if TimeDataMapControl::is_animated(map) {
456 Data::Point3(map.interpolate(time))
457 } else {
458 Data::Point3(map.iter().next().unwrap().1.clone())
459 }
460 }
461 #[cfg(feature = "matrix4")]
462 AnimatedData::Matrix4(map) => {
463 if TimeDataMapControl::is_animated(map) {
464 Data::Matrix4(map.interpolate(time))
465 } else {
466 Data::Matrix4(map.iter().next().unwrap().1.clone())
467 }
468 }
469 AnimatedData::BooleanVec(map) => Data::BooleanVec(map.closest_sample(time).clone()),
470 AnimatedData::IntegerVec(map) => {
471 if TimeDataMapControl::is_animated(map) {
472 Data::IntegerVec(map.interpolate(time))
473 } else {
474 Data::IntegerVec(map.iter().next().unwrap().1.clone())
475 }
476 }
477 AnimatedData::RealVec(map) => {
478 if TimeDataMapControl::is_animated(map) {
479 Data::RealVec(map.interpolate(time))
480 } else {
481 Data::RealVec(map.iter().next().unwrap().1.clone())
482 }
483 }
484 AnimatedData::ColorVec(map) => {
485 if TimeDataMapControl::is_animated(map) {
486 Data::ColorVec(map.interpolate(time))
487 } else {
488 Data::ColorVec(map.iter().next().unwrap().1.clone())
489 }
490 }
491 AnimatedData::StringVec(map) => Data::StringVec(map.closest_sample(time).clone()),
492 #[cfg(all(feature = "vector2", feature = "vec_variants"))]
493 AnimatedData::Vector2Vec(map) => {
494 if TimeDataMapControl::is_animated(map) {
495 Data::Vector2Vec(map.interpolate(time))
496 } else {
497 Data::Vector2Vec(map.iter().next().unwrap().1.clone())
498 }
499 }
500 #[cfg(all(feature = "vector3", feature = "vec_variants"))]
501 AnimatedData::Vector3Vec(map) => {
502 if TimeDataMapControl::is_animated(map) {
503 Data::Vector3Vec(map.interpolate(time))
504 } else {
505 Data::Vector3Vec(map.iter().next().unwrap().1.clone())
506 }
507 }
508 #[cfg(all(feature = "matrix3", feature = "vec_variants"))]
509 AnimatedData::Matrix3Vec(map) => {
510 if TimeDataMapControl::is_animated(map) {
511 Data::Matrix3Vec(map.interpolate(time))
512 } else {
513 Data::Matrix3Vec(map.iter().next().unwrap().1.clone())
514 }
515 }
516 #[cfg(all(feature = "normal3", feature = "vec_variants"))]
517 AnimatedData::Normal3Vec(map) => {
518 if TimeDataMapControl::is_animated(map) {
519 Data::Normal3Vec(map.interpolate(time))
520 } else {
521 Data::Normal3Vec(map.iter().next().unwrap().1.clone())
522 }
523 }
524 #[cfg(all(feature = "point3", feature = "vec_variants"))]
525 AnimatedData::Point3Vec(map) => {
526 if TimeDataMapControl::is_animated(map) {
527 Data::Point3Vec(map.interpolate(time))
528 } else {
529 Data::Point3Vec(map.iter().next().unwrap().1.clone())
530 }
531 }
532 #[cfg(all(feature = "matrix4", feature = "vec_variants"))]
533 AnimatedData::Matrix4Vec(map) => {
534 if TimeDataMapControl::is_animated(map) {
535 Data::Matrix4Vec(map.interpolate(time))
536 } else {
537 Data::Matrix4Vec(map.iter().next().unwrap().1.clone())
538 }
539 }
540 }
541 }
542}
543
544impl Hash for AnimatedData {
545 fn hash<H: Hasher>(&self, state: &mut H) {
546 std::mem::discriminant(self).hash(state);
547 match self {
548 AnimatedData::Boolean(map) => {
549 map.len().hash(state);
550 #[cfg(not(feature = "interpolation"))]
551 for (time, value) in &map.values {
552 time.hash(state);
553 value.0.hash(state);
554 }
555 #[cfg(feature = "interpolation")]
556 for (time, (value, spec)) in &map.values {
557 time.hash(state);
558 value.0.hash(state);
559 spec.hash(state);
560 }
561 }
562 AnimatedData::Integer(map) => {
563 map.len().hash(state);
564 #[cfg(not(feature = "interpolation"))]
565 for (time, value) in &map.values {
566 time.hash(state);
567 value.0.hash(state);
568 }
569 #[cfg(feature = "interpolation")]
570 for (time, (value, spec)) in &map.values {
571 time.hash(state);
572 value.0.hash(state);
573 spec.hash(state);
574 }
575 }
576 AnimatedData::Real(map) => {
577 map.len().hash(state);
578 #[cfg(not(feature = "interpolation"))]
579 for (time, value) in &map.values {
580 time.hash(state);
581 value.0.to_bits().hash(state);
582 }
583 #[cfg(feature = "interpolation")]
584 for (time, (value, spec)) in &map.values {
585 time.hash(state);
586 value.0.to_bits().hash(state);
587 spec.hash(state);
588 }
589 }
590 AnimatedData::String(map) => {
591 map.len().hash(state);
592 #[cfg(not(feature = "interpolation"))]
593 for (time, value) in &map.values {
594 time.hash(state);
595 value.0.hash(state);
596 }
597 #[cfg(feature = "interpolation")]
598 for (time, (value, spec)) in &map.values {
599 time.hash(state);
600 value.0.hash(state);
601 spec.hash(state);
602 }
603 }
604 AnimatedData::Color(map) => {
605 map.len().hash(state);
606 #[cfg(not(feature = "interpolation"))]
607 for (time, value) in &map.values {
608 time.hash(state);
609 value.0.iter().for_each(|v| v.to_bits().hash(state));
610 }
611 #[cfg(feature = "interpolation")]
612 for (time, (value, spec)) in &map.values {
613 time.hash(state);
614 value.0.iter().for_each(|v| v.to_bits().hash(state));
615 spec.hash(state);
616 }
617 }
618 #[cfg(feature = "vector2")]
619 AnimatedData::Vector2(map) => {
620 map.len().hash(state);
621 #[cfg(not(feature = "interpolation"))]
622 for (time, value) in &map.values {
623 time.hash(state);
624 value.0.iter().for_each(|v| v.to_bits().hash(state));
625 }
626 #[cfg(feature = "interpolation")]
627 for (time, (value, spec)) in &map.values {
628 time.hash(state);
629 value.0.iter().for_each(|v| v.to_bits().hash(state));
630 spec.hash(state);
631 }
632 }
633 #[cfg(feature = "vector3")]
634 AnimatedData::Vector3(map) => {
635 map.len().hash(state);
636 #[cfg(not(feature = "interpolation"))]
637 for (time, value) in &map.values {
638 time.hash(state);
639 value.0.iter().for_each(|v| v.to_bits().hash(state));
640 }
641 #[cfg(feature = "interpolation")]
642 for (time, (value, spec)) in &map.values {
643 time.hash(state);
644 value.0.iter().for_each(|v| v.to_bits().hash(state));
645 spec.hash(state);
646 }
647 }
648 #[cfg(feature = "matrix3")]
649 AnimatedData::Matrix3(map) => {
650 map.len().hash(state);
651 #[cfg(not(feature = "interpolation"))]
652 for (time, value) in &map.values {
653 time.hash(state);
654 value.0.iter().for_each(|v| v.to_bits().hash(state));
655 }
656 #[cfg(feature = "interpolation")]
657 for (time, (value, spec)) in &map.values {
658 time.hash(state);
659 value.0.iter().for_each(|v| v.to_bits().hash(state));
660 spec.hash(state);
661 }
662 }
663 #[cfg(feature = "normal3")]
664 AnimatedData::Normal3(map) => {
665 map.len().hash(state);
666 #[cfg(not(feature = "interpolation"))]
667 for (time, value) in &map.values {
668 time.hash(state);
669 value.0.iter().for_each(|v| v.to_bits().hash(state));
670 }
671 #[cfg(feature = "interpolation")]
672 for (time, (value, spec)) in &map.values {
673 time.hash(state);
674 value.0.iter().for_each(|v| v.to_bits().hash(state));
675 spec.hash(state);
676 }
677 }
678 #[cfg(feature = "point3")]
679 AnimatedData::Point3(map) => {
680 map.len().hash(state);
681 #[cfg(not(feature = "interpolation"))]
682 for (time, value) in &map.values {
683 time.hash(state);
684 value.0.coords.iter().for_each(|v| v.to_bits().hash(state));
685 }
686 #[cfg(feature = "interpolation")]
687 for (time, (value, spec)) in &map.values {
688 time.hash(state);
689 value.0.coords.iter().for_each(|v| v.to_bits().hash(state));
690 spec.hash(state);
691 }
692 }
693 #[cfg(feature = "matrix4")]
694 AnimatedData::Matrix4(map) => {
695 map.len().hash(state);
696 #[cfg(not(feature = "interpolation"))]
697 for (time, value) in &map.values {
698 time.hash(state);
699 value.0.iter().for_each(|v| v.to_bits().hash(state));
700 }
701 #[cfg(feature = "interpolation")]
702 for (time, (value, spec)) in &map.values {
703 time.hash(state);
704 value.0.iter().for_each(|v| v.to_bits().hash(state));
705 spec.hash(state);
706 }
707 }
708 AnimatedData::BooleanVec(map) => {
709 map.len().hash(state);
710 #[cfg(not(feature = "interpolation"))]
711 for (time, value) in &map.values {
712 time.hash(state);
713 value.0.hash(state);
714 }
715 #[cfg(feature = "interpolation")]
716 for (time, (value, spec)) in &map.values {
717 time.hash(state);
718 value.0.hash(state);
719 spec.hash(state);
720 }
721 }
722 AnimatedData::IntegerVec(map) => {
723 map.len().hash(state);
724 #[cfg(not(feature = "interpolation"))]
725 for (time, value) in &map.values {
726 time.hash(state);
727 value.0.hash(state);
728 }
729 #[cfg(feature = "interpolation")]
730 for (time, (value, spec)) in &map.values {
731 time.hash(state);
732 value.0.hash(state);
733 spec.hash(state);
734 }
735 }
736 AnimatedData::RealVec(map) => {
737 map.len().hash(state);
738 #[cfg(not(feature = "interpolation"))]
739 for (time, value) in &map.values {
740 time.hash(state);
741 value.0.len().hash(state);
742 value.0.iter().for_each(|v| v.to_bits().hash(state));
743 }
744 #[cfg(feature = "interpolation")]
745 for (time, (value, spec)) in &map.values {
746 time.hash(state);
747 value.0.len().hash(state);
748 value.0.iter().for_each(|v| v.to_bits().hash(state));
749 spec.hash(state);
750 }
751 }
752 AnimatedData::ColorVec(map) => {
753 map.len().hash(state);
754 #[cfg(not(feature = "interpolation"))]
755 for (time, value) in &map.values {
756 time.hash(state);
757 value.0.len().hash(state);
758 value.0.iter().for_each(|c| {
759 c.iter().for_each(|v| v.to_bits().hash(state));
760 });
761 }
762 #[cfg(feature = "interpolation")]
763 for (time, (value, spec)) in &map.values {
764 time.hash(state);
765 value.0.len().hash(state);
766 value.0.iter().for_each(|c| {
767 c.iter().for_each(|v| v.to_bits().hash(state));
768 });
769 spec.hash(state);
770 }
771 }
772 AnimatedData::StringVec(map) => {
773 map.len().hash(state);
774 #[cfg(not(feature = "interpolation"))]
775 for (time, value) in &map.values {
776 time.hash(state);
777 value.0.hash(state);
778 }
779 #[cfg(feature = "interpolation")]
780 for (time, (value, spec)) in &map.values {
781 time.hash(state);
782 value.0.hash(state);
783 spec.hash(state);
784 }
785 }
786 #[cfg(all(feature = "vector2", feature = "vec_variants"))]
787 AnimatedData::Vector2Vec(map) => {
788 map.len().hash(state);
789 #[cfg(not(feature = "interpolation"))]
790 for (time, value) in &map.values {
791 time.hash(state);
792 value.0.len().hash(state);
793 value.0.iter().for_each(|v| {
794 v.iter().for_each(|f| f.to_bits().hash(state));
795 });
796 }
797 #[cfg(feature = "interpolation")]
798 for (time, (value, spec)) in &map.values {
799 time.hash(state);
800 value.0.len().hash(state);
801 value.0.iter().for_each(|v| {
802 v.iter().for_each(|f| f.to_bits().hash(state));
803 });
804 spec.hash(state);
805 }
806 }
807 #[cfg(all(feature = "vector3", feature = "vec_variants"))]
808 AnimatedData::Vector3Vec(map) => {
809 map.len().hash(state);
810 #[cfg(not(feature = "interpolation"))]
811 for (time, value) in &map.values {
812 time.hash(state);
813 value.0.len().hash(state);
814 value.0.iter().for_each(|v| {
815 v.iter().for_each(|f| f.to_bits().hash(state));
816 });
817 }
818 #[cfg(feature = "interpolation")]
819 for (time, (value, spec)) in &map.values {
820 time.hash(state);
821 value.0.len().hash(state);
822 value.0.iter().for_each(|v| {
823 v.iter().for_each(|f| f.to_bits().hash(state));
824 });
825 spec.hash(state);
826 }
827 }
828 #[cfg(all(feature = "matrix3", feature = "vec_variants"))]
829 AnimatedData::Matrix3Vec(map) => {
830 map.len().hash(state);
831 #[cfg(not(feature = "interpolation"))]
832 for (time, value) in &map.values {
833 time.hash(state);
834 value.0.len().hash(state);
835 value.0.iter().for_each(|m| {
836 m.iter().for_each(|f| f.to_bits().hash(state));
837 });
838 }
839 #[cfg(feature = "interpolation")]
840 for (time, (value, spec)) in &map.values {
841 time.hash(state);
842 value.0.len().hash(state);
843 value.0.iter().for_each(|m| {
844 m.iter().for_each(|f| f.to_bits().hash(state));
845 });
846 spec.hash(state);
847 }
848 }
849 #[cfg(all(feature = "normal3", feature = "vec_variants"))]
850 AnimatedData::Normal3Vec(map) => {
851 map.len().hash(state);
852 #[cfg(not(feature = "interpolation"))]
853 for (time, value) in &map.values {
854 time.hash(state);
855 value.0.len().hash(state);
856 value.0.iter().for_each(|v| {
857 v.iter().for_each(|f| f.to_bits().hash(state));
858 });
859 }
860 #[cfg(feature = "interpolation")]
861 for (time, (value, spec)) in &map.values {
862 time.hash(state);
863 value.0.len().hash(state);
864 value.0.iter().for_each(|v| {
865 v.iter().for_each(|f| f.to_bits().hash(state));
866 });
867 spec.hash(state);
868 }
869 }
870 #[cfg(all(feature = "point3", feature = "vec_variants"))]
871 AnimatedData::Point3Vec(map) => {
872 map.len().hash(state);
873 #[cfg(not(feature = "interpolation"))]
874 for (time, value) in &map.values {
875 time.hash(state);
876 value.0.len().hash(state);
877 value.0.iter().for_each(|p| {
878 p.coords.iter().for_each(|f| f.to_bits().hash(state));
879 });
880 }
881 #[cfg(feature = "interpolation")]
882 for (time, (value, spec)) in &map.values {
883 time.hash(state);
884 value.0.len().hash(state);
885 value.0.iter().for_each(|p| {
886 p.coords.iter().for_each(|f| f.to_bits().hash(state));
887 });
888 spec.hash(state);
889 }
890 }
891 #[cfg(all(feature = "matrix4", feature = "vec_variants"))]
892 AnimatedData::Matrix4Vec(map) => {
893 map.len().hash(state);
894 #[cfg(not(feature = "interpolation"))]
895 for (time, value) in &map.values {
896 time.hash(state);
897 value.0.len().hash(state);
898 value.0.iter().for_each(|m| {
899 m.iter().for_each(|f| f.to_bits().hash(state));
900 });
901 }
902 #[cfg(feature = "interpolation")]
903 for (time, (value, spec)) in &map.values {
904 time.hash(state);
905 value.0.len().hash(state);
906 value.0.iter().for_each(|m| {
907 m.iter().for_each(|f| f.to_bits().hash(state));
908 });
909 spec.hash(state);
910 }
911 }
912 }
913 }
914}
915
916impl_sample_for_animated_data!(
918 Real, Real;
919 Integer, Integer;
920 Color, Color;
921);
922
923impl_sample_for_animated_data!(
924 Vector2, Vector2, "vector2";
925 Vector3, Vector3, "vector3";
926 Matrix3, Matrix3, "matrix3";
927 Normal3, Normal3, "normal3";
928 Point3, Point3, "point3";
929 Matrix4, Matrix4, "matrix4";
930);
931
932impl AnimatedData {
933 pub fn hash_with_shutter<H: Hasher>(&self, state: &mut H, shutter: &Shutter) {
939 use smallvec::SmallVec;
940
941 const SAMPLE_POSITIONS: [f32; 5] = [0.0, 0.25, 0.5, 0.75, 1.0];
943
944 let samples: SmallVec<[Data; 5]> = SAMPLE_POSITIONS
946 .iter()
947 .map(|&pos| {
948 let time = shutter.evaluate(pos);
949 self.interpolate(time)
950 })
951 .collect();
952
953 let all_same = samples.windows(2).all(|w| w[0] == w[1]);
955
956 std::mem::discriminant(self).hash(state);
958
959 if all_same {
960 1usize.hash(state); samples[0].hash(state);
963 } else {
964 samples.len().hash(state); for sample in &samples {
967 sample.hash(state);
968 }
969 }
970 }
971}