1use crate::animation::{AnimationState, Interpolator};
2use crate::prelude::*;
3use vizia_storage::{SparseSet, SparseSetGeneric, SparseSetIndex};
4
5const INDEX_MASK: u32 = u32::MAX / 4;
6const INLINE_MASK: u32 = 1 << 31;
7const INHERITED_MASK: u32 = 1 << 30;
8
9#[derive(Clone, Copy, PartialEq)]
18struct DataIndex(u32);
19
20impl DataIndex {
21 pub fn inline(index: usize) -> Self {
24 assert!((index as u32) < INDEX_MASK);
25 let value = (index as u32) | INLINE_MASK;
26 Self(value)
27 }
28
29 pub fn inherited(self) -> Self {
30 let value = self.0;
31 Self(value | INHERITED_MASK)
32 }
33
34 pub fn shared(index: usize) -> Self {
37 assert!((index as u32) < INDEX_MASK);
38 Self(index as u32)
39 }
40
41 pub fn index(&self) -> usize {
43 (self.0 & INDEX_MASK) as usize
44 }
45
46 pub fn is_inline(&self) -> bool {
48 (self.0 & INLINE_MASK).rotate_left(1) != 0
49 }
50
51 pub fn is_inherited(&self) -> bool {
53 (self.0 & INHERITED_MASK).rotate_left(2) != 0
54 }
55
56 pub fn null() -> Self {
60 Self(u32::MAX >> 1)
61 }
62}
63
64impl std::fmt::Debug for DataIndex {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 if self.is_inline() {
67 write!(f, "Inline: {}", self.index())
68 } else {
69 write!(f, "Shared: {}", self.index())
70 }
71 }
72}
73
74#[derive(Debug, Clone, Copy, PartialEq)]
76pub(crate) struct InlineIndex {
77 data_index: DataIndex,
78 anim_index: u32,
79}
80
81impl Default for InlineIndex {
82 fn default() -> Self {
83 InlineIndex { data_index: DataIndex::null(), anim_index: u32::MAX }
84 }
85}
86
87impl SparseSetIndex for InlineIndex {
88 fn new(index: usize) -> Self {
89 InlineIndex { data_index: DataIndex::inline(index), anim_index: u32::MAX }
90 }
91
92 fn null() -> Self {
93 Self::default()
94 }
95
96 fn index(&self) -> usize {
97 self.data_index.index()
98 }
99}
100
101#[derive(Debug, Clone, Copy, PartialEq)]
102pub(crate) struct SharedIndex {
103 data_index: u32,
104 animation: Animation,
105}
106
107impl Default for SharedIndex {
108 fn default() -> Self {
109 SharedIndex { data_index: u32::MAX, animation: Animation::null() }
110 }
111}
112
113impl SparseSetIndex for SharedIndex {
114 fn new(index: usize) -> Self {
115 SharedIndex { data_index: index as u32, animation: Animation::null() }
116 }
117
118 fn null() -> Self {
119 Self::default()
120 }
121
122 fn index(&self) -> usize {
123 self.data_index as usize
124 }
125}
126
127#[derive(Default, Debug)]
134pub(crate) struct AnimatableSet<T: Interpolator> {
135 pub(crate) shared_data: SparseSetGeneric<SharedIndex, T>,
137 pub(crate) inline_data: SparseSetGeneric<InlineIndex, T>,
139 animations: SparseSet<AnimationState<T>>,
141 active_animations: Vec<AnimationState<T>>,
143}
144
145impl<T> AnimatableSet<T>
146where
147 T: 'static + Default + Clone + Interpolator + PartialEq + std::fmt::Debug,
148{
149 pub fn insert(&mut self, entity: Entity, value: T) {
151 self.inline_data.insert(entity, value);
152 }
153
154 pub fn remove(&mut self, entity: Entity) -> Option<T> {
156 let entity_index = entity.index();
157
158 if entity_index < self.inline_data.sparse.len() {
159 let active_anim_index = self.inline_data.sparse[entity_index].anim_index as usize;
160
161 if active_anim_index < self.active_animations.len() {
162 let anim_state = &mut self.active_animations[active_anim_index];
163 anim_state.t = 1.0;
164
165 self.remove_innactive_animations();
166 }
167
168 let data_index = self.inline_data.sparse[entity_index].data_index;
169 if data_index.is_inline() && !data_index.is_inherited() {
170 self.inline_data.remove(entity)
171 } else {
172 self.inline_data.sparse[entity_index] = InlineIndex::null();
173 None
174 }
175 } else {
176 None
177 }
178 }
179
180 pub fn inherit_inline(&mut self, entity: Entity, parent: Entity) -> bool {
182 let entity_index = entity.index();
183 let parent_index = parent.index();
184
185 if parent_index < self.inline_data.sparse.len() {
186 let parent_sparse_index = self.inline_data.sparse[parent_index];
187
188 if parent_sparse_index.data_index.is_inline()
189 && parent_sparse_index.data_index.index() < self.inline_data.dense.len()
190 {
191 if entity_index >= self.inline_data.sparse.len() {
192 self.inline_data.sparse.resize(entity_index + 1, InlineIndex::null());
193 }
194
195 let entity_sparse_index = self.inline_data.sparse[entity_index];
196
197 if self.inline_data.sparse[entity_index].data_index.index()
198 != parent_sparse_index.data_index.index()
199 {
200 if entity_sparse_index.data_index.index() < self.inline_data.dense.len() {
201 if entity_sparse_index.data_index.is_inherited()
202 && entity_sparse_index.data_index.is_inline()
203 {
204 self.inline_data.sparse[entity_index] = InlineIndex {
205 data_index: DataIndex::inline(
206 parent_sparse_index.data_index.index(),
207 )
208 .inherited(),
209 anim_index: u32::MAX,
210 };
211 return true;
212 }
213 } else {
214 self.inline_data.sparse[entity_index] = InlineIndex {
215 data_index: DataIndex::inline(parent_sparse_index.data_index.index())
216 .inherited(),
217 anim_index: u32::MAX,
218 };
219 return true;
220 }
221 }
222 }
223 }
224
225 false
226 }
227
228 pub fn inherit_shared(&mut self, entity: Entity, parent: Entity) -> bool {
230 let entity_index = entity.index();
231 let parent_index = parent.index();
232
233 if parent_index < self.inline_data.sparse.len() {
234 let parent_sparse_index = self.inline_data.sparse[parent_index];
235
236 if !parent_sparse_index.data_index.is_inline()
237 && parent_sparse_index.data_index.index() < self.shared_data.dense.len()
238 {
239 if entity_index >= self.inline_data.sparse.len() {
240 self.inline_data.sparse.resize(entity_index + 1, InlineIndex::null());
241 }
242
243 let entity_sparse_index = self.inline_data.sparse[entity_index];
244
245 if !entity_sparse_index.data_index.is_inline()
246 && self.inline_data.sparse[entity_index].data_index.index()
247 != parent_sparse_index.data_index.index()
248 {
249 if entity_sparse_index.data_index.index() < self.shared_data.dense.len() {
250 if entity_sparse_index.data_index.is_inherited() {
251 self.inline_data.sparse[entity_index] = InlineIndex {
252 data_index: DataIndex::shared(
253 parent_sparse_index.data_index.index(),
254 )
255 .inherited(),
256 anim_index: u32::MAX,
257 };
258 return true;
259 }
260 } else {
261 if !entity_sparse_index.data_index.is_inline() {
262 self.inline_data.sparse[entity_index] = InlineIndex {
263 data_index: DataIndex::shared(
264 parent_sparse_index.data_index.index(),
265 )
266 .inherited(),
267 anim_index: u32::MAX,
268 };
269 }
270 return true;
271 }
272 }
273 }
274 }
275
276 false
277 }
278
279 pub(crate) fn insert_animation(
285 &mut self,
286 animation: Animation,
287 animation_description: AnimationState<T>,
288 ) {
289 self.animations.insert(animation, animation_description);
290 }
291
292 pub(crate) fn insert_rule(&mut self, rule: Rule, value: T) {
293 self.shared_data.insert(rule, value);
294 }
295
296 pub(crate) fn insert_transition(&mut self, rule: Rule, animation: Animation) {
306 if self.shared_data.contains(rule) && self.animations.contains(animation) {
308 self.shared_data.sparse[rule.index()].animation = animation;
309 }
310 }
311
312 pub(crate) fn play_animation(
314 &mut self,
315 entity: Entity,
316 animation: Animation,
317 start_time: Instant,
318 duration: Duration,
319 delay: Duration,
320 ) {
321 let entity_index = entity.index();
322
323 if !self.animations.contains(animation) {
324 return;
325 }
326
327 if entity_index >= self.inline_data.sparse.len() {
329 self.inline_data.sparse.resize(entity_index + 1, InlineIndex::null());
330 }
331
332 if entity_index < self.inline_data.sparse.len() {
333 let active_anim_index = self.inline_data.sparse[entity_index].anim_index as usize;
334 if active_anim_index < self.active_animations.len() {
335 let anim_state = &mut self.active_animations[active_anim_index];
336 if anim_state.id == animation {
337 anim_state.active = true;
338 anim_state.t = 0.0;
339 anim_state.start_time = start_time;
340 anim_state.output = Some(
341 self.animations
342 .get(animation)
343 .cloned()
344 .unwrap()
345 .keyframes
346 .first()
347 .unwrap()
348 .value
349 .clone(),
350 );
351 } else {
352 anim_state.output = Some(
353 self.animations
354 .get(animation)
355 .cloned()
356 .unwrap()
357 .keyframes
358 .first()
359 .unwrap()
360 .value
361 .clone(),
362 );
363 anim_state.entities.remove(&entity);
364 }
365 }
366
367 let mut anim_state = self.animations.get(animation).cloned().unwrap();
369 anim_state.duration = duration;
370 anim_state.id = animation;
371 anim_state.delay = delay;
372 anim_state.dt = delay.as_secs_f32() / duration.as_secs_f32();
373 anim_state.output = Some(
374 self.animations
375 .get(animation)
376 .cloned()
377 .unwrap()
378 .keyframes
379 .first()
380 .unwrap()
381 .value
382 .clone(),
383 );
384 anim_state.play(entity);
385 self.inline_data.sparse[entity_index].anim_index = self.active_animations.len() as u32;
386 self.active_animations.push(anim_state);
387 }
388 }
389
390 pub(crate) fn stop_animation(&mut self, entity: Entity, animation: Animation) {
392 let entity_index = entity.index();
393
394 if entity_index < self.inline_data.sparse.len() {
395 let active_anim_index = self.inline_data.sparse[entity_index].anim_index as usize;
396 if active_anim_index < self.active_animations.len() {
397 let anim_state = &mut self.active_animations[active_anim_index];
398 if anim_state.id == animation {
399 anim_state.entities.remove(&entity);
400 }
401 }
402 self.inline_data.sparse[entity_index].anim_index = u32::MAX;
403 }
404 }
405
406 pub fn tick(&mut self, time: Instant) -> Vec<Entity> {
408 self.remove_innactive_animations();
409
410 if self.has_animations() {
411 for state in self.active_animations.iter_mut() {
412 if state.t == 1.0 {
414 continue;
415 }
416
417 if state.keyframes.len() == 1 {
418 state.output = Some(state.keyframes[0].value.clone());
419 continue;
420 }
421
422 let elapsed_time = time.duration_since(state.start_time);
423 let mut normalised_time =
424 (elapsed_time.as_secs_f32() / state.duration.as_secs_f32()) - state.dt;
425
426 normalised_time = normalised_time.clamp(0.0, 1.0);
427
428 let mut i = 0;
429 while i < state.keyframes.len() - 1 && state.keyframes[i + 1].time < normalised_time
430 {
431 i += 1;
432 }
433 let start = &state.keyframes[i];
434 let end = &state.keyframes[i + 1];
435
436 let normalised_elapsed_time =
437 (normalised_time - start.time) / (end.time - start.time);
438
439 state.t = normalised_time;
440
441 let timing_t = start.timing_function.value(normalised_elapsed_time);
442 state.output = Some(T::interpolate(&start.value, &end.value, timing_t));
443 }
444
445 self.active_animations
446 .iter()
447 .flat_map(|state| state.entities.clone())
448 .collect::<Vec<Entity>>()
449 } else {
450 Vec::new()
451 }
452 }
453
454 pub fn remove_innactive_animations(&mut self) {
469 let inactive: Vec<AnimationState<T>> = self
471 .active_animations
472 .iter()
473 .filter(|e| e.t == 1.0 && !e.persistent)
474 .cloned()
475 .collect();
476
477 self.active_animations.retain(|e| e.t < 1.0 || e.persistent);
480
481 for state in inactive.into_iter() {
482 for entity in state.entities.iter() {
483 self.inline_data.sparse[entity.index()].anim_index = u32::MAX;
484 }
485 }
486
487 for (index, state) in self.active_animations.iter().enumerate() {
488 for entity in state.entities.iter() {
489 self.inline_data.sparse[entity.index()].anim_index = index as u32;
490 }
491 }
492 }
493
494 pub fn has_animations(&self) -> bool {
496 for state in self.active_animations.iter() {
497 if state.t < 1.0 {
498 return true;
499 }
500 }
501
502 false
503 }
504
505 pub fn has_active_animation(&self, entity: Entity, animation: Animation) -> bool {
507 let entity_index = entity.index();
508 if entity_index < self.inline_data.sparse.len() {
509 let anim_index = self.inline_data.sparse[entity_index].anim_index as usize;
510 if anim_index < self.active_animations.len()
511 && self.active_animations[anim_index].id == animation
512 {
513 return true;
514 }
515 }
516
517 false
518 }
519
520 pub fn get_inline_mut(&mut self, entity: Entity) -> Option<&mut T> {
535 let entity_index = entity.index();
536 if entity_index < self.inline_data.sparse.len() {
537 let data_index = self.inline_data.sparse[entity_index].data_index;
538 if data_index.is_inline() {
539 return self.inline_data.get_mut(entity);
540 }
541 }
542
543 None
544 }
545
546 pub(crate) fn get_animation_mut(
557 &mut self,
558 animation: Animation,
559 ) -> Option<&mut AnimationState<T>> {
560 self.animations.get_mut(animation)
561 }
562
563 pub(crate) fn get_active_animation(&self, entity: Entity) -> Option<&AnimationState<T>> {
566 let entity_index = entity.index();
567 if entity_index < self.inline_data.sparse.len() {
568 let anim_index = self.inline_data.sparse[entity_index].anim_index as usize;
569 if anim_index < self.active_animations.len() {
570 return Some(&self.active_animations[anim_index]);
571 }
572 }
573
574 None
575 }
576
577 pub(crate) fn get_active_animations(&mut self) -> Option<&Vec<AnimationState<T>>> {
579 Some(&self.active_animations)
580 }
581
582 pub fn get(&self, entity: Entity) -> Option<&T> {
584 let entity_index = entity.index();
585 if entity_index < self.inline_data.sparse.len() {
586 let animation_index = self.inline_data.sparse[entity_index].anim_index as usize;
588
589 if animation_index < self.active_animations.len() {
590 return self.active_animations[animation_index].get_output();
591 }
592
593 let data_index = self.inline_data.sparse[entity_index].data_index;
594 if data_index.is_inline() {
595 if data_index.index() < self.inline_data.dense.len() {
596 return Some(&self.inline_data.dense[data_index.index()].value);
597 }
598 } else if data_index.index() < self.shared_data.dense.len() {
599 return Some(&self.shared_data.dense[data_index.index()].value);
600 }
601 }
602
603 None
604 }
605
606 pub(crate) fn link(&mut self, entity: Entity, rules: &[(Rule, u32)]) -> bool {
608 let entity_index = entity.index();
609
610 if entity_index < self.inline_data.sparse.len() {
612 let data_index = self.inline_data.sparse[entity_index].data_index;
613 if data_index.is_inline() && !data_index.is_inherited() {
615 return false;
616 }
617 }
618
619 for (rule, _) in rules {
621 if let Some(shared_data_index) = self.shared_data.dense_idx(*rule) {
622 if entity_index >= self.inline_data.sparse.len() {
624 self.inline_data.sparse.resize(entity_index + 1, InlineIndex::null());
625 }
626
627 let rule_animation = shared_data_index.animation;
629
630 let entity_anim_index = self.inline_data.sparse[entity_index].anim_index as usize;
632 if entity_anim_index < self.active_animations.len() {
633 let current_value = self.get(entity).cloned().unwrap_or_default();
635 let current_anim_state = &mut self.active_animations[entity_anim_index];
636 let rule_data_index = shared_data_index.data_index as usize;
637
638 if current_anim_state.is_transition() {
639 if current_anim_state.to_rule != rule_data_index {
641 if rule_data_index == current_anim_state.from_rule {
642 current_anim_state.from_rule = current_anim_state.to_rule;
644 current_anim_state.to_rule = rule_data_index;
645 current_anim_state.keyframes.first_mut().unwrap().value =
646 self.shared_data.dense[current_anim_state.from_rule]
647 .value
648 .clone();
649
650 current_anim_state.keyframes.last_mut().unwrap().value =
651 self.shared_data.dense[current_anim_state.to_rule]
652 .value
653 .clone();
654
655 current_anim_state.dt = current_anim_state.t - 1.0;
656 current_anim_state.start_time = Instant::now();
657 } else {
658 current_anim_state.to_rule = rule_data_index;
660 current_anim_state.keyframes.first_mut().unwrap().value =
661 current_value;
662 current_anim_state.keyframes.last_mut().unwrap().value =
663 self.shared_data.dense[current_anim_state.to_rule]
664 .value
665 .clone();
666 current_anim_state.t = 0.0;
667 current_anim_state.start_time = Instant::now();
668 }
669 }
670 }
671 } else if let Some(transition_state) = self.animations.get_mut(rule_animation) {
672 let end = self.shared_data.get(*rule).unwrap();
674
675 let entity_data_index = self.inline_data.sparse[entity_index].data_index;
676
677 if !entity_data_index.is_inline()
678 && entity_data_index.index() < self.shared_data.dense.len()
679 {
680 let start_data =
681 self.shared_data.dense[entity_data_index.index()].value.clone();
682 transition_state.keyframes.first_mut().unwrap().value = start_data;
683 } else {
684 transition_state.keyframes.first_mut().unwrap().value = end.clone();
685 }
686
687 transition_state.keyframes.last_mut().unwrap().value = end.clone();
688 transition_state.from_rule =
689 self.inline_data.sparse[entity_index].data_index.index();
690 transition_state.to_rule = shared_data_index.index();
691
692 let duration = transition_state.duration;
693 let delay = transition_state.delay;
694
695 if transition_state.from_rule != DataIndex::null().index()
696 && transition_state.from_rule != transition_state.to_rule
697 {
698 self.play_animation(
699 entity,
700 rule_animation,
701 Instant::now(),
702 duration,
703 delay,
704 );
705 }
706 }
708 let data_index = self.inline_data.sparse[entity_index].data_index;
711
712 if !data_index.is_inline() && data_index.index() == shared_data_index.index() {
714 return false;
715 }
716
717 self.inline_data.sparse[entity_index].data_index =
718 DataIndex::shared(shared_data_index.index());
719
720 return true;
721 }
722 }
723
724 if entity_index < self.inline_data.sparse.len() {
726 let data_index = self.inline_data.sparse[entity_index].data_index;
727 if !data_index.is_inline()
728 && !data_index.is_inherited()
729 && self.inline_data.sparse[entity_index].data_index != DataIndex::null()
730 {
731 self.inline_data.sparse[entity_index].data_index = DataIndex::null();
732 return true;
733 }
734 }
735
736 false
737 }
738
739 pub fn clear_rules(&mut self) {
741 for index in self.shared_data.sparse.iter() {
743 let animation = index.animation;
744 self.animations.remove(animation);
745 }
746
747 self.shared_data.clear();
748
749 for index in self.inline_data.sparse.iter_mut() {
750 if !index.data_index.is_inline() {
751 index.data_index = DataIndex::null();
752 }
753 }
754 }
755}
756
757#[cfg(test)]
758mod tests {
759 use super::*;
760
761 #[test]
765 fn inline() {
766 let data_index = DataIndex::inline(5);
767 assert_eq!(data_index.0, INLINE_MASK + 5);
768 assert_eq!(data_index.index(), 5);
769 }
770
771 #[test]
773 #[should_panic]
774 fn invalid_inline() {
775 DataIndex::inline(usize::MAX);
776 }
777
778 #[test]
780 fn shared() {
781 let data_index = DataIndex::shared(5);
782 assert_eq!(data_index.0, 5);
783 assert_eq!(data_index.index(), 5);
784 }
785
786 #[test]
788 #[should_panic]
789 fn invalid_shared() {
790 DataIndex::shared(usize::MAX);
791 }
792
793 #[test]
795 fn is_inline() {
796 let data_index1 = DataIndex::inline(5);
797 assert!(data_index1.is_inline());
798 let data_index2 = DataIndex::shared(5);
799 assert!(!data_index2.is_inline());
800 }
801
802 #[test]
804 fn null() {
805 let data_index = DataIndex::null();
806 assert_eq!(data_index.0, 2147483647);
807 }
808
809 #[test]
813 fn new() {
814 let animatable_storage = AnimatableSet::<f32>::default();
815 assert!(animatable_storage.inline_data.is_empty());
816 assert!(animatable_storage.shared_data.is_empty());
817 assert!(animatable_storage.animations.is_empty());
818 assert!(animatable_storage.active_animations.is_empty());
819 }
820
821 #[test]
823 fn insert_inline() {
824 let mut animatable_storage = AnimatableSet::default();
825 animatable_storage.insert(Entity::root(), 5.0);
826 }
828}