pub use canary_types::*; #[macro_export] macro_rules! export_abi { ($panel_impl: ident) => { #[no_mangle] pub extern "C" fn bind_panel(panel: u32) -> u32 { ::canary_script::abi::bind_panel::<$panel_impl>(panel) } #[no_mangle] pub extern "C" fn update(dt: f32) { ::canary_script::abi::update(dt) } #[no_mangle] pub extern "C" fn draw() { ::canary_script::abi::draw() } #[no_mangle] pub extern "C" fn on_cursor_event(kind: u32, x: f32, y: f32) { ::canary_script::abi::on_cursor_event(kind, x, y) } }; } pub mod abi { use super::*; use num_traits::FromPrimitive; static mut PANEL_IMPLS: Vec> = Vec::new(); pub fn bind_panel(panel: u32) -> u32 { unsafe { let panel = Panel(panel); let panel_impl = T::bind(panel); let id = PANEL_IMPLS.len() as u32; PANEL_IMPLS.push(panel_impl); id } } pub fn update(dt: f32) { unsafe { for panel in PANEL_IMPLS.iter_mut() { panel.update(dt); } } } pub fn draw() { unsafe { for panel in PANEL_IMPLS.iter_mut() { panel.draw(); } } } pub fn on_cursor_event(kind: u32, x: f32, y: f32) { let panel = unsafe { &mut PANEL_IMPLS[0] }; let at = canary_types::Vec2 { x, y }; let kind = CursorEventKind::from_u32(kind).unwrap(); panel.on_cursor_event(kind, at); } } pub trait BindPanel { fn bind(panel: Panel) -> Box; } pub trait PanelImpl { fn update(&mut self, dt: f32); fn draw(&mut self); fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2); } #[repr(transparent)] #[derive(Copy, Clone)] pub struct Panel(u32); impl Panel { pub unsafe fn bind(id: u32) -> Self { Self(id) } pub fn draw_indexed(&self, vertices: &[MeshVertex], indices: &[MeshIndex]) { unsafe { draw_indexed( vertices.as_ptr() as u32, vertices.len() as u32, indices.as_ptr() as u32, indices.len() as u32, ) } } pub fn draw_glyphs(&self, glyphs: &[GlyphPosition], offset: Vec2, scale: f32, color: Color) { unsafe { draw_glyphs( glyphs.as_ptr() as u32, glyphs.len() as u32, offset.x, offset.y, scale, color.r, color.g, color.b, color.a, ) } } pub fn draw_triangle(&self, v1: Vec2, v2: Vec2, v3: Vec2, color: Color) { let vertices = [ MeshVertex { position: v1, color, }, MeshVertex { position: v2, color, }, MeshVertex { position: v3, color, }, ]; let indices = [0, 1, 2]; self.draw_indexed(&vertices, &indices); } } #[repr(transparent)] pub struct TextLayout(u32); impl TextLayout { pub fn new(text: &str) -> Self { unsafe { Self(text_layout_new(text.as_ptr() as u32, text.len() as u32)) } } pub fn get_bounds(&self) -> Rect { unsafe { let mut bounds = Rect::default(); let bounds_ptr: *mut Rect = &mut bounds; text_layout_get_bounds(self.0, bounds_ptr as u32); bounds } } pub fn get_glyphs(&self) -> Vec { unsafe { let num = text_layout_get_glyphs_num(self.0) as usize; let mut glyphs = Vec::with_capacity(num); glyphs.set_len(num); text_layout_get_glyphs_data(self.0, glyphs.as_ptr() as u32, num as u32); glyphs } } } impl Drop for TextLayout { fn drop(&mut self) { unsafe { text_layout_delete(self.0) } } } extern "C" { fn draw_indexed(vertices_ptr: u32, vertices_num: u32, indices_ptr: u32, indices_num: u32); fn draw_glyphs( glyphs_ptr: u32, glyphs_len: u32, xoff: f32, yoff: f32, scale: f32, r: f32, g: f32, b: f32, a: f32, ); fn text_layout_new(text_ptr: u32, text_len: u32) -> u32; fn text_layout_delete(id: u32); fn text_layout_get_bounds(id: u32, rect_ptr: u32); fn text_layout_get_glyphs_num(id: u32) -> u32; fn text_layout_get_glyphs_data(id: u32, glyphs_ptr: u32, glyphs_num: u32); }