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}