This commit is contained in:
mars 2022-07-08 12:48:31 -06:00
parent 118c73a030
commit 59e84485e4
5 changed files with 215 additions and 166 deletions

107
src/abi.rs Normal file
View File

@ -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,
)
}
}
}

66
src/draw.rs Normal file
View File

@ -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(&center, &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);
}
}

View File

@ -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(&center, &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);
}
}

1
src/panel.rs Normal file
View File

@ -0,0 +1 @@

22
src/widgets.rs Normal file
View File

@ -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);
}
}