1use std::fmt::{self, Debug};
4use std::marker::PhantomData;
5use std::rc::Rc;
6
7use inset_embedder::{Color, Offset, Rect, Size};
8use inset_foundation::{App, Handle, Listener, RetainedHandle};
9
10use crate::animation::{Animation, AnimationStatus, AnimationStatusListener, AnyAnimation};
11use crate::curves::Curve;
12
13pub trait Animatable<T> {
21 fn transform(&self, app: &App, t: f64) -> T;
26
27 fn evaluate(&self, app: &App, animation: AnyAnimation<f64>) -> T
36 where
37 Self: Sized,
38 {
39 self.transform(app, animation.value(app))
40 }
41
42 fn animate(self, app: &mut App, parent: AnyAnimation<f64>) -> AnyAnimation<T>
45 where
46 Self: Sized + Clone + 'static,
47 T: 'static,
48 {
49 let parent = app.retain(parent);
50 app.create(AnimatedEvaluation {
51 parent,
52 evaluatable: self,
53 _value: PhantomData,
54 })
55 .as_animation()
56 }
57
58 fn chain<P>(self, parent: P) -> ChainedEvaluation<P, Self>
62 where
63 Self: Sized + Clone,
64 P: Animatable<f64> + Clone,
65 {
66 ChainedEvaluation {
67 parent,
68 evaluatable: self,
69 }
70 }
71}
72
73#[derive(Clone)]
75pub struct CallbackAnimatable<T> {
76 callback: Rc<dyn Fn(f64) -> T>,
77}
78
79impl<T> CallbackAnimatable<T> {
80 pub fn from_callback(callback: impl Fn(f64) -> T + 'static) -> CallbackAnimatable<T> {
82 CallbackAnimatable {
83 callback: Rc::new(callback),
84 }
85 }
86}
87
88impl<T> Animatable<T> for CallbackAnimatable<T> {
89 fn transform(&self, _app: &App, t: f64) -> T {
90 (self.callback)(t)
91 }
92}
93
94impl<T> Debug for CallbackAnimatable<T> {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 f.write_str("CallbackAnimatable")
97 }
98}
99
100struct AnimatedEvaluation<T, A> {
103 parent: RetainedHandle<AnyAnimation<f64>>,
104 evaluatable: A,
105 _value: PhantomData<fn() -> T>,
106}
107
108impl<T: 'static, A: Animatable<T> + Clone + 'static> Animation<T> for AnimatedEvaluation<T, A> {
109 fn add_listener(self: Handle<Self>, app: &mut App, listener: Listener) {
110 app.get(self).parent.add_listener(app, listener);
111 }
112
113 fn remove_listener(self: Handle<Self>, app: &mut App, listener: &Listener) {
114 app.get(self).parent.remove_listener(app, listener);
115 }
116
117 fn add_status_listener(self: Handle<Self>, app: &mut App, listener: AnimationStatusListener) {
118 app.get(self).parent.add_status_listener(app, listener);
119 }
120
121 fn remove_status_listener(
122 self: Handle<Self>,
123 app: &mut App,
124 listener: &AnimationStatusListener,
125 ) {
126 app.get(self).parent.remove_status_listener(app, listener);
127 }
128
129 fn status(self: Handle<Self>, app: &App) -> AnimationStatus {
130 app.get(self).parent.status(app)
131 }
132
133 fn value(self: Handle<Self>, app: &App) -> T {
134 let parent = app.get(self).parent.get();
135 let evaluatable = app.get(self).evaluatable.clone();
136 evaluatable.evaluate(app, parent)
137 }
138}
139
140#[derive(Clone)]
142pub struct ChainedEvaluation<P, C> {
143 parent: P,
144 evaluatable: C,
145}
146
147impl<P: Animatable<f64>, C: Animatable<T>, T> Animatable<T> for ChainedEvaluation<P, C> {
148 fn transform(&self, app: &App, t: f64) -> T {
149 self.evaluatable
150 .transform(app, self.parent.transform(app, t))
151 }
152}
153
154impl<P: Debug, C: Debug> Debug for ChainedEvaluation<P, C> {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 write!(f, "{:?}\u{27A9}{:?}", self.parent, self.evaluatable)
157 }
158}
159
160pub trait TweenLerp: Clone {
166 fn lerp(begin: &Self, end: &Self, t: f64) -> Self;
168}
169
170impl TweenLerp for f64 {
171 fn lerp(begin: &f64, end: &f64, t: f64) -> f64 {
172 begin + (end - begin) * t
173 }
174}
175
176impl TweenLerp for Offset {
177 fn lerp(begin: &Offset, end: &Offset, t: f64) -> Offset {
178 *begin + (*end - *begin) * t
179 }
180}
181
182impl TweenLerp for Size {
183 fn lerp(begin: &Size, end: &Size, t: f64) -> Size {
184 *begin + (*end - *begin) * t
186 }
187}
188
189#[derive(Debug)]
197pub struct Tween<T> {
198 pub begin: Option<T>,
200
201 pub end: Option<T>,
203}
204
205impl<T: 'static> Tween<T> {
206 pub fn new(app: &mut App, begin: Option<T>, end: Option<T>) -> Handle<Tween<T>> {
215 app.create(Tween { begin, end })
216 }
217
218 pub fn begin(self: Handle<Self>, app: &App) -> Option<&T> {
220 app.get(self).begin.as_ref()
221 }
222
223 pub fn set_begin(self: Handle<Self>, app: &mut App, begin: Option<T>) {
225 app.get_mut(self).begin = begin;
226 }
227
228 pub fn end(self: Handle<Self>, app: &App) -> Option<&T> {
230 app.get(self).end.as_ref()
231 }
232
233 pub fn set_end(self: Handle<Self>, app: &mut App, end: Option<T>) {
235 app.get_mut(self).end = end;
236 }
237}
238
239fn tween_transform<T: Clone>(
240 begin: &Option<T>,
241 end: &Option<T>,
242 t: f64,
243 lerp: impl FnOnce(f64) -> T,
244) -> T {
245 if t == 0.0 {
246 return begin.clone().expect("Tween.begin must be set before use");
247 }
248 if t == 1.0 {
249 return end.clone().expect("Tween.end must be set before use");
250 }
251 lerp(t)
252}
253
254impl<T: TweenLerp + 'static> Tween<T> {
255 pub fn lerp(self: Handle<Self>, app: &App, t: f64) -> T {
257 let tween = app.get(self);
258 let begin = tween
259 .begin
260 .as_ref()
261 .expect("Tween.begin must be set before use");
262 let end = tween
263 .end
264 .as_ref()
265 .expect("Tween.end must be set before use");
266 T::lerp(begin, end, t)
267 }
268}
269
270impl<T: TweenLerp + 'static> Animatable<T> for Handle<Tween<T>> {
271 fn transform(&self, app: &App, t: f64) -> T {
272 let this = *self;
273 let tween = app.get(this);
274 tween_transform(&tween.begin, &tween.end, t, |t| this.lerp(app, t))
275 }
276}
277
278pub struct ReverseTween<T: 'static> {
282 parent: Handle<Tween<T>>,
283}
284
285impl<T: TweenLerp + 'static> ReverseTween<T> {
286 pub fn new(app: &mut App, parent: Handle<Tween<T>>) -> Handle<ReverseTween<T>> {
288 app.create(ReverseTween { parent })
289 }
290
291 pub fn parent(self: Handle<Self>, app: &App) -> Handle<Tween<T>> {
293 app.get(self).parent
294 }
295}
296
297impl<T: TweenLerp + 'static> Animatable<T> for Handle<ReverseTween<T>> {
298 fn transform(&self, app: &App, t: f64) -> T {
299 let this = *self;
300 this.parent(app).lerp(app, 1.0 - t)
301 }
302}
303
304pub struct ColorTween {
306 pub begin: Option<Color>,
308
309 pub end: Option<Color>,
311}
312
313impl ColorTween {
314 pub fn new(app: &mut App, begin: Option<Color>, end: Option<Color>) -> Handle<ColorTween> {
319 app.create(ColorTween { begin, end })
320 }
321
322 pub fn begin(self: Handle<Self>, app: &App) -> Option<Color> {
324 app.get(self).begin
325 }
326
327 pub fn set_begin(self: Handle<Self>, app: &mut App, begin: Option<Color>) {
329 app.get_mut(self).begin = begin;
330 }
331
332 pub fn end(self: Handle<Self>, app: &App) -> Option<Color> {
334 app.get(self).end
335 }
336
337 pub fn set_end(self: Handle<Self>, app: &mut App, end: Option<Color>) {
339 app.get_mut(self).end = end;
340 }
341
342 pub fn lerp(self: Handle<Self>, app: &App, t: f64) -> Option<Color> {
344 let tween = app.get(self);
345 Color::lerp(tween.begin, tween.end, t)
346 }
347}
348
349impl Animatable<Option<Color>> for Handle<ColorTween> {
350 fn transform(&self, app: &App, t: f64) -> Option<Color> {
351 let this = *self;
352 if t == 0.0 {
353 return this.begin(app);
354 }
355 if t == 1.0 {
356 return this.end(app);
357 }
358 this.lerp(app, t)
359 }
360}
361
362pub struct SizeTween {
364 pub begin: Option<Size>,
366
367 pub end: Option<Size>,
369}
370
371impl SizeTween {
372 pub fn new(app: &mut App, begin: Option<Size>, end: Option<Size>) -> Handle<SizeTween> {
374 app.create(SizeTween { begin, end })
375 }
376
377 pub fn lerp(self: Handle<Self>, app: &App, t: f64) -> Option<Size> {
379 let tween = app.get(self);
380 Size::lerp(tween.begin, tween.end, t)
381 }
382}
383
384impl Animatable<Option<Size>> for Handle<SizeTween> {
385 fn transform(&self, app: &App, t: f64) -> Option<Size> {
386 let this = *self;
387 let tween = app.get(this);
388 if t == 0.0 {
389 return tween.begin;
390 }
391 if t == 1.0 {
392 return tween.end;
393 }
394 this.lerp(app, t)
395 }
396}
397
398pub struct RectTween {
400 pub begin: Option<Rect>,
402
403 pub end: Option<Rect>,
405}
406
407impl RectTween {
408 pub fn new(app: &mut App, begin: Option<Rect>, end: Option<Rect>) -> Handle<RectTween> {
410 app.create(RectTween { begin, end })
411 }
412
413 pub fn lerp(self: Handle<Self>, app: &App, t: f64) -> Option<Rect> {
415 let tween = app.get(self);
416 Rect::lerp(tween.begin, tween.end, t)
417 }
418}
419
420impl Animatable<Option<Rect>> for Handle<RectTween> {
421 fn transform(&self, app: &App, t: f64) -> Option<Rect> {
422 let this = *self;
423 let tween = app.get(this);
424 if t == 0.0 {
425 return tween.begin;
426 }
427 if t == 1.0 {
428 return tween.end;
429 }
430 this.lerp(app, t)
431 }
432}
433
434pub struct IntTween {
436 pub begin: Option<i64>,
438
439 pub end: Option<i64>,
441}
442
443impl IntTween {
444 pub fn new(app: &mut App, begin: Option<i64>, end: Option<i64>) -> Handle<IntTween> {
446 app.create(IntTween { begin, end })
447 }
448
449 pub fn lerp(self: Handle<Self>, app: &App, t: f64) -> i64 {
451 let tween = app.get(self);
452 let begin = tween.begin.expect("IntTween.begin must be set before use");
453 let end = tween.end.expect("IntTween.end must be set before use");
454 (begin as f64 + (end - begin) as f64 * t).round() as i64
455 }
456}
457
458impl Animatable<i64> for Handle<IntTween> {
459 fn transform(&self, app: &App, t: f64) -> i64 {
460 let this = *self;
461 let tween = app.get(this);
462 tween_transform(&tween.begin, &tween.end, t, |t| this.lerp(app, t))
463 }
464}
465
466pub struct StepTween {
468 pub begin: Option<i64>,
470
471 pub end: Option<i64>,
473}
474
475impl StepTween {
476 pub fn new(app: &mut App, begin: Option<i64>, end: Option<i64>) -> Handle<StepTween> {
478 app.create(StepTween { begin, end })
479 }
480
481 pub fn lerp(self: Handle<Self>, app: &App, t: f64) -> i64 {
483 let tween = app.get(self);
484 let begin = tween.begin.expect("StepTween.begin must be set before use");
485 let end = tween.end.expect("StepTween.end must be set before use");
486 (begin as f64 + (end - begin) as f64 * t).floor() as i64
487 }
488}
489
490impl Animatable<i64> for Handle<StepTween> {
491 fn transform(&self, app: &App, t: f64) -> i64 {
492 let this = *self;
493 let tween = app.get(this);
494 tween_transform(&tween.begin, &tween.end, t, |t| this.lerp(app, t))
495 }
496}
497
498pub struct ConstantTween<T> {
500 tween: Tween<T>,
503}
504
505impl<T: Clone + 'static> ConstantTween<T> {
506 pub fn new(app: &mut App, value: T) -> Handle<ConstantTween<T>> {
508 app.create(ConstantTween {
509 tween: Tween {
510 begin: Some(value.clone()),
511 end: Some(value),
512 },
513 })
514 }
515}
516
517impl<T: Clone + 'static> Animatable<T> for Handle<ConstantTween<T>> {
518 fn transform(&self, app: &App, _t: f64) -> T {
519 app.get(*self)
520 .tween
521 .begin
522 .clone()
523 .expect("ConstantTween.begin must be set")
524 }
525}
526
527#[derive(Debug)]
529pub struct CurveTween {
530 pub curve: Rc<dyn Curve>,
532}
533
534impl CurveTween {
535 pub fn new(app: &mut App, curve: Rc<dyn Curve>) -> Handle<CurveTween> {
537 app.create(CurveTween { curve })
538 }
539
540 pub fn curve(self: Handle<Self>, app: &App) -> Rc<dyn Curve> {
542 Rc::clone(&app.get(self).curve)
543 }
544
545 pub fn set_curve(self: Handle<Self>, app: &mut App, curve: Rc<dyn Curve>) {
547 app.get_mut(self).curve = curve;
548 }
549}
550
551impl Animatable<f64> for Handle<CurveTween> {
552 fn transform(&self, app: &App, t: f64) -> f64 {
553 let curve = &app.get(*self).curve;
554 if t == 0.0 || t == 1.0 {
555 debug_assert_eq!(curve.transform(t).round(), t);
556 return t;
557 }
558 curve.transform(t)
559 }
560}
561
562#[cfg(test)]
563mod tests {
564 use super::*;
565 use crate::animation::Animation;
566 use crate::animations::AlwaysStoppedAnimation;
567 use inset_foundation::AppCell;
568
569 #[test]
570 fn a_driven_tween_sees_end_assigned_after_animate() {
571 let cell = AppCell::new();
572 let mut app = cell.borrow_mut();
573 let tween = Tween::new(&mut app, Some(0.0), Some(1.0));
574 let parent = app.create(AlwaysStoppedAnimation::new(1.0)).as_animation();
575 let driven = tween.animate(&mut app, parent);
576
577 assert_eq!(driven.value(&app), 1.0);
578 tween.set_end(&mut app, Some(0.4));
579 assert_eq!(driven.value(&app), 0.4);
580 }
581
582 #[test]
583 fn lerp_walks_the_line() {
584 let cell = AppCell::new();
585 let mut app = cell.borrow_mut();
586 let tween = Tween::new(&mut app, Some(0.0), Some(10.0));
587 assert_eq!(tween.transform(&app, 0.0), 0.0);
588 assert_eq!(tween.transform(&app, 0.25), 2.5);
589 assert_eq!(tween.transform(&app, 1.0), 10.0);
590 }
591
592 #[test]
593 fn an_offset_tween_walks_both_axes() {
594 let cell = AppCell::new();
595 let mut app = cell.borrow_mut();
596 let tween = Tween::new(
597 &mut app,
598 Some(Offset::new(0.0, 10.0)),
599 Some(Offset::new(4.0, -10.0)),
600 );
601 assert_eq!(tween.transform(&app, 0.0), Offset::new(0.0, 10.0));
602 assert_eq!(tween.transform(&app, 0.25), Offset::new(1.0, 5.0));
603 assert_eq!(tween.transform(&app, 1.0), Offset::new(4.0, -10.0));
604 }
605
606 #[test]
607 fn a_size_tween_walks_both_dimensions() {
608 let cell = AppCell::new();
609 let mut app = cell.borrow_mut();
610 let tween = Tween::new(
611 &mut app,
612 Some(Size::new(10.0, 20.0)),
613 Some(Size::new(20.0, 0.0)),
614 );
615 assert_eq!(tween.transform(&app, 0.5), Size::new(15.0, 10.0));
616 }
617}