Cursor events/basic animation

This commit is contained in:
mars 2022-07-08 13:48:32 -06:00
parent 59e84485e4
commit d36fa7b90c
5 changed files with 121 additions and 21 deletions

View File

@ -8,6 +8,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
glam = "^0.21"
keyframe = "1"
wee_alloc = "^0.4"
[profile.release]

View File

@ -1,4 +1,4 @@
use crate::{Color, Vec2};
use crate::{Color, Vec2, CursorEventKind};
static mut PANEL_IMPLS: Vec<Box<dyn PanelImpl>> = Vec::new();
@ -23,31 +23,28 @@ pub extern "C" fn update(dt: f32) {
}
#[macro_export]
macro_rules! handle_event_at {
($event: ident) => {
macro_rules! handle_cursor_event {
($event: ident, $kind: expr) => {
#[no_mangle]
pub extern "C" fn $event(id: u32, x: f32, y: f32) {
unsafe {
let panel = &mut PANEL_IMPLS[id as usize];
let at = Vec2::new(x, y);
(&mut *panel).$event(at);
(&mut *panel).on_cursor_event($kind, at);
}
}
};
}
handle_event_at!(on_hover);
handle_event_at!(on_select);
handle_event_at!(on_drag);
handle_event_at!(on_deselect);
handle_cursor_event!(on_hover, CursorEventKind::Hover);
handle_cursor_event!(on_select, CursorEventKind::Select);
handle_cursor_event!(on_drag, CursorEventKind::Drag);
handle_cursor_event!(on_deselect, CursorEventKind::Deselect);
#[allow(unused)]
pub trait PanelImpl {
fn update(&mut self, dt: f32) {}
fn on_hover(&mut self, at: Vec2) {}
fn on_select(&mut self, at: Vec2) {}
fn on_drag(&mut self, at: Vec2) {}
fn on_deselect(&mut self, at: Vec2) {}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {}
}
extern "C" {

56
src/anim.rs Normal file
View File

@ -0,0 +1,56 @@
use keyframe::EasingFunction;
pub struct Animation {
time: f32,
duration: f32,
from: f32,
to: f32,
function: Option<Box<dyn EasingFunction>>,
direction: bool,
}
impl Animation {
pub fn new(start: f32) -> Self {
Self {
time: 1.0,
duration: 0.0,
from: 0.0,
to: start,
function: None,
direction: true,
}
}
pub fn update(&mut self, dt: f32) {
self.time += dt;
}
pub fn is_active(&self) -> bool {
self.function.is_none() || self.time >= self.duration
}
pub fn get(&self) -> f32 {
if self.time >= self.duration {
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
}
}
pub fn ease_to(&mut self, function: Box<dyn EasingFunction>, duration: f32, to: f32) {
self.from = self.get();
self.to = to;
self.time = 0.0;
self.duration = duration;
self.function = Some(function);
}
}

View File

@ -4,6 +4,7 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
pub use glam::Vec2;
pub mod abi;
pub mod anim;
pub mod draw;
pub mod panel;
pub mod widgets;
@ -20,9 +21,7 @@ impl DummyPanel {
fn bind(panel: UiPanel) -> Self {
Self {
panel,
button: widgets::RoundButton {
pos: Vec2::new(0., 0.),
},
button: Default::default(),
}
}
}
@ -34,6 +33,10 @@ impl abi::PanelImpl for DummyPanel {
let ctx = draw::DrawContext::new(self.panel);
self.button.draw(&ctx);
}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
self.button.on_cursor_event(kind, at);
}
}
#[repr(C)]
@ -44,3 +47,11 @@ pub struct Color {
pub b: f32,
pub a: f32,
}
#[derive(Copy, Clone, Debug)]
pub enum CursorEventKind {
Hover,
Select,
Drag,
Deselect,
}

View File

@ -1,22 +1,57 @@
use crate::{Color, Vec2};
use crate::anim::Animation;
use crate::draw::DrawContext;
use crate::{Color, CursorEventKind, Vec2};
pub trait Widget {
fn update(&mut self, dt: f32);
fn draw(&mut self, ctx: &DrawContext);
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2);
}
pub struct RoundButton {
pub pos: Vec2,
pub radius: f32,
pub spacing: f32,
pub thickness: f32,
pub shrink_anim: Animation,
}
impl Default for RoundButton {
fn default() -> Self {
Self {
pos: Default::default(),
radius: 0.3,
spacing: 0.01,
thickness: 0.01,
shrink_anim: Animation::new(1.0),
}
}
}
impl Widget for RoundButton {
fn update(&mut self, dt: f32) {}
fn update(&mut self, dt: f32) {
self.shrink_anim.update(dt);
}
fn draw(&mut self, ctx: &DrawContext) {
let radius = 0.03;
let color = Color { r: 1.0, g: 0.0, b: 1.0, a: 1.0 };
ctx.draw_circle(&self.pos, radius, &color);
ctx.draw_ring(&self.pos, radius + 0.005, 0.001, &color);
let color = Color {
r: 1.0,
g: 0.0,
b: 1.0,
a: 1.0,
};
let spacing = self.shrink_anim.get() * self.spacing;
ctx.draw_circle(&self.pos, self.radius, &color);
ctx.draw_ring(&self.pos, self.radius + spacing, self.thickness, &color);
}
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);
},
_ => {}
}
}
}