Ease in/out animations
This commit is contained in:
parent
d36fa7b90c
commit
dd34f5110c
66
src/anim.rs
66
src/anim.rs
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
24
src/lib.rs
24
src/lib.rs
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue