Skip to main content

aura_anim_core/
timing.rs

1//! Timing configuration and elapsed-time normalization.
2
3mod duration;
4mod iteration;
5mod mode;
6mod utils;
7
8pub use duration::{Delay, Duration};
9pub use iteration::IterationCount;
10pub use mode::Direction;
11
12pub use lilt::Easing;
13
14/// Timing configuration shared by duration-based animations.
15///
16/// # Examples
17///
18/// ```
19/// use aura_anim_core::timing::{Delay, Direction, Easing, Timing};
20///
21/// let timing = Timing::new(250.0)
22///     .with_delay(Delay::from_millis(50.0))
23///     .with_easing(Easing::EaseOut)
24///     .with_direction(Direction::Alternate)
25///     .with_iterations(2);
26///
27/// assert_eq!(timing.duration().as_millis(), 250.0);
28/// assert_eq!(timing.total_duration().unwrap().as_millis(), 550.0);
29/// ```
30#[derive(Debug, Clone, Copy, PartialEq)]
31pub struct Timing {
32    /// Active duration for one iteration.
33    duration: Duration,
34    /// Start delay before the active interval.
35    delay: Delay,
36    /// Playback direction configuration.
37    direction: Direction,
38    /// Easing curve applied to normalized iteration progress.
39    easing: Easing,
40    /// Number of active iterations.
41    iterations: IterationCount,
42}
43
44impl Timing {
45    /// Creates a timing value with a duration in milliseconds.
46    #[must_use]
47    pub fn new(duration_ms: f64) -> Self {
48        Self {
49            duration: Duration::from_millis(duration_ms),
50            ..Self::default()
51        }
52    }
53
54    /// Returns the duration of the timing.
55    #[must_use]
56    pub const fn duration(&self) -> Duration {
57        self.duration
58    }
59
60    /// Returns the delay of the timing.
61    #[must_use]
62    pub const fn delay(&self) -> Delay {
63        self.delay
64    }
65
66    /// Returns the direction of the timing.
67    #[must_use]
68    pub const fn direction(&self) -> Direction {
69        self.direction
70    }
71
72    /// Returns the easing curve of the timing.
73    #[must_use]
74    pub const fn easing(&self) -> Easing {
75        self.easing
76    }
77
78    /// Returns the number of iterations of the timing.
79    #[must_use]
80    pub const fn iterations(&self) -> IterationCount {
81        self.iterations
82    }
83
84    /// Sets the start delay.
85    #[must_use]
86    pub const fn with_delay(mut self, delay: Delay) -> Self {
87        self.delay = delay;
88        self
89    }
90
91    /// Sets the playback direction.
92    #[must_use]
93    pub const fn with_direction(mut self, direction: Direction) -> Self {
94        self.direction = direction;
95        self
96    }
97
98    /// Sets the easing curve.
99    #[must_use]
100    pub const fn with_easing(mut self, easing: Easing) -> Self {
101        self.easing = easing;
102        self
103    }
104
105    /// Sets the iteration count.
106    #[must_use]
107    pub fn with_iterations(mut self, iterations: impl Into<IterationCount>) -> Self {
108        self.iterations = iterations.into();
109        self
110    }
111
112    /// Returns the total active duration when the timing has a finite length.
113    #[must_use]
114    pub fn active_duration(self) -> Option<Duration> {
115        let count = self.iterations.finite_count()?;
116
117        self.duration.checked_mul(count)
118    }
119
120    /// Returns the total duration including delay when finite.
121    #[must_use]
122    pub fn total_duration(self) -> Option<Duration> {
123        let active = self.active_duration()?;
124
125        active.checked_add_delay(self.delay)
126    }
127
128    pub(crate) fn with_duration(mut self, duration: Duration) -> Self {
129        self.duration = duration;
130        self
131    }
132}
133
134impl Default for Timing {
135    fn default() -> Self {
136        Self {
137            duration: Duration::ZERO,
138            delay: Delay::ZERO,
139            direction: Direction::default(),
140            easing: Easing::Linear,
141            iterations: IterationCount::default(),
142        }
143    }
144}