anim8/
transition.rs

1use crate::{Scalar, phase::Phase};
2use serde::{Deserialize, Serialize};
3use std::ops::Range;
4
5/// Describes playable smooth transition between two data values using animation phase.
6#[derive(Debug, Default, Clone, Serialize, Deserialize)]
7pub struct Transition<T> {
8    from: T,
9    to: T,
10    #[serde(default)]
11    pub phase: Phase,
12    #[serde(default)]
13    pub playing: bool,
14    #[serde(default)]
15    time: Scalar,
16}
17
18impl<T> Transition<T>
19where
20    T: Clone,
21{
22    pub fn new(from: T, to: T, phase: Phase) -> Self {
23        Self {
24            from,
25            to,
26            playing: false,
27            time: phase.time_frame().start,
28            phase,
29        }
30    }
31
32    pub fn instant(value: T) -> Self {
33        Self::new(
34            value.clone(),
35            value,
36            Phase::point(1.0).expect("Could not create point phase for instant transition"),
37        )
38    }
39
40    pub fn time(&self) -> Scalar {
41        self.time
42    }
43
44    pub fn start(&mut self) {
45        self.time = self.phase.time_frame().start;
46    }
47
48    pub fn end(&mut self) {
49        self.time = self.phase.time_frame().end;
50    }
51
52    pub fn set_time(&mut self, time: Scalar) {
53        self.time = time
54            .max(self.phase.time_frame().start)
55            .min(self.phase.time_frame().end);
56    }
57
58    pub fn in_progress(&self) -> bool {
59        self.time < self.phase.time_frame().end
60    }
61
62    pub fn is_complete(&self) -> bool {
63        !self.in_progress()
64    }
65
66    pub fn from(&self) -> &T {
67        &self.from
68    }
69
70    pub fn from_mut(&mut self) -> &mut T {
71        &mut self.from
72    }
73
74    pub fn to(&self) -> &T {
75        &self.to
76    }
77
78    pub fn to_mut(&mut self) -> &mut T {
79        &mut self.to
80    }
81
82    pub fn time_frame(&self) -> Range<Scalar> {
83        self.phase.time_frame()
84    }
85
86    pub fn duration(&self) -> Scalar {
87        self.phase.duration()
88    }
89
90    pub fn phase(&self) -> Scalar {
91        self.sample(self.time)
92    }
93
94    pub fn sample(&self, time: Scalar) -> Scalar {
95        self.phase.sample(time)
96    }
97
98    pub fn set(&mut self, value: T) {
99        self.from = self.to.clone();
100        self.to = value;
101        self.time = 0.0;
102    }
103
104    pub fn process(&mut self, delta_time: Scalar) {
105        if self.playing {
106            let time_frame = self.phase.time_frame();
107            let time = self.time + delta_time;
108            if time >= time_frame.end {
109                self.playing = false;
110            }
111            self.time = time.max(time_frame.start).min(time_frame.end);
112        }
113    }
114}
115
116impl<T> PartialEq for Transition<T>
117where
118    T: Clone + PartialEq,
119{
120    fn eq(&self, other: &Self) -> bool {
121        self.from == other.from
122            && self.to == other.to
123            && self.phase == other.phase
124            && self.playing == other.playing
125            && self.time == other.time
126    }
127}
128
129/// Describes playable step transition between two data values using animation phase.
130#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
131pub struct SwitchTransition {
132    value: bool,
133    #[serde(default)]
134    pub phase: Phase,
135    #[serde(default)]
136    pub playing: bool,
137    #[serde(default)]
138    time: Scalar,
139}
140
141impl SwitchTransition {
142    pub fn new(value: bool, phase: Phase) -> Self {
143        let time = if value {
144            phase.time_frame().end
145        } else {
146            phase.time_frame().start
147        };
148        Self {
149            value,
150            phase,
151            playing: false,
152            time,
153        }
154    }
155
156    pub fn instant(value: bool) -> Self {
157        Self::new(
158            value,
159            Phase::point(1.0).expect("Could not create point phase for instant switch"),
160        )
161    }
162
163    pub fn time(&self) -> Scalar {
164        self.time
165    }
166
167    pub fn start(&mut self) {
168        self.time = if self.value {
169            self.phase.time_frame().start
170        } else {
171            self.phase.time_frame().end
172        };
173    }
174
175    pub fn end(&mut self) {
176        self.time = if self.value {
177            self.phase.time_frame().end
178        } else {
179            self.phase.time_frame().start
180        };
181    }
182
183    pub fn set_time(&mut self, time: Scalar) {
184        self.time = time
185            .max(self.phase.time_frame().start)
186            .min(self.phase.time_frame().end);
187    }
188
189    pub fn in_progress(&self) -> bool {
190        if self.value {
191            self.time < self.phase.time_frame().end
192        } else {
193            self.time > self.phase.time_frame().start
194        }
195    }
196
197    pub fn is_complete(&self) -> bool {
198        !self.in_progress()
199    }
200
201    pub fn value(&self) -> bool {
202        self.value
203    }
204
205    pub fn duration(&self) -> Scalar {
206        self.phase.duration()
207    }
208
209    pub fn phase(&self) -> Scalar {
210        self.sample(self.time)
211    }
212
213    pub fn sample(&self, time: Scalar) -> Scalar {
214        self.phase.sample(time)
215    }
216
217    pub fn set(&mut self, value: bool) {
218        self.value = value;
219    }
220
221    pub fn process(&mut self, delta_time: Scalar) {
222        if self.playing {
223            let time_frame = self.phase.time_frame();
224            let time = if self.value {
225                let time = self.time + delta_time;
226                if time >= time_frame.end {
227                    self.playing = false;
228                }
229                time
230            } else {
231                let time = self.time - delta_time;
232                if time <= time_frame.start {
233                    self.playing = false;
234                }
235                time
236            };
237            self.time = time.max(time_frame.start).min(time_frame.end);
238        }
239    }
240}