mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-12 17:48:09 +00:00
63 lines
1.7 KiB
Rust
63 lines
1.7 KiB
Rust
use crate::{
|
|
time::{Duration, Instant},
|
|
ui::lerp::{InvLerp, Lerp},
|
|
};
|
|
|
|
/// Running, time-based linear progression of a value.
|
|
pub struct Animation<T> {
|
|
/// Starting value.
|
|
pub from: T,
|
|
/// Ending value.
|
|
pub to: T,
|
|
/// Total duration of the animation.
|
|
pub duration: Duration,
|
|
/// Instant the animation was started on.
|
|
pub started: Instant,
|
|
}
|
|
|
|
impl<T> Animation<T> {
|
|
pub fn new(from: T, to: T, duration: Duration, started: Instant) -> Self {
|
|
Self {
|
|
from,
|
|
to,
|
|
duration,
|
|
started,
|
|
}
|
|
}
|
|
|
|
/// Time elapsed between `now` and the starting instant.
|
|
pub fn elapsed(&self, now: Instant) -> Duration {
|
|
now.saturating_duration_since(self.started)
|
|
}
|
|
|
|
/// Value of this animation at `now` instant.
|
|
pub fn value(&self, now: Instant) -> T
|
|
where
|
|
T: Lerp,
|
|
{
|
|
let factor = self.elapsed(now) / self.duration;
|
|
T::lerp_bounded(self.from, self.to, factor)
|
|
}
|
|
|
|
/// Seek the animation such that `value` would be the current value.
|
|
pub fn seek_to_value(&mut self, value: T)
|
|
where
|
|
T: InvLerp,
|
|
{
|
|
let factor = T::inv_lerp(self.from, self.to, value);
|
|
let offset = self.duration * factor;
|
|
self.seek_forward(offset);
|
|
}
|
|
|
|
/// Seek the animation forward by moving the starting instant back in time.
|
|
pub fn seek_forward(&mut self, offset: Duration) {
|
|
if let Some(started) = self.started.checked_sub(offset) {
|
|
self.started = started;
|
|
} else {
|
|
// Duration is too large to be added to an `Instant`.
|
|
#[cfg(feature = "ui_debug")]
|
|
panic!("offset is too large");
|
|
}
|
|
}
|
|
}
|