Refactor
This commit is contained in:
parent
118c73a030
commit
59e84485e4
|
@ -0,0 +1,107 @@
|
|||
use crate::{Color, Vec2};
|
||||
|
||||
static mut PANEL_IMPLS: Vec<Box<dyn PanelImpl>> = Vec::new();
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn bind_panel(panel: u32) -> u32 {
|
||||
unsafe {
|
||||
let panel = UiPanel::bind(panel);
|
||||
let panel_impl = Box::new(crate::DummyPanel::bind(panel));
|
||||
let id = PANEL_IMPLS.len() as u32;
|
||||
PANEL_IMPLS.push(panel_impl);
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn update(dt: f32) {
|
||||
unsafe {
|
||||
for panel in PANEL_IMPLS.iter_mut() {
|
||||
panel.update(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! handle_event_at {
|
||||
($event: ident) => {
|
||||
#[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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
handle_event_at!(on_hover);
|
||||
handle_event_at!(on_select);
|
||||
handle_event_at!(on_drag);
|
||||
handle_event_at!(on_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) {}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn UiPanel_getWidth(panel: u32) -> f32;
|
||||
fn UiPanel_getHeight(panel: u32) -> f32;
|
||||
fn UiPanel_setSize(panel: u32, width: f32, height: f32);
|
||||
fn UiPanel_setColor(panel: u32, r: f32, g: f32, b: f32, a: f32);
|
||||
|
||||
#[link_name = "UiPanel_drawTriangle"]
|
||||
fn UiPanel_drawTriangle(
|
||||
panel: u32,
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
x2: f32,
|
||||
y2: f32,
|
||||
x3: f32,
|
||||
y3: f32,
|
||||
r: f32,
|
||||
g: f32,
|
||||
b: f32,
|
||||
a: f32,
|
||||
);
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct UiPanel(u32);
|
||||
|
||||
impl UiPanel {
|
||||
pub unsafe fn bind(id: u32) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
|
||||
pub fn get_width(&self) -> f32 {
|
||||
unsafe { UiPanel_getWidth(self.0) }
|
||||
}
|
||||
|
||||
pub fn get_height(&self) -> f32 {
|
||||
unsafe { UiPanel_getHeight(self.0) }
|
||||
}
|
||||
|
||||
pub fn set_size(&mut self, width: f32, height: f32) {
|
||||
unsafe { UiPanel_setSize(self.0, width, height) }
|
||||
}
|
||||
|
||||
pub fn set_color(&mut self, color: &Color) {
|
||||
unsafe { UiPanel_setColor(self.0, color.r, color.g, color.b, color.a) }
|
||||
}
|
||||
|
||||
pub fn draw_triangle(&self, v1: &Vec2, v2: &Vec2, v3: &Vec2, color: &Color) {
|
||||
unsafe {
|
||||
UiPanel_drawTriangle(
|
||||
self.0, v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, color.r, color.g, color.b, color.a,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
use crate::{Color, Vec2};
|
||||
use crate::abi::UiPanel;
|
||||
|
||||
pub struct DrawContext {
|
||||
panel: UiPanel,
|
||||
}
|
||||
|
||||
impl DrawContext {
|
||||
pub fn new(panel: UiPanel) -> Self {
|
||||
Self { panel }
|
||||
}
|
||||
|
||||
pub fn draw_triangle(&self, v1: &Vec2, v2: &Vec2, v3: &Vec2, color: &Color) {
|
||||
self.panel.draw_triangle(v1, v2, v3, color)
|
||||
}
|
||||
|
||||
pub fn draw_circle(&self, center: &Vec2, radius: f32, color: &Color) {
|
||||
use std::f32::consts::PI;
|
||||
|
||||
let delta = PI / 16.0;
|
||||
let limit = PI * 2.0 + delta;
|
||||
|
||||
let mut last_spoke = Vec2::new(radius + center.x, center.y);
|
||||
let mut theta = delta;
|
||||
while theta < limit {
|
||||
let new_spoke = Vec2::from_angle(theta) * radius + *center;
|
||||
self.draw_triangle(¢er, &last_spoke, &new_spoke, &color);
|
||||
last_spoke = new_spoke;
|
||||
theta += delta;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_ring(&self, center: &Vec2, radius: f32, thickness: f32, color: &Color) {
|
||||
use std::f32::consts::PI;
|
||||
|
||||
let delta = PI / 64.0;
|
||||
let limit = PI * 2.0 + delta;
|
||||
|
||||
let mut last_spoke = glam::Vec2::new(radius + center.x, center.y);
|
||||
let mut last_theta = 0.0;
|
||||
let mut theta = delta;
|
||||
while theta < limit {
|
||||
let angle = Vec2::from_angle(theta);
|
||||
let new_spoke = angle * radius + *center;
|
||||
let new_spoke2 = angle * (radius + thickness) + *center;
|
||||
let last_spoke2 = Vec2::from_angle(last_theta) * (radius + thickness) + *center;
|
||||
|
||||
self.draw_triangle(&new_spoke2, &last_spoke, &new_spoke, &color);
|
||||
self.draw_triangle(&new_spoke2, &last_spoke2, &last_spoke, &color);
|
||||
|
||||
last_spoke = new_spoke;
|
||||
last_theta = theta;
|
||||
theta += delta;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_rect(&self, xy: &Vec2, size: &Vec2, color: &Color) {
|
||||
let v1 = *xy;
|
||||
let v2 = v1 + Vec2::new(size.x, 0.0);
|
||||
let v3 = v1 + Vec2::new(0.0, size.y);
|
||||
let v4 = v1 + *size;
|
||||
|
||||
self.draw_triangle(&v1, &v2, &v3, &color);
|
||||
self.draw_triangle(&v2, &v3, &v4, &color);
|
||||
}
|
||||
}
|
185
src/lib.rs
185
src/lib.rs
|
@ -1,103 +1,39 @@
|
|||
use glam::Vec2;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
static mut PANEL_IMPLS: Vec<Box<dyn PanelImpl>> = Vec::new();
|
||||
pub use glam::Vec2;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn bind_panel(panel: u32) -> u32 {
|
||||
unsafe {
|
||||
let panel = UiPanel::bind(panel);
|
||||
let panel_impl = Box::new(DummyPanel::bind(panel));
|
||||
let id = PANEL_IMPLS.len() as u32;
|
||||
PANEL_IMPLS.push(panel_impl);
|
||||
id
|
||||
}
|
||||
}
|
||||
pub mod abi;
|
||||
pub mod draw;
|
||||
pub mod panel;
|
||||
pub mod widgets;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn update(dt: f32) {
|
||||
unsafe {
|
||||
for panel in PANEL_IMPLS.iter_mut() {
|
||||
panel.update(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! handle_event_at {
|
||||
($event: ident) => {
|
||||
#[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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
handle_event_at!(on_hover);
|
||||
handle_event_at!(on_select);
|
||||
handle_event_at!(on_drag);
|
||||
handle_event_at!(on_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) {}
|
||||
}
|
||||
use abi::UiPanel;
|
||||
use widgets::Widget;
|
||||
|
||||
pub struct DummyPanel {
|
||||
panel: UiPanel,
|
||||
button: widgets::RoundButton,
|
||||
}
|
||||
|
||||
impl DummyPanel {
|
||||
fn bind(panel: UiPanel) -> Self {
|
||||
Self { panel }
|
||||
}
|
||||
}
|
||||
|
||||
impl PanelImpl for DummyPanel {
|
||||
fn update(&mut self, _dt: f32) {
|
||||
self.panel.draw_rect(
|
||||
&Vec2 { x: 0.0, y: 0.0 },
|
||||
&Vec2 { x: 0.5, y: 0.5 },
|
||||
&Color {
|
||||
r: 1.0,
|
||||
g: 0.0,
|
||||
b: 1.0,
|
||||
a: 1.0,
|
||||
Self {
|
||||
panel,
|
||||
button: widgets::RoundButton {
|
||||
pos: Vec2::new(0., 0.),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn UiPanel_getWidth(panel: u32) -> f32;
|
||||
fn UiPanel_getHeight(panel: u32) -> f32;
|
||||
fn UiPanel_setSize(panel: u32, width: f32, height: f32);
|
||||
fn UiPanel_setColor(panel: u32, r: f32, g: f32, b: f32, a: f32);
|
||||
impl abi::PanelImpl for DummyPanel {
|
||||
fn update(&mut self, dt: f32) {
|
||||
self.button.update(dt);
|
||||
|
||||
#[link_name = "UiPanel_drawTriangle"]
|
||||
fn UiPanel_drawTriangle(
|
||||
panel: u32,
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
x2: f32,
|
||||
y2: f32,
|
||||
x3: f32,
|
||||
y3: f32,
|
||||
r: f32,
|
||||
g: f32,
|
||||
b: f32,
|
||||
a: f32,
|
||||
);
|
||||
let ctx = draw::DrawContext::new(self.panel);
|
||||
self.button.draw(&ctx);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -108,86 +44,3 @@ pub struct Color {
|
|||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct UiPanel(u32);
|
||||
|
||||
impl UiPanel {
|
||||
pub unsafe fn bind(id: u32) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
|
||||
pub fn get_width(&self) -> f32 {
|
||||
unsafe { UiPanel_getWidth(self.0) }
|
||||
}
|
||||
|
||||
pub fn get_height(&self) -> f32 {
|
||||
unsafe { UiPanel_getHeight(self.0) }
|
||||
}
|
||||
|
||||
pub fn set_size(&mut self, width: f32, height: f32) {
|
||||
unsafe { UiPanel_setSize(self.0, width, height) }
|
||||
}
|
||||
|
||||
pub fn set_color(&mut self, color: &Color) {
|
||||
unsafe { UiPanel_setColor(self.0, color.r, color.g, color.b, color.a) }
|
||||
}
|
||||
|
||||
pub fn draw_triangle(&mut self, v1: &Vec2, v2: &Vec2, v3: &Vec2, color: &Color) {
|
||||
unsafe {
|
||||
UiPanel_drawTriangle(
|
||||
self.0, v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, color.r, color.g, color.b, color.a,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_circle(&mut self, center: &Vec2, radius: f32, color: &Color) {
|
||||
use std::f32::consts::PI;
|
||||
|
||||
let delta = PI / 16.0;
|
||||
let limit = PI * 2.0 + delta;
|
||||
|
||||
let mut last_spoke = Vec2::new(radius + center.x, center.y);
|
||||
let mut theta = delta;
|
||||
while theta < limit {
|
||||
let new_spoke = Vec2::from_angle(theta) * radius + *center;
|
||||
self.draw_triangle(¢er, &last_spoke, &new_spoke, &color);
|
||||
last_spoke = new_spoke;
|
||||
theta += delta;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_ring(&mut self, center: &Vec2, radius: f32, thickness: f32, color: &Color) {
|
||||
use std::f32::consts::PI;
|
||||
|
||||
let delta = PI / 64.0;
|
||||
let limit = PI * 2.0 + delta;
|
||||
|
||||
let mut last_spoke = glam::Vec2::new(radius + center.x, center.y);
|
||||
let mut last_theta = 0.0;
|
||||
let mut theta = delta;
|
||||
while theta < limit {
|
||||
let angle = Vec2::from_angle(theta);
|
||||
let new_spoke = angle * radius + *center;
|
||||
let new_spoke2 = angle * (radius + thickness) + *center;
|
||||
let last_spoke2 = Vec2::from_angle(last_theta) * (radius + thickness) + *center;
|
||||
|
||||
self.draw_triangle(&new_spoke2, &last_spoke, &new_spoke, &color);
|
||||
self.draw_triangle(&new_spoke2, &last_spoke2, &last_spoke, &color);
|
||||
|
||||
last_spoke = new_spoke;
|
||||
last_theta = theta;
|
||||
theta += delta;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_rect(&mut self, xy: &Vec2, size: &Vec2, color: &Color) {
|
||||
let v1 = *xy;
|
||||
let v2 = v1 + Vec2::new(size.x, 0.0);
|
||||
let v3 = v1 + Vec2::new(0.0, size.y);
|
||||
let v4 = v1 + *size;
|
||||
|
||||
self.draw_triangle(&v1, &v2, &v3, &color);
|
||||
self.draw_triangle(&v2, &v3, &v4, &color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
use crate::{Color, Vec2};
|
||||
use crate::draw::DrawContext;
|
||||
|
||||
pub trait Widget {
|
||||
fn update(&mut self, dt: f32);
|
||||
fn draw(&mut self, ctx: &DrawContext);
|
||||
}
|
||||
|
||||
pub struct RoundButton {
|
||||
pub pos: Vec2,
|
||||
}
|
||||
|
||||
impl Widget for RoundButton {
|
||||
fn update(&mut self, dt: f32) {}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue