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