Closing animation + in/out anim delays + ScrollMenu was_clicked()
This commit is contained in:
parent
cc4f064587
commit
7eb0983ee9
18
src/anim.rs
18
src/anim.rs
|
@ -4,7 +4,8 @@ use keyframe::EasingFunction;
|
|||
pub struct Animation<F> {
|
||||
time: f32,
|
||||
duration: f32,
|
||||
delay: f32,
|
||||
in_delay: f32,
|
||||
out_delay: f32,
|
||||
from: f32,
|
||||
to: f32,
|
||||
function: F,
|
||||
|
@ -18,7 +19,8 @@ impl<F: EasingFunction> Animation<F> {
|
|||
duration,
|
||||
from,
|
||||
to,
|
||||
delay: 0.0,
|
||||
in_delay: 0.0,
|
||||
out_delay: 0.0,
|
||||
function,
|
||||
direction: false,
|
||||
}
|
||||
|
@ -75,14 +77,20 @@ impl<F: EasingFunction> Animation<F> {
|
|||
pub fn ease_toggle(&mut self) {
|
||||
if self.is_active() {
|
||||
self.time = self.duration - self.time;
|
||||
} else if self.direction {
|
||||
self.time = -self.out_delay;
|
||||
} else {
|
||||
self.time = -self.delay;
|
||||
self.time = -self.in_delay;
|
||||
}
|
||||
|
||||
self.direction = !self.direction;
|
||||
}
|
||||
|
||||
pub fn set_delay(&mut self, delay: f32) {
|
||||
self.delay = delay;
|
||||
pub fn set_in_delay(&mut self, delay: f32) {
|
||||
self.in_delay = delay;
|
||||
}
|
||||
|
||||
pub fn set_out_delay(&mut self, delay: f32) {
|
||||
self.out_delay = delay;
|
||||
}
|
||||
}
|
||||
|
|
103
src/widgets.rs
103
src/widgets.rs
|
@ -94,6 +94,8 @@ impl Widget for RoundButton {
|
|||
pub enum ScrollMenuState {
|
||||
Opening,
|
||||
Idle,
|
||||
Closing,
|
||||
Closed,
|
||||
}
|
||||
|
||||
pub struct ScrollMenuButton<T> {
|
||||
|
@ -107,23 +109,30 @@ pub struct ScrollMenu<T> {
|
|||
pub spacing: f32,
|
||||
pub scroll_anim: Animation<EaseInOutQuint>,
|
||||
pub state: ScrollMenuState,
|
||||
pub was_clicked: Option<usize>,
|
||||
}
|
||||
|
||||
impl<T> ScrollMenu<T> {
|
||||
pub fn new(buttons: Vec<T>, spacing: f32) -> Self {
|
||||
let inter_button_delay = 0.05;
|
||||
let max_delay = buttons.len() as f32 * inter_button_delay;
|
||||
|
||||
let buttons: Vec<_> = buttons
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, widget)| {
|
||||
let duration = 0.25;
|
||||
let delay = i as f32 * 0.05;
|
||||
let in_delay = i as f32 * inter_button_delay;
|
||||
let out_delay = max_delay - in_delay;
|
||||
|
||||
let mut slide_anim = Animation::new(EaseOut, duration, 0.25, 0.0);
|
||||
slide_anim.set_delay(delay);
|
||||
slide_anim.set_in_delay(in_delay);
|
||||
slide_anim.set_out_delay(out_delay);
|
||||
slide_anim.ease_in();
|
||||
|
||||
let mut opacity_anim = Animation::new(EaseOut, duration, 0.0, 1.0);
|
||||
opacity_anim.set_delay(delay);
|
||||
opacity_anim.set_in_delay(in_delay);
|
||||
opacity_anim.set_out_delay(out_delay);
|
||||
opacity_anim.ease_in();
|
||||
|
||||
ScrollMenuButton {
|
||||
|
@ -139,6 +148,24 @@ impl<T> ScrollMenu<T> {
|
|||
spacing,
|
||||
scroll_anim: Animation::new(EaseInOutQuint, 0.2, 0.0, 0.0),
|
||||
state: ScrollMenuState::Opening,
|
||||
was_clicked: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn was_clicked(&self) -> Option<usize> {
|
||||
self.was_clicked
|
||||
}
|
||||
|
||||
pub fn scroll_to(&mut self, button_id: usize) {
|
||||
self.scroll_anim.ease_to(button_id as f32);
|
||||
}
|
||||
|
||||
pub fn close(&mut self) {
|
||||
self.state = ScrollMenuState::Closing;
|
||||
|
||||
for button in self.buttons.iter_mut() {
|
||||
button.slide_anim.ease_out();
|
||||
button.opacity_anim.ease_out();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,29 +175,8 @@ impl<T> ScrollMenu<T> {
|
|||
cb(button, i, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Widget + Button> Widget for ScrollMenu<T> {
|
||||
fn update(&mut self, dt: f32) {
|
||||
match self.state {
|
||||
ScrollMenuState::Idle => {
|
||||
self.scroll_anim.update(dt);
|
||||
|
||||
let mut scroll_to = None;
|
||||
|
||||
self.for_buttons(|button, i, _y| {
|
||||
if button.widget.was_clicked() {
|
||||
scroll_to = Some(i);
|
||||
}
|
||||
|
||||
button.widget.update(dt);
|
||||
});
|
||||
|
||||
if let Some(to) = scroll_to {
|
||||
self.scroll_anim.ease_to(to as f32);
|
||||
}
|
||||
}
|
||||
ScrollMenuState::Opening => {
|
||||
fn animate_buttons(&mut self, dt: f32) -> bool {
|
||||
let mut all_slid = true;
|
||||
|
||||
self.for_buttons(|button, _i, _y| {
|
||||
|
@ -182,14 +188,41 @@ impl<T: Widget + Button> Widget for ScrollMenu<T> {
|
|||
}
|
||||
});
|
||||
|
||||
if all_slid {
|
||||
all_slid
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Widget + Button> Widget for ScrollMenu<T> {
|
||||
fn update(&mut self, dt: f32) {
|
||||
self.was_clicked = None;
|
||||
|
||||
match self.state {
|
||||
ScrollMenuState::Idle => {
|
||||
self.scroll_anim.update(dt);
|
||||
|
||||
self.for_buttons(|button, _i, _y| {
|
||||
button.widget.update(dt);
|
||||
});
|
||||
}
|
||||
ScrollMenuState::Opening => {
|
||||
if self.animate_buttons(dt) {
|
||||
self.state = ScrollMenuState::Idle;
|
||||
}
|
||||
}
|
||||
ScrollMenuState::Closing => {
|
||||
if self.animate_buttons(dt) {
|
||||
self.state = ScrollMenuState::Closed;
|
||||
}
|
||||
}
|
||||
ScrollMenuState::Closed => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&mut self, ctx: &DrawContext) {
|
||||
if self.state == ScrollMenuState::Closed {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.draw_triangle(
|
||||
Vec2::new(self.spacing, 0.0),
|
||||
Vec2::new(self.spacing + 0.05, 0.05),
|
||||
|
@ -221,10 +254,18 @@ impl<T: Widget + Button> Widget for ScrollMenu<T> {
|
|||
return;
|
||||
}
|
||||
|
||||
self.for_buttons(|button, _i, y| {
|
||||
let mut was_clicked = None;
|
||||
|
||||
self.for_buttons(|button, i, y| {
|
||||
let at = at - Vec2::new(0.0, y);
|
||||
button.widget.on_cursor_event(kind, at);
|
||||
})
|
||||
|
||||
if button.widget.was_clicked() {
|
||||
was_clicked = Some(i);
|
||||
}
|
||||
});
|
||||
|
||||
self.was_clicked = was_clicked;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,6 +289,12 @@ impl Default for MainMenu {
|
|||
|
||||
impl Widget for MainMenu {
|
||||
fn update(&mut self, dt: f32) {
|
||||
match self.menu.was_clicked() {
|
||||
None => {},
|
||||
Some(0) => self.menu.close(),
|
||||
Some(button) => self.menu.scroll_to(button),
|
||||
};
|
||||
|
||||
self.menu.update(dt);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue