Skip to main content

Animation

Struct Animation 

Source
pub struct Animation { /* private fields */ }
Expand description

Small time-based animation helper.

Implementations§

Source§

impl Animation

Source

pub const fn new(duration_ms: u32, curve: Curve) -> Self

Creates a new animation with a duration and easing curve.

Examples found in repository?
src/modal.rs (line 34)
31    pub fn show(&mut self, modal: M) {
32        self.state = ModalState::Showing {
33            modal,
34            animation: Animation::new(MODAL_ANIMATION_MS, Curve::EaseInOut),
35        };
36    }
37
38    /// Starts dismissing the current modal, if any.
39    pub fn dismiss(&mut self) {
40        let modal = match self.state {
41            ModalState::Showing { modal, .. } | ModalState::Visible { modal } => Some(modal),
42            ModalState::Hiding { modal, .. } => Some(modal),
43            ModalState::Hidden => None,
44        };
45
46        if let Some(modal) = modal {
47            self.state = ModalState::Hiding {
48                modal,
49                animation: Animation::new(MODAL_ANIMATION_MS, Curve::EaseInOut),
50            };
51        }
52    }
More examples
Hide additional examples
src/stack.rs (line 123)
113    pub fn push(&mut self, key: K) -> Result<(), StackError> {
114        if self.transition.is_some() {
115            return Err(StackError::Busy);
116        }
117
118        let from = self.top();
119        self.stack.push(key).map_err(|_| StackError::Full)?;
120        self.transition = Some(Transition::Push {
121            from,
122            to: key,
123            animation: Animation::new(STACK_ANIMATION_MS, Curve::EaseInOut),
124        });
125        Ok(())
126    }
127
128    /// Pops the current view and starts a transition.
129    pub fn pop(&mut self) -> Result<K, StackError> {
130        if self.transition.is_some() {
131            return Err(StackError::Busy);
132        }
133        if self.stack.len() <= 1 {
134            return Err(StackError::RootLocked);
135        }
136
137        let from = self.stack.pop().ok_or(StackError::RootLocked)?;
138        let to = self.top();
139        self.transition = Some(Transition::Pop {
140            from,
141            to,
142            animation: Animation::new(STACK_ANIMATION_MS, Curve::EaseInOut),
143        });
144        Ok(from)
145    }
Source

pub const fn is_running(&self) -> bool

Returns true while the animation is still progressing.

Examples found in repository?
src/animation.rs (line 37)
36    pub const fn is_finished(&self) -> bool {
37        !self.is_running()
38    }
39
40    /// Advances the animation by `dt_ms`.
41    pub fn advance(&mut self, dt_ms: u32) -> bool {
42        self.elapsed_ms = self.elapsed_ms.saturating_add(dt_ms).min(self.duration_ms);
43        self.is_running()
44    }
More examples
Hide additional examples
src/stack.rs (line 155)
148    pub fn advance(&mut self, dt_ms: u32) -> bool {
149        let Some(mut transition) = self.transition.take() else {
150            return false;
151        };
152
153        let was_running = match &transition {
154            Transition::Push { animation, .. } | Transition::Pop { animation, .. } => {
155                animation.is_running()
156            }
157        };
158        let is_running = match &mut transition {
159            Transition::Push { animation, .. } | Transition::Pop { animation, .. } => {
160                animation.advance(dt_ms)
161            }
162        };
163
164        if is_running {
165            self.transition = Some(transition);
166        }
167
168        was_running
169    }
src/modal.rs (line 72)
68    pub fn advance(&mut self, dt_ms: u32) -> bool {
69        match &mut self.state {
70            ModalState::Hidden | ModalState::Visible { .. } => false,
71            ModalState::Showing { modal, animation } => {
72                let was_running = animation.is_running();
73                let is_running = animation.advance(dt_ms);
74                if is_running {
75                    true
76                } else {
77                    self.state = ModalState::Visible { modal: *modal };
78                    was_running
79                }
80            }
81            ModalState::Hiding { animation, .. } => {
82                let was_running = animation.is_running();
83                let is_running = animation.advance(dt_ms);
84                if is_running {
85                    true
86                } else {
87                    self.state = ModalState::Hidden;
88                    was_running
89                }
90            }
91        }
92    }
Source

pub const fn is_finished(&self) -> bool

Returns true once the animation has completed.

Source

pub fn advance(&mut self, dt_ms: u32) -> bool

Advances the animation by dt_ms.

Examples found in repository?
src/stack.rs (line 160)
148    pub fn advance(&mut self, dt_ms: u32) -> bool {
149        let Some(mut transition) = self.transition.take() else {
150            return false;
151        };
152
153        let was_running = match &transition {
154            Transition::Push { animation, .. } | Transition::Pop { animation, .. } => {
155                animation.is_running()
156            }
157        };
158        let is_running = match &mut transition {
159            Transition::Push { animation, .. } | Transition::Pop { animation, .. } => {
160                animation.advance(dt_ms)
161            }
162        };
163
164        if is_running {
165            self.transition = Some(transition);
166        }
167
168        was_running
169    }
More examples
Hide additional examples
src/modal.rs (line 73)
68    pub fn advance(&mut self, dt_ms: u32) -> bool {
69        match &mut self.state {
70            ModalState::Hidden | ModalState::Visible { .. } => false,
71            ModalState::Showing { modal, animation } => {
72                let was_running = animation.is_running();
73                let is_running = animation.advance(dt_ms);
74                if is_running {
75                    true
76                } else {
77                    self.state = ModalState::Visible { modal: *modal };
78                    was_running
79                }
80            }
81            ModalState::Hiding { animation, .. } => {
82                let was_running = animation.is_running();
83                let is_running = animation.advance(dt_ms);
84                if is_running {
85                    true
86                } else {
87                    self.state = ModalState::Hidden;
88                    was_running
89                }
90            }
91        }
92    }
Source

pub fn progress_permille(&self) -> u16

Returns eased progress in the 0..=1000 permille range.

Examples found in repository?
src/stack.rs (line 98)
88    pub(crate) fn header_transition(&self) -> Option<HeaderTransition<K>> {
89        match self.transition {
90            None => None,
91            Some(Transition::Push {
92                from,
93                to,
94                animation,
95            }) => Some(HeaderTransition::Push {
96                from,
97                to,
98                progress: animation.progress_permille(),
99            }),
100            Some(Transition::Pop {
101                from,
102                to,
103                animation,
104            }) => Some(HeaderTransition::Pop {
105                from,
106                to,
107                progress: animation.progress_permille(),
108            }),
109        }
110    }
111
112    /// Pushes `key` and starts a transition.
113    pub fn push(&mut self, key: K) -> Result<(), StackError> {
114        if self.transition.is_some() {
115            return Err(StackError::Busy);
116        }
117
118        let from = self.top();
119        self.stack.push(key).map_err(|_| StackError::Full)?;
120        self.transition = Some(Transition::Push {
121            from,
122            to: key,
123            animation: Animation::new(STACK_ANIMATION_MS, Curve::EaseInOut),
124        });
125        Ok(())
126    }
127
128    /// Pops the current view and starts a transition.
129    pub fn pop(&mut self) -> Result<K, StackError> {
130        if self.transition.is_some() {
131            return Err(StackError::Busy);
132        }
133        if self.stack.len() <= 1 {
134            return Err(StackError::RootLocked);
135        }
136
137        let from = self.stack.pop().ok_or(StackError::RootLocked)?;
138        let to = self.top();
139        self.transition = Some(Transition::Pop {
140            from,
141            to,
142            animation: Animation::new(STACK_ANIMATION_MS, Curve::EaseInOut),
143        });
144        Ok(from)
145    }
146
147    /// Advances the active transition, if any.
148    pub fn advance(&mut self, dt_ms: u32) -> bool {
149        let Some(mut transition) = self.transition.take() else {
150            return false;
151        };
152
153        let was_running = match &transition {
154            Transition::Push { animation, .. } | Transition::Pop { animation, .. } => {
155                animation.is_running()
156            }
157        };
158        let is_running = match &mut transition {
159            Transition::Push { animation, .. } | Transition::Pop { animation, .. } => {
160                animation.advance(dt_ms)
161            }
162        };
163
164        if is_running {
165            self.transition = Some(transition);
166        }
167
168        was_running
169    }
170
171    /// Returns the base and overlay layers for a frame.
172    pub fn layers(&self, frame: Rectangle) -> StackLayers<K> {
173        let width = frame.size.width as i32;
174        let idle = Layer::new(self.top(), frame, Point::zero());
175
176        match self.transition {
177            None => StackLayers {
178                base: idle,
179                overlay: None,
180            },
181            Some(Transition::Push {
182                from,
183                to,
184                animation,
185            }) => {
186                let progress = animation.progress_permille();
187                let base = Layer::new(from, frame, Point::zero());
188                let overlay = Layer::new(to, frame, Point::new(lerp_i32(width, 0, progress), 0));
189                StackLayers {
190                    base,
191                    overlay: Some(overlay),
192                }
193            }
194            Some(Transition::Pop {
195                from,
196                to,
197                animation,
198            }) => {
199                let progress = animation.progress_permille();
200                let base = Layer::new(to, frame, Point::zero());
201                let overlay = Layer::new(from, frame, Point::new(lerp_i32(0, width, progress), 0));
202                StackLayers {
203                    base,
204                    overlay: Some(overlay),
205                }
206            }
207        }
208    }
More examples
Hide additional examples
src/modal.rs (line 107)
100    pub fn current_with_panel(&self, bounds: Rectangle, panel: Rectangle) -> Option<ModalLayer<M>> {
101        let offscreen = offscreen_offset(bounds, panel);
102
103        match self.state {
104            ModalState::Hidden => None,
105            ModalState::Visible { modal } => Some(ModalLayer::new(modal, panel, 0, DIM_ALPHA_MAX)),
106            ModalState::Showing { modal, animation } => {
107                let progress = animation.progress_permille();
108                Some(ModalLayer::new(
109                    modal,
110                    panel,
111                    lerp_i32(offscreen, 0, progress),
112                    lerp_u8(0, DIM_ALPHA_MAX, progress),
113                ))
114            }
115            ModalState::Hiding { modal, animation } => {
116                let progress = animation.progress_permille();
117                Some(ModalLayer::new(
118                    modal,
119                    panel,
120                    lerp_i32(0, offscreen, progress),
121                    lerp_u8(DIM_ALPHA_MAX, 0, progress),
122                ))
123            }
124        }
125    }

Trait Implementations§

Source§

impl Clone for Animation

Source§

fn clone(&self) -> Animation

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Animation

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Animation

Source§

fn eq(&self, other: &Animation) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Animation

Source§

impl Eq for Animation

Source§

impl StructuralPartialEq for Animation

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.