aura_anim_iced/timeline/
parallel.rs1use super::{Hold, Sequence, TimelineStep, Track, duration::max_duration};
2use crate::{keyframes::Keyframes, property::PropertySnapshot, timing::Duration};
3
4#[derive(Debug, Clone, PartialEq, Default)]
6pub struct Parallel {
7 steps: Vec<TimelineStep>,
8}
9
10impl Parallel {
11 #[must_use]
13 pub fn new() -> Self {
14 Self::default()
15 }
16
17 #[must_use]
19 pub fn from_steps(steps: impl IntoIterator<Item = TimelineStep>) -> Self {
20 Self {
21 steps: steps.into_iter().collect(),
22 }
23 }
24
25 #[must_use]
27 pub fn steps(&self) -> &[TimelineStep] {
28 &self.steps
29 }
30
31 pub fn push_step(&mut self, step: impl Into<TimelineStep>) {
33 self.steps.push(step.into());
34 }
35
36 #[must_use]
38 pub fn then(mut self, step: impl Into<TimelineStep>) -> Self {
39 self.push_step(step);
40 self
41 }
42
43 #[must_use]
45 pub fn track(self, track: impl Into<Track>) -> Self {
46 self.then(track.into())
47 }
48
49 #[must_use]
51 pub fn keyframes(self, keyframes: Keyframes) -> Self {
52 self.track(keyframes)
53 }
54
55 #[must_use]
57 pub fn hold(self, duration: impl Into<Duration>) -> Self {
58 self.then(Hold::new(duration.into()))
59 }
60
61 #[must_use]
63 pub fn sequence(self, sequence: Sequence) -> Self {
64 self.then(sequence)
65 }
66
67 #[must_use]
69 pub fn parallel_step(self, parallel: Parallel) -> Self {
70 self.then(parallel)
71 }
72
73 #[must_use]
75 pub fn total_duration(&self) -> Option<Duration> {
76 max_duration(self.steps.iter().map(TimelineStep::total_duration))
77 }
78
79 #[must_use]
81 pub fn sample_at(&self, offset: impl Into<Duration>) -> Option<PropertySnapshot> {
82 let offset = offset.into();
83 let mut merged = PropertySnapshot::with_capacity(
84 self.steps.iter().map(TimelineStep::sample_entry_hint).sum(),
85 );
86
87 for step in &self.steps {
88 if let Some(snapshot) = step.sample_at(offset) {
89 merged.merge_unsorted(snapshot);
90 }
91 }
92
93 if merged.is_empty() {
94 None
95 } else {
96 merged.sort_by_composition_key();
97 Some(merged)
98 }
99 }
100
101 #[must_use]
103 pub fn completion_snapshot(&self) -> Option<PropertySnapshot> {
104 let mut merged = PropertySnapshot::new();
105
106 for step in &self.steps {
107 if let Some(snapshot) = step.completion_snapshot() {
108 merged.merge(snapshot);
109 }
110 }
111
112 if merged.is_empty() {
113 None
114 } else {
115 merged.sort_by_composition_key();
116 Some(merged)
117 }
118 }
119}