feat(core): word quiz enter animation

[no changelog]
pull/3911/head
tychovrahe 4 weeks ago committed by matejcik
parent 6ad41aa06e
commit 2f6ade5911

@ -7,7 +7,7 @@ use crate::trezorhal::time;
const MILLIS_PER_SEC: u32 = 1000;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct Duration {
millis: u32,
}

@ -5,7 +5,10 @@ use crate::{
strutil::TString,
time::{Duration, Stopwatch},
ui::{
component::{base::Component, Event, EventCtx},
component::{
base::{AttachType, Component},
Event, EventCtx, SwipeDirection,
},
constant::screen,
display::{Color, Icon},
geometry::{Offset, Rect},
@ -39,19 +42,19 @@ type AreasForSeparators = Vec<Rect, N_SEPS>;
#[derive(Default, Clone)]
struct AttachAnimation {
pub attach_top: bool,
pub timer: Stopwatch,
pub active: bool,
pub duration: Duration,
}
impl AttachAnimation {
const DURATION_MS: u32 = 350;
fn is_active(&self) -> bool {
if animation_disabled() {
return false;
}
self.timer
.is_running_within(Duration::from_millis(Self::DURATION_MS))
self.timer.is_running_within(self.duration)
}
fn eval(&self) -> f32 {
@ -63,25 +66,69 @@ impl AttachAnimation {
}
fn get_offset(&self, t: f32) -> Offset {
let value = pareen::constant(0.0).seq_ease_in(
0.0,
easer::functions::Cubic,
Self::DURATION_MS as f32 / 1000.0,
pareen::constant(1.0),
);
Offset::lerp(Offset::new(-40, 0), Offset::zero(), value.eval(t))
let value = if self.attach_top {
1.0
} else {
pareen::constant(0.0)
.seq_ease_in(
0.0,
easer::functions::Cubic,
self.duration.to_millis() as f32 / 1000.0,
pareen::constant(1.0).eval(t),
)
.eval(t)
};
Offset::lerp(Offset::new(-40, 0), Offset::zero(), value)
}
fn get_mask_width(&self, t: f32) -> i16 {
let value = pareen::constant(0.0).seq_ease_in(
0.0,
easer::functions::Circ,
0.15,
pareen::constant(1.0),
);
let value = if self.attach_top {
1.0
} else {
pareen::constant(0.0)
.seq_ease_in(0.0, easer::functions::Circ, 0.15, pareen::constant(1.0))
.eval(t)
};
//todo screen here is incorrect
i16::lerp(screen().width(), 0, value.eval(t))
i16::lerp(screen().width(), 0, value)
}
pub fn get_mask_item1_opacity(&self, t: f32) -> u8 {
let value = if self.attach_top {
pareen::constant(0.0)
.seq_ease_in(0.0, easer::functions::Cubic, 0.15, pareen::constant(1.0))
.eval(t)
} else {
1.0
};
u8::lerp(255, 0, value)
}
pub fn get_mask_item2_opacity(&self, t: f32) -> u8 {
let value = if self.attach_top {
pareen::constant(0.0)
.seq_ease_in(0.1, easer::functions::Cubic, 0.15, pareen::constant(1.0))
.eval(t)
} else {
1.0
};
u8::lerp(255, 0, value)
}
pub fn get_mask_item3_opacity(&self, t: f32) -> u8 {
let value = if self.attach_top {
pareen::constant(0.0)
.seq_ease_in(0.2, easer::functions::Cubic, 0.15, pareen::constant(1.0))
.eval(t)
} else {
1.0
};
u8::lerp(255, 0, value)
}
fn start(&mut self) {
@ -96,6 +143,15 @@ impl AttachAnimation {
fn lazy_start(&mut self, ctx: &mut EventCtx, event: Event) {
if let Event::Attach(_) = event {
if let Event::Attach(AttachType::Swipe(SwipeDirection::Up))
| Event::Attach(AttachType::Swipe(SwipeDirection::Down))
| Event::Attach(AttachType::Initial) = event
{
self.attach_top = true;
self.duration = Duration::from_millis(350);
} else {
self.duration = Duration::from_millis(350);
}
self.reset();
ctx.request_anim_frame();
}
@ -213,17 +269,34 @@ impl Component for VerticalMenu {
let offset = self.attach_animation.get_offset(t);
let mask_width = self.attach_animation.get_mask_width(t);
let item1_opacity = self.attach_animation.get_mask_item1_opacity(t);
let item2_opacity = self.attach_animation.get_mask_item2_opacity(t);
let item3_opacity = self.attach_animation.get_mask_item3_opacity(t);
let opacities = [item1_opacity, item2_opacity, item3_opacity];
target.with_origin(offset, &|target| {
// render buttons separated by thin bars
for button in &self.buttons {
for (i, button) in (&self.buttons).into_iter().enumerate() {
button.render(target);
Bar::new(button.area())
.with_fg(Color::black())
.with_bg(Color::black())
.with_alpha(opacities[i])
.render(target);
}
for area in self.areas_sep.iter() {
for (i, area) in self.areas_sep.iter().enumerate() {
Bar::new(*area)
.with_thickness(MENU_SEP_HEIGHT)
.with_fg(theme::GREY_EXTRA_DARK)
.render(target);
Bar::new(*area)
.with_fg(Color::black())
.with_bg(Color::black())
.with_alpha(opacities[i])
.render(target);
}
// todo screen here is incorrect

Loading…
Cancel
Save