polyhorn_ui/animation/mod.rs
1//! Types and traits for working with animations.
2
3use std::future::Future;
4use std::time::Duration;
5
6use crate::linalg::Transform3D;
7
8/// Single keyframe within a keyframe animation that describes the value of a
9/// property at a particular point in time.
10#[derive(Copy, Clone, Debug, PartialEq)]
11pub struct Keyframe<T> {
12 /// This is the time to which this keyframe applies. The time is relative to
13 /// the start of the animation, not to the start of time itself.
14 pub time: Duration,
15
16 /// This is the value that the property should have at this point in time.
17 pub value: T,
18}
19
20/// Collection of keyframes that make up an animation.
21#[derive(Clone, Debug, PartialEq)]
22pub struct KeyframeAnimation<T> {
23 /// This is the total duration of this animation.
24 pub duration: Duration,
25
26 /// These are the keyframes that make up this animation.
27 pub keyframes: Vec<Keyframe<T>>,
28}
29
30/// Animatable properties.
31#[derive(Clone, Debug, PartialEq)]
32pub enum Animation {
33 /// Animates the opacity property of a view.
34 Opacity(KeyframeAnimation<f32>),
35
36 /// Animates the transform property of a view.
37 Transform(KeyframeAnimation<Transform3D<f32>>),
38}
39
40/// Trait that should be implemented by animation handles that are returned by
41/// the animator trait's start function. This handle can be used to wait for an
42/// animation to complete (because it is a future) or cancel a pending animation
43/// by dropping it.
44///
45/// Note: the handle itself doesn't necessarily have to implement `Drop`, it
46/// might have a field that holds an internal representation that implements
47/// `Drop`. For example, on iOS the `AnimationHandle` has a field that holds a
48/// reference counted `PLYAnimationHandle` that is written in Objective-C. Once
49/// the reference count drops to zero and the Objective-C object is released, it
50/// will automatically remove the animation from its view.
51pub trait AnimationHandle: Future<Output = ()> + Send + Sync {}
52
53/// This trait should be implemented by types that schedule animations for
54/// objects that can be animated.
55pub trait Animator {
56 /// This is the handle that this animator returns and that can be used to
57 /// track pending animations.
58 type AnimationHandle: AnimationHandle;
59
60 /// This function should start the given animation and return a handle that
61 /// can be used to track and control its progress.
62 fn start(&mut self, animation: Animation) -> Self::AnimationHandle;
63}
64
65/// This trait is implemented by types that can be animated.
66pub trait Animatable {
67 /// This is the type that can schedule new animations for this object.
68 type Animator: Animator;
69
70 /// This is the command buffer that this object can piggy-back on.
71 type CommandBuffer;
72
73 /// This function should invoke the given callback with a mutable reference
74 /// to (a new instance of) this object's animator.
75 fn animate<F>(&mut self, animations: F)
76 where
77 F: FnOnce(&mut Self::Animator) + Send + 'static;
78
79 /// This function should invoke the given callback with a mutable reference
80 /// to (a new instance of) this object's animator that piggy-backs on the
81 /// given command buffer. Explicitly passing a command buffer ensures that
82 /// the animations are started in the same UI event loop iteration as the
83 /// current render itself.
84 fn animate_with_buffer<F>(&mut self, buffer: &mut Self::CommandBuffer, animations: F)
85 where
86 F: FnOnce(&mut Self::Animator) + Send + 'static;
87}