Ease in/out animations

This commit is contained in:
mars 2022-07-08 20:07:19 -06:00
parent d36fa7b90c
commit dd34f5110c
3 changed files with 68 additions and 38 deletions

View File

@ -1,23 +1,23 @@
use keyframe::EasingFunction;
pub struct Animation {
pub struct Animation<F> {
time: f32,
duration: f32,
from: f32,
to: f32,
function: Option<Box<dyn EasingFunction>>,
function: F,
direction: bool,
}
impl Animation {
pub fn new(start: f32) -> Self {
impl<F: EasingFunction> Animation<F> {
pub fn new(function: F, duration: f32, from: f32, to: f32) -> Self {
Self {
time: 1.0,
duration: 0.0,
from: 0.0,
to: start,
function: None,
direction: true,
time: duration,
duration,
from,
to,
function,
direction: false,
}
}
@ -26,31 +26,49 @@ impl Animation {
}
pub fn is_active(&self) -> bool {
self.function.is_none() || self.time >= self.duration
self.time < self.duration
}
pub fn get(&self) -> f32 {
if self.time >= self.duration {
if self.is_active() {
let x = self.time / self.duration;
let x = if self.direction { x } else { 1.0 - x };
let lerp = self.function.y(x as f64) as f32;
(1.0 - lerp) * self.from + lerp * self.to
} else if self.direction {
self.to
} else if let Some(function) = self.function.as_ref() {
let (from, to) = if self.direction {
(self.from, self.to)
} else {
(self.to, self.from)
};
let lerp = function.y((self.time / self.duration) as f64) as f32;
(1.0 - lerp) * from + lerp * to
} else {
self.to
self.from
}
}
pub fn ease_to(&mut self, function: Box<dyn EasingFunction>, duration: f32, to: f32) {
pub fn ease_to(&mut self, duration: f32, to: f32) {
self.from = self.get();
self.to = to;
self.time = 0.0;
self.duration = duration;
self.function = Some(function);
self.direction = true;
}
pub fn ease_in(&mut self) {
if !self.direction {
self.ease_toggle();
}
}
pub fn ease_out(&mut self) {
if self.direction {
self.ease_toggle();
}
}
pub fn ease_toggle(&mut self) {
if self.is_active() {
self.time = self.duration - self.time;
} else {
self.time = 0.0;
}
self.direction = !self.direction;
}
}

View File

@ -14,28 +14,36 @@ use widgets::Widget;
pub struct DummyPanel {
panel: UiPanel,
button: widgets::RoundButton,
buttons: Vec<widgets::RoundButton>,
}
impl DummyPanel {
fn bind(panel: UiPanel) -> Self {
Self {
panel,
button: Default::default(),
let mut buttons = Vec::new();
for i in 0..6 {
let mut button = widgets::RoundButton::default();
button.pos.y = i as f32 * 0.2;
buttons.push(button);
}
Self { panel, buttons }
}
}
impl abi::PanelImpl for DummyPanel {
fn update(&mut self, dt: f32) {
self.button.update(dt);
let ctx = draw::DrawContext::new(self.panel);
self.button.draw(&ctx);
for button in self.buttons.iter_mut() {
button.update(dt);
button.draw(&ctx);
}
}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
self.button.on_cursor_event(kind, at);
for button in self.buttons.iter_mut() {
button.on_cursor_event(kind, at);
}
}
}

View File

@ -1,4 +1,5 @@
use crate::anim::Animation;
use keyframe::functions::*;
use crate::draw::DrawContext;
use crate::{Color, CursorEventKind, Vec2};
@ -13,17 +14,17 @@ pub struct RoundButton {
pub radius: f32,
pub spacing: f32,
pub thickness: f32,
pub shrink_anim: Animation,
pub shrink_anim: Animation<EaseInQuint>,
}
impl Default for RoundButton {
fn default() -> Self {
Self {
pos: Default::default(),
radius: 0.3,
radius: 0.05,
spacing: 0.01,
thickness: 0.01,
shrink_anim: Animation::new(1.0),
thickness: 0.005,
shrink_anim: Animation::new(EaseInQuint, 0.1, 1.0, 0.0),
}
}
}
@ -48,9 +49,12 @@ impl Widget for RoundButton {
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
match kind {
CursorEventKind::Select => if at.distance(self.pos) < self.radius {
self.shrink_anim.ease_to(Box::new(keyframe::functions::EaseIn), 0.2, 0.0);
CursorEventKind::Select => if self.pos.distance(at) < self.radius {
self.shrink_anim.ease_in();
},
CursorEventKind::Deselect => {
self.shrink_anim.ease_out();
}
_ => {}
}
}