aura_anim_iced/state/
progress.rs1use crate::{AnimationHandle, Duration};
2
3#[derive(Debug, Clone, Copy, PartialEq)]
5pub struct ActiveStateTransition<S>
6where
7 S: Copy + Eq,
8{
9 handle: AnimationHandle,
10 from: S,
11 to: S,
12 started_at: Duration,
13 duration: Option<Duration>,
14}
15
16impl<S> ActiveStateTransition<S>
17where
18 S: Copy + Eq,
19{
20 pub(crate) const fn new(
21 handle: AnimationHandle,
22 from: S,
23 to: S,
24 started_at: Duration,
25 duration: Option<Duration>,
26 ) -> Self {
27 Self {
28 handle,
29 from,
30 to,
31 started_at,
32 duration,
33 }
34 }
35
36 #[must_use]
38 pub const fn handle(&self) -> AnimationHandle {
39 self.handle
40 }
41
42 #[must_use]
44 pub const fn from(&self) -> S {
45 self.from
46 }
47
48 #[must_use]
50 pub const fn to(&self) -> S {
51 self.to
52 }
53
54 #[must_use]
56 pub const fn started_at(&self) -> Duration {
57 self.started_at
58 }
59
60 #[must_use]
62 pub const fn duration(&self) -> Option<Duration> {
63 self.duration
64 }
65
66 #[must_use]
68 pub fn progress_at(&self, timestamp: Duration) -> StateTransitionProgress<S> {
69 let elapsed = timestamp
70 .checked_sub(self.started_at)
71 .unwrap_or(Duration::ZERO);
72 let progress = self
73 .duration
74 .map(|duration| normalized_progress(elapsed, duration));
75
76 StateTransitionProgress {
77 handle: self.handle,
78 from: self.from,
79 to: self.to,
80 elapsed,
81 duration: self.duration,
82 progress,
83 }
84 }
85}
86
87#[derive(Debug, Clone, Copy, PartialEq)]
89pub struct StateTransitionProgress<S>
90where
91 S: Copy + Eq,
92{
93 handle: AnimationHandle,
94 from: S,
95 to: S,
96 elapsed: Duration,
97 duration: Option<Duration>,
98 progress: Option<f32>,
99}
100
101impl<S> StateTransitionProgress<S>
102where
103 S: Copy + Eq,
104{
105 #[must_use]
107 pub const fn handle(&self) -> AnimationHandle {
108 self.handle
109 }
110
111 #[must_use]
113 pub const fn from(&self) -> S {
114 self.from
115 }
116
117 #[must_use]
119 pub const fn to(&self) -> S {
120 self.to
121 }
122
123 #[must_use]
125 pub const fn elapsed(&self) -> Duration {
126 self.elapsed
127 }
128
129 #[must_use]
131 pub const fn duration(&self) -> Option<Duration> {
132 self.duration
133 }
134
135 #[must_use]
137 pub const fn progress(&self) -> Option<f32> {
138 self.progress
139 }
140}
141
142fn normalized_progress(elapsed: Duration, duration: Duration) -> f32 {
143 let duration_ms = duration.as_millis();
144
145 if duration_ms <= 0.0 {
146 return 1.0;
147 }
148
149 #[allow(
150 clippy::cast_possible_truncation,
151 reason = "State transition progress is normalized for UI consumption."
152 )]
153 {
154 (elapsed.as_millis() / duration_ms).clamp(0.0, 1.0) as f32
155 }
156}