Cursor events/basic animation
This commit is contained in:
parent
59e84485e4
commit
d36fa7b90c
|
@ -8,6 +8,7 @@ crate-type = ["cdylib", "rlib"]
|
|||
|
||||
[dependencies]
|
||||
glam = "^0.21"
|
||||
keyframe = "1"
|
||||
wee_alloc = "^0.4"
|
||||
|
||||
[profile.release]
|
||||
|
|
21
src/abi.rs
21
src/abi.rs
|
@ -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" {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
17
src/lib.rs
17
src/lib.rs
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue