1use simple_easing::*;
2
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[derive(Default, Clone, Copy, Debug, PartialEq)]
11pub enum Easing {
12 BackIn,
14 BackInOuT,
16 BackOut,
18 BounceIn,
20 BounceInOut,
22 BounceOut,
24 CircIn,
26 CircInOut,
28 CircOut,
30 CubicIn,
32 CubicInOut,
34 CubicOut,
36 ElasticIn,
38 ElasticInOut,
40 ElasticOut,
42 ExpoIn,
44 ExpoInOut,
46 ExpoOut,
48 #[default]
50 Linear,
51 QuadIn,
53 QuadInOut,
55 QuadOut,
57 QuartIn,
59 QuartInOut,
61 QuartOut,
63 QuintIn,
65 QuintInOut,
67 QuintOut,
69 Reverse,
71 RoundTrip,
73 SineIn,
75 SineInOut,
77 SineOut,
79}
80
81impl Easing {
82 pub(crate) fn call(&self, t: f32) -> f32 {
84 match self {
85 Easing::BackIn => back_in(t),
86 Easing::BackInOuT => back_in_out(t),
87 Easing::BackOut => back_out(t),
88 Easing::BounceIn => bounce_in(t),
89 Easing::BounceInOut => bounce_in_out(t),
90 Easing::BounceOut => bounce_out(t),
91 Easing::CircIn => circ_in(t),
92 Easing::CircInOut => circ_in_out(t),
93 Easing::CircOut => circ_out(t),
94 Easing::CubicIn => cubic_in(t),
95 Easing::CubicInOut => cubic_in_out(t),
96 Easing::CubicOut => cubic_out(t),
97 Easing::ElasticIn => elastic_in(t),
98 Easing::ElasticInOut => elastic_in_out(t),
99 Easing::ElasticOut => elastic_out(t),
100 Easing::ExpoIn => expo_in(t),
101 Easing::ExpoInOut => expo_in_out(t),
102 Easing::ExpoOut => expo_out(t),
103 Easing::Linear => t,
104 Easing::QuadIn => quad_in(t),
105 Easing::QuadInOut => quad_in_out(t),
106 Easing::QuadOut => quad_out(t),
107 Easing::QuartIn => quart_in(t),
108 Easing::QuartInOut => quart_in_out(t),
109 Easing::QuartOut => quart_out(t),
110 Easing::QuintIn => quint_in(t),
111 Easing::QuintInOut => quint_in_out(t),
112 Easing::QuintOut => quint_out(t),
113 Easing::Reverse => reverse(t),
114 Easing::RoundTrip => roundtrip(t),
115 Easing::SineIn => sine_in(t),
116 Easing::SineInOut => sine_in_out(t),
117 Easing::SineOut => sine_out(t),
118 }
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 fn assert_easing_approx_equal(easing: Easing, input: f32, expected: f32) {
127 let result = easing.call(input);
128 assert!(
129 (result - expected).abs() < 1e-6,
130 "Expected {}, got {}",
131 expected,
132 result
133 );
134 }
135
136 #[test]
137 fn test_back_in() {
138 assert_easing_approx_equal(Easing::BackIn, 0.0, 0.0);
139 assert_easing_approx_equal(Easing::BackIn, 0.5, -0.0876975);
140 assert_easing_approx_equal(Easing::BackIn, 1.0, 1.0);
141 }
142
143 #[test]
144 fn test_back_in_out() {
145 assert_easing_approx_equal(Easing::BackInOuT, 0.0, 0.0);
146 assert_easing_approx_equal(Easing::BackInOuT, 0.2, -0.092556);
147 assert_easing_approx_equal(Easing::BackInOuT, 0.5, 0.5);
148 assert_easing_approx_equal(Easing::BackInOuT, 0.8, 1.0925556);
149 assert_easing_approx_equal(Easing::BackInOuT, 1.0, 1.0);
150 }
151
152 #[test]
153 fn test_back_out() {
154 assert_easing_approx_equal(Easing::BackOut, 0.0, 0.0);
155 assert_easing_approx_equal(Easing::BackOut, 0.5, 1.0876975);
156 assert_easing_approx_equal(Easing::BackOut, 1.0, 1.0);
157 }
158
159 #[test]
160 fn test_bounce_in() {
161 assert_easing_approx_equal(Easing::BounceIn, 0.0, 0.0);
162 assert_easing_approx_equal(Easing::BounceIn, 0.5, 0.234375);
163 assert_easing_approx_equal(Easing::BounceIn, 1.0, 1.0);
164 }
165
166 #[test]
167 fn test_bounce_in_out() {
168 assert_easing_approx_equal(Easing::BounceInOut, 0.0, 0.0);
169 assert_easing_approx_equal(Easing::BounceInOut, 0.2, 0.113750);
170 assert_easing_approx_equal(Easing::BounceInOut, 0.5, 0.5);
171 assert_easing_approx_equal(Easing::BounceInOut, 0.8, 0.88625);
172 assert_easing_approx_equal(Easing::BounceInOut, 1.0, 1.0);
173 }
174
175 #[test]
176 fn test_bounce_out() {
177 assert_easing_approx_equal(Easing::BounceOut, 0.0, 0.0);
178 assert_easing_approx_equal(Easing::BounceOut, 0.5, 0.765625);
179 assert_easing_approx_equal(Easing::BounceOut, 1.0, 1.0);
180 }
181
182 #[test]
183 fn test_circ_in() {
184 assert_easing_approx_equal(Easing::CircIn, 0.0, 0.0);
185 assert_easing_approx_equal(Easing::CircIn, 0.5, 0.133975);
186 assert_easing_approx_equal(Easing::CircIn, 1.0, 1.0);
187 }
188
189 #[test]
190 fn test_circ_in_out() {
191 assert_easing_approx_equal(Easing::CircInOut, 0.0, 0.0);
192 assert_easing_approx_equal(Easing::CircInOut, 0.2, 0.041742);
193 assert_easing_approx_equal(Easing::CircInOut, 0.5, 0.5);
194 assert_easing_approx_equal(Easing::CircInOut, 0.8, 0.958257);
195 assert_easing_approx_equal(Easing::CircInOut, 1.0, 1.0);
196 }
197
198 #[test]
199 fn test_circ_out() {
200 assert_easing_approx_equal(Easing::CircOut, 0.0, 0.0);
201 assert_easing_approx_equal(Easing::CircOut, 0.5, 0.866025);
202 assert_easing_approx_equal(Easing::CircOut, 1.0, 1.0);
203 }
204
205 #[test]
206 fn test_cubic_in() {
207 assert_easing_approx_equal(Easing::CubicIn, 0.0, 0.0);
208 assert_easing_approx_equal(Easing::CubicIn, 0.5, 0.125);
209 assert_easing_approx_equal(Easing::CubicIn, 1.0, 1.0);
210 }
211
212 #[test]
213 fn test_cubic_in_out() {
214 assert_easing_approx_equal(Easing::CubicInOut, 0.0, 0.0);
215 assert_easing_approx_equal(Easing::CubicInOut, 0.2, 0.032);
216 assert_easing_approx_equal(Easing::CubicInOut, 0.5, 0.5);
217 assert_easing_approx_equal(Easing::CubicInOut, 0.8, 0.968);
218 assert_easing_approx_equal(Easing::CubicInOut, 1.0, 1.0);
219 }
220
221 #[test]
222 fn test_cubic_out() {
223 assert_easing_approx_equal(Easing::CubicOut, 0.0, 0.0);
224 assert_easing_approx_equal(Easing::CubicOut, 0.5, 0.875);
225 assert_easing_approx_equal(Easing::CubicOut, 1.0, 1.0);
226 }
227
228 #[test]
229 fn test_elastic_in() {
230 assert_easing_approx_equal(Easing::ElasticIn, 0.0, 0.0);
231 assert_easing_approx_equal(Easing::ElasticIn, 0.5, -0.015625);
232 assert_easing_approx_equal(Easing::ElasticIn, 1.0, 1.0);
233 }
234
235 #[test]
236 fn test_elastic_in_out() {
237 assert_easing_approx_equal(Easing::ElasticInOut, 0.0, 0.0);
238 assert_easing_approx_equal(Easing::ElasticInOut, 0.2, -0.003906);
239 assert_easing_approx_equal(Easing::ElasticInOut, 0.5, 0.5);
240 assert_easing_approx_equal(Easing::ElasticInOut, 0.8, 1.0039063);
241 assert_easing_approx_equal(Easing::ElasticInOut, 1.0, 1.0);
242 }
243
244 #[test]
245 fn test_elastic_out() {
246 assert_easing_approx_equal(Easing::ElasticOut, 0.0, 0.0);
247 assert_easing_approx_equal(Easing::ElasticOut, 0.5, 1.015625);
248 assert_easing_approx_equal(Easing::ElasticOut, 1.0, 1.0);
249 }
250
251 #[test]
252 fn test_expo_in() {
253 assert_easing_approx_equal(Easing::ExpoIn, 0.0, 0.0);
254 assert_easing_approx_equal(Easing::ExpoIn, 0.5, 0.03125);
255 assert_easing_approx_equal(Easing::ExpoIn, 1.0, 1.0);
256 }
257
258 #[test]
259 fn test_expo_in_out() {
260 assert_easing_approx_equal(Easing::ExpoInOut, 0.0, 0.0);
261 assert_easing_approx_equal(Easing::ExpoInOut, 0.2, 0.007812);
262 assert_easing_approx_equal(Easing::ExpoInOut, 0.5, 0.5);
263 assert_easing_approx_equal(Easing::ExpoInOut, 0.8, 0.992187);
264 assert_easing_approx_equal(Easing::ExpoInOut, 1.0, 1.0);
265 }
266
267 #[test]
268 fn test_expo_out() {
269 assert_easing_approx_equal(Easing::ExpoOut, 0.0, 0.0);
270 assert_easing_approx_equal(Easing::ExpoOut, 0.5, 0.96875);
271 assert_easing_approx_equal(Easing::ExpoOut, 1.0, 1.0);
272 }
273
274 #[test]
275 fn test_linear() {
276 assert_easing_approx_equal(Easing::Linear, 0.0, 0.0);
277 assert_easing_approx_equal(Easing::Linear, 0.5, 0.5);
278 assert_easing_approx_equal(Easing::Linear, 1.0, 1.0);
279 }
280
281 #[test]
282 fn test_quad_in() {
283 assert_easing_approx_equal(Easing::QuadIn, 0.0, 0.0);
284 assert_easing_approx_equal(Easing::QuadIn, 0.5, 0.25);
285 assert_easing_approx_equal(Easing::QuadIn, 1.0, 1.0);
286 }
287
288 #[test]
289 fn test_quad_in_out() {
290 assert_easing_approx_equal(Easing::QuadInOut, 0.0, 0.0);
291 assert_easing_approx_equal(Easing::QuadInOut, 0.2, 0.08000);
292 assert_easing_approx_equal(Easing::QuadInOut, 0.5, 0.5);
293 assert_easing_approx_equal(Easing::QuadInOut, 0.8, 0.92);
294 assert_easing_approx_equal(Easing::QuadInOut, 1.0, 1.0);
295 }
296
297 #[test]
298 fn test_quad_out() {
299 assert_easing_approx_equal(Easing::QuadOut, 0.0, 0.0);
300 assert_easing_approx_equal(Easing::QuadOut, 0.5, 0.75);
301 assert_easing_approx_equal(Easing::QuadOut, 1.0, 1.0);
302 }
303
304 #[test]
305 fn test_quart_in() {
306 assert_easing_approx_equal(Easing::QuartIn, 0.0, 0.0);
307 assert_easing_approx_equal(Easing::QuartIn, 0.5, 0.0625);
308 assert_easing_approx_equal(Easing::QuartIn, 1.0, 1.0);
309 }
310
311 #[test]
312 fn test_quart_in_out() {
313 assert_easing_approx_equal(Easing::QuartInOut, 0.0, 0.0);
314 assert_easing_approx_equal(Easing::QuartInOut, 0.2, 0.0128);
315 assert_easing_approx_equal(Easing::QuartInOut, 0.5, 0.5);
316 assert_easing_approx_equal(Easing::QuartInOut, 0.8, 0.9872);
317 assert_easing_approx_equal(Easing::QuartInOut, 1.0, 1.0);
318 }
319
320 #[test]
321 fn test_quart_out() {
322 assert_easing_approx_equal(Easing::QuartOut, 0.0, 0.0);
323 assert_easing_approx_equal(Easing::QuartOut, 0.5, 0.9375);
324 assert_easing_approx_equal(Easing::QuartOut, 1.0, 1.0);
325 }
326
327 #[test]
328 fn test_quint_in() {
329 assert_easing_approx_equal(Easing::QuintIn, 0.0, 0.0);
330 assert_easing_approx_equal(Easing::QuintIn, 0.5, 0.0625);
331 assert_easing_approx_equal(Easing::QuintIn, 1.0, 1.0);
332 }
333
334 #[test]
335 fn test_quint_in_out() {
336 assert_easing_approx_equal(Easing::QuintInOut, 0.0, 0.0);
337 assert_easing_approx_equal(Easing::QuintInOut, 0.2, 0.00512);
338 assert_easing_approx_equal(Easing::QuintInOut, 0.5, 0.5);
339 assert_easing_approx_equal(Easing::QuintInOut, 0.8, 0.99488);
340 assert_easing_approx_equal(Easing::QuintInOut, 1.0, 1.0);
341 }
342
343 #[test]
344 fn test_quint_out() {
345 assert_easing_approx_equal(Easing::QuintOut, 0.0, 0.0);
346 assert_easing_approx_equal(Easing::QuintOut, 0.5, 0.96875);
347 assert_easing_approx_equal(Easing::QuintOut, 1.0, 1.0);
348 }
349
350 #[test]
351 fn test_reverse() {
352 assert_eq!(Easing::Reverse.call(0.0), 1.0);
353 assert_eq!(Easing::Reverse.call(0.5), 0.5);
354 assert_eq!(Easing::Reverse.call(1.0), 0.0);
355 }
356
357 #[test]
358 fn test_roundtrip() {
359 assert_eq!(Easing::RoundTrip.call(0.0), 0.0);
360 assert_eq!(Easing::RoundTrip.call(0.5), 1.0);
361 assert_eq!(Easing::RoundTrip.call(1.0), 0.0);
362 }
363
364 #[test]
365 fn test_sine_in() {
366 assert_easing_approx_equal(Easing::SineIn, 0.0, 0.0);
367 assert_easing_approx_equal(Easing::SineIn, 0.5, 0.292893);
368 assert_easing_approx_equal(Easing::SineIn, 1.0, 1.0);
369 }
370
371 #[test]
372 fn test_sine_in_out() {
373 assert_easing_approx_equal(Easing::SineInOut, 0.0, 0.0);
374 assert_easing_approx_equal(Easing::SineInOut, 0.2, 0.0954915);
375 assert_easing_approx_equal(Easing::SineInOut, 0.5, 0.5);
376 assert_easing_approx_equal(Easing::SineInOut, 0.8, 0.9045085);
377 assert_easing_approx_equal(Easing::SineInOut, 1.0, 1.0);
378 }
379
380 #[test]
381 fn test_sine_out() {
382 assert_easing_approx_equal(Easing::SineOut, 0.0, 0.0);
383 assert_easing_approx_equal(Easing::SineOut, 0.5, std::f32::consts::FRAC_1_SQRT_2);
384 assert_easing_approx_equal(Easing::SineOut, 1.0, 1.0);
385 }
386}