inset_rendering/
tweens.rs1use inset_animation::Animatable;
4use inset_foundation::App;
5use inset_painting::{Alignment, AlignmentGeometry, FractionalOffset};
6
7#[derive(Clone, Debug)]
23pub struct FractionalOffsetTween {
24 pub begin: Option<FractionalOffset>,
26
27 pub end: Option<FractionalOffset>,
29}
30
31impl FractionalOffsetTween {
32 pub fn new(
37 begin: Option<FractionalOffset>,
38 end: Option<FractionalOffset>,
39 ) -> FractionalOffsetTween {
40 FractionalOffsetTween { begin, end }
41 }
42
43 pub fn lerp(&self, t: f64) -> Option<FractionalOffset> {
45 FractionalOffset::lerp(self.begin, self.end, t)
46 }
47}
48
49impl Animatable<Option<FractionalOffset>> for FractionalOffsetTween {
50 fn transform(&self, _app: &App, t: f64) -> Option<FractionalOffset> {
51 if t == 0.0 {
52 return self.begin;
53 }
54 if t == 1.0 {
55 return self.end;
56 }
57 self.lerp(t)
58 }
59}
60
61#[derive(Clone, Debug)]
76pub struct AlignmentTween {
77 pub begin: Option<Alignment>,
79
80 pub end: Option<Alignment>,
82}
83
84impl AlignmentTween {
85 pub fn new(begin: Option<Alignment>, end: Option<Alignment>) -> AlignmentTween {
90 AlignmentTween { begin, end }
91 }
92
93 pub fn lerp(&self, t: f64) -> Alignment {
95 Alignment::lerp(self.begin, self.end, t)
96 .expect("AlignmentTween.begin or end must be set before use")
97 }
98}
99
100impl Animatable<Alignment> for AlignmentTween {
101 fn transform(&self, _app: &App, t: f64) -> Alignment {
102 if t == 0.0 {
103 return self.begin.expect("Tween.begin must be set before use");
104 }
105 if t == 1.0 {
106 return self.end.expect("Tween.end must be set before use");
107 }
108 self.lerp(t)
109 }
110}
111
112#[derive(Clone, Debug)]
126pub struct AlignmentGeometryTween {
127 pub begin: Option<AlignmentGeometry>,
129
130 pub end: Option<AlignmentGeometry>,
132}
133
134impl AlignmentGeometryTween {
135 pub fn new(
140 begin: Option<AlignmentGeometry>,
141 end: Option<AlignmentGeometry>,
142 ) -> AlignmentGeometryTween {
143 AlignmentGeometryTween { begin, end }
144 }
145
146 pub fn lerp(&self, t: f64) -> Option<AlignmentGeometry> {
148 AlignmentGeometry::lerp(self.begin, self.end, t)
149 }
150}
151
152impl Animatable<Option<AlignmentGeometry>> for AlignmentGeometryTween {
153 fn transform(&self, _app: &App, t: f64) -> Option<AlignmentGeometry> {
154 if t == 0.0 {
155 return self.begin;
156 }
157 if t == 1.0 {
158 return self.end;
159 }
160 self.lerp(t)
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use inset_foundation::AppCell;
167 use inset_painting::{AlignmentDirectional, TextDirection};
168
169 use super::*;
170
171 #[test]
172 fn an_alignment_tween_walks_between_the_corners() {
173 let cell = AppCell::new();
174 let app = cell.borrow();
175 let tween = AlignmentTween::new(Some(Alignment::TOP_LEFT), Some(Alignment::BOTTOM_LEFT));
176 assert_eq!(tween.transform(&app, 0.0), Alignment::TOP_LEFT);
177 assert_eq!(tween.transform(&app, 0.5), Alignment::CENTER_LEFT);
178 assert_eq!(tween.transform(&app, 1.0), Alignment::BOTTOM_LEFT);
179 }
180
181 #[test]
182 fn an_alignment_geometry_tween_crosses_the_two_kinds() {
183 let cell = AppCell::new();
184 let app = cell.borrow();
185 let tween = AlignmentGeometryTween::new(
186 Some(Alignment::CENTER_RIGHT.into()),
187 Some(AlignmentDirectional::CENTER_END.into()),
188 );
189 let halfway = tween.transform(&app, 0.5).expect("both ends are set");
190 assert_eq!(
191 halfway.resolve(Some(TextDirection::Ltr)),
192 Alignment::CENTER_RIGHT
193 );
194 assert_eq!(halfway.resolve(Some(TextDirection::Rtl)), Alignment::CENTER);
195 }
196
197 #[test]
198 fn a_fractional_offset_tween_walks_between_the_corners() {
199 let cell = AppCell::new();
200 let app = cell.borrow();
201 let tween = FractionalOffsetTween::new(
202 Some(FractionalOffset::new(0.0, 0.0)),
203 Some(FractionalOffset::new(1.0, 1.0)),
204 );
205 assert_eq!(
206 tween.transform(&app, 0.25),
207 Some(FractionalOffset::new(0.25, 0.25))
208 );
209 }
210}