use super::{Hold, Sequence, TimelineStep, Track, duration::max_duration};
use crate::{keyframes::Keyframes, property::PropertySnapshot, timing::Duration};
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Parallel {
steps: Vec<TimelineStep>,
}
impl Parallel {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn from_steps(steps: impl IntoIterator<Item = TimelineStep>) -> Self {
Self {
steps: steps.into_iter().collect(),
}
}
#[must_use]
pub fn steps(&self) -> &[TimelineStep] {
&self.steps
}
pub fn push_step(&mut self, step: impl Into<TimelineStep>) {
self.steps.push(step.into());
}
#[must_use]
pub fn then(mut self, step: impl Into<TimelineStep>) -> Self {
self.push_step(step);
self
}
#[must_use]
pub fn track(self, track: impl Into<Track>) -> Self {
self.then(track.into())
}
#[must_use]
pub fn keyframes(self, keyframes: Keyframes) -> Self {
self.track(keyframes)
}
#[must_use]
pub fn hold(self, duration: impl Into<Duration>) -> Self {
self.then(Hold::new(duration.into()))
}
#[must_use]
pub fn sequence(self, sequence: Sequence) -> Self {
self.then(sequence)
}
#[must_use]
pub fn parallel_step(self, parallel: Parallel) -> Self {
self.then(parallel)
}
#[must_use]
pub fn total_duration(&self) -> Option<Duration> {
max_duration(self.steps.iter().map(TimelineStep::total_duration))
}
#[must_use]
pub fn sample_at(&self, offset: impl Into<Duration>) -> Option<PropertySnapshot> {
let offset = offset.into();
let mut merged = PropertySnapshot::with_capacity(
self.steps.iter().map(TimelineStep::sample_entry_hint).sum(),
);
for step in &self.steps {
if let Some(snapshot) = step.sample_at(offset) {
merged.merge_unsorted(snapshot);
}
}
if merged.is_empty() {
None
} else {
merged.sort_by_composition_key();
Some(merged)
}
}
#[must_use]
pub fn completion_snapshot(&self) -> Option<PropertySnapshot> {
let mut merged = PropertySnapshot::new();
for step in &self.steps {
if let Some(snapshot) = step.completion_snapshot() {
merged.merge(snapshot);
}
}
if merged.is_empty() {
None
} else {
merged.sort_by_composition_key();
Some(merged)
}
}
}