Add Message and bind_panel() message
This commit is contained in:
parent
9aa71b4cea
commit
237ef96dfa
|
@ -36,7 +36,8 @@ impl App {
|
|||
let abi = canary::ScriptAbiImpl::default();
|
||||
let module = std::fs::read(module_path).unwrap();
|
||||
let mut script = runtime.load_module(abi, &module).unwrap();
|
||||
let panel = script.bind_panel();
|
||||
let msg = "Hello, script!".to_string().as_bytes().to_vec();
|
||||
let panel = script.bind_panel(msg);
|
||||
|
||||
Self {
|
||||
script,
|
||||
|
|
|
@ -12,7 +12,7 @@ use glam::Vec2;
|
|||
use widgets::Widget;
|
||||
use main_menu::MainMenuPanel;
|
||||
|
||||
export_abi!(MainMenuPanel);
|
||||
export_abi!(ConfirmationDialogPanel);
|
||||
|
||||
pub const ICON_FONT: &str = "Iosevka Nerd Font";
|
||||
pub const DISPLAY_FONT: &str = "Homenaje";
|
||||
|
@ -24,11 +24,14 @@ pub struct ConfirmationDialogPanel {
|
|||
}
|
||||
|
||||
impl BindPanel for ConfirmationDialogPanel {
|
||||
fn bind(panel: Panel) -> Box<dyn PanelImpl> {
|
||||
fn bind(panel: Panel, msg: Message) -> Box<dyn PanelImpl> {
|
||||
let msg = msg.to_vec();
|
||||
let title = String::from_utf8(msg).unwrap();
|
||||
|
||||
use widgets::dialog::*;
|
||||
let style = DialogStyle::default();
|
||||
let info = DialogInfo {
|
||||
title: "ha jk",
|
||||
title: &title,
|
||||
content: "lmao u wish",
|
||||
responses: &[DialogResponse::Yes, DialogResponse::No],
|
||||
};
|
||||
|
@ -51,4 +54,6 @@ impl PanelImpl for ConfirmationDialogPanel {
|
|||
fn on_cursor_event(&mut self, kind: CursorEventKind, at: canary_script::Vec2) {
|
||||
self.dialog.on_cursor_event(kind, at.into());
|
||||
}
|
||||
|
||||
fn on_message(&mut self, _msg: Message) {}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::widgets::*;
|
||||
use button::{RectButton, RoundButton, RoundButtonStyle};
|
||||
use canary_script::draw::{DrawContext, Rect};
|
||||
use canary_script::{BindPanel, Color, CursorEventKind, Font, Panel, PanelImpl};
|
||||
use canary_script::{BindPanel, Color, CursorEventKind, Font, Message, Panel, PanelImpl};
|
||||
use dialog::{Dialog, DialogInfo, DialogResponse, DialogStyle};
|
||||
use glam::Vec2;
|
||||
use menu::{SlotMenu, SlotMenuEvent, TabMenu};
|
||||
|
@ -14,7 +14,7 @@ pub struct MainMenuPanel {
|
|||
}
|
||||
|
||||
impl BindPanel for MainMenuPanel {
|
||||
fn bind(panel: Panel) -> Box<dyn PanelImpl> {
|
||||
fn bind(panel: Panel, msg: Message) -> Box<dyn PanelImpl> {
|
||||
Box::new(Self {
|
||||
panel,
|
||||
menu: MainMenu::default(),
|
||||
|
@ -35,6 +35,8 @@ impl PanelImpl for MainMenuPanel {
|
|||
fn on_cursor_event(&mut self, kind: CursorEventKind, at: canary_script::Vec2) {
|
||||
Widget::on_cursor_event(&mut self.menu, kind, at.into());
|
||||
}
|
||||
|
||||
fn on_message(&mut self, msg: Message) {}
|
||||
}
|
||||
|
||||
pub struct MainMenu {
|
||||
|
|
|
@ -6,8 +6,8 @@ pub mod draw;
|
|||
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)
|
||||
pub extern "C" fn bind_panel(panel: u32, msg: u32) -> u32 {
|
||||
::canary_script::abi::bind_panel::<$panel_impl>(panel, msg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -24,6 +24,11 @@ macro_rules! export_abi {
|
|||
pub extern "C" fn on_cursor_event(panel_data: u32, kind: u32, x: f32, y: f32) {
|
||||
::canary_script::abi::on_cursor_event(panel_data, kind, x, y)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn on_message(panel_data: u32, msg: u32) {
|
||||
::canary_script::abi::on_message(panel_data, msg)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -33,10 +38,11 @@ pub mod abi {
|
|||
|
||||
static mut PANEL_IMPLS: Vec<Box<dyn PanelImpl>> = Vec::new();
|
||||
|
||||
pub fn bind_panel<T: BindPanel>(panel: u32) -> u32 {
|
||||
pub fn bind_panel<T: BindPanel>(panel: u32, msg: u32) -> u32 {
|
||||
unsafe {
|
||||
let panel = Panel(panel);
|
||||
let panel_impl = T::bind(panel);
|
||||
let msg = Message(msg);
|
||||
let panel_impl = T::bind(panel, msg);
|
||||
let id = PANEL_IMPLS.len() as u32;
|
||||
PANEL_IMPLS.push(panel_impl);
|
||||
id
|
||||
|
@ -59,16 +65,23 @@ pub mod abi {
|
|||
let kind = CursorEventKind::from_u32(kind).unwrap();
|
||||
panel.on_cursor_event(kind, at);
|
||||
}
|
||||
|
||||
pub fn on_message(panel_data: u32, msg: u32) {
|
||||
let panel = unsafe { &mut PANEL_IMPLS[panel_data as usize] };
|
||||
let msg = Message(msg);
|
||||
panel.on_message(msg)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BindPanel {
|
||||
fn bind(panel: Panel) -> Box<dyn PanelImpl>;
|
||||
fn bind(panel: Panel, msg: Message) -> Box<dyn PanelImpl>;
|
||||
}
|
||||
|
||||
pub trait PanelImpl {
|
||||
fn update(&mut self, dt: f32);
|
||||
fn draw(&mut self);
|
||||
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2);
|
||||
fn on_message(&mut self, msg: Message);
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
|
@ -161,6 +174,21 @@ impl Drop for TextLayout {
|
|||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct Message(u32);
|
||||
|
||||
impl Message {
|
||||
pub fn to_vec(self) -> Vec<u8> {
|
||||
unsafe {
|
||||
let len = message_get_len(self.0) as usize;
|
||||
let mut vec = Vec::with_capacity(len);
|
||||
vec.set_len(len);
|
||||
message_get_data(self.0, vec.as_ptr() as u32);
|
||||
vec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn draw_indexed(vertices_ptr: u32, vertices_num: u32, indices_ptr: u32, indices_num: u32);
|
||||
fn draw_text_layout(id: u32, xoff: f32, yoff: f32, scale: f32, r: f32, g: f32, b: f32, a: f32);
|
||||
|
@ -169,4 +197,7 @@ extern "C" {
|
|||
fn text_layout_new(font_id: u32, text_ptr: u32, text_len: u32) -> u32;
|
||||
fn text_layout_delete(id: u32);
|
||||
fn text_layout_get_bounds(id: u32, rect_ptr: u32);
|
||||
|
||||
fn message_get_len(id: u32) -> u32;
|
||||
fn message_get_data(id: u32, ptr: u32);
|
||||
}
|
||||
|
|
56
src/lib.rs
56
src/lib.rs
|
@ -21,13 +21,18 @@ pub trait ScriptAbi {
|
|||
fn text_layout_new(&self, font_id: u32, text: &str) -> u32;
|
||||
fn text_layout_delete(&self, id: u32);
|
||||
fn text_layout_get_bounds(&self, id: u32, rect: &mut Rect);
|
||||
|
||||
fn message_new(&self, data: Vec<u8>) -> u32;
|
||||
fn message_free(&self, id: u32);
|
||||
fn message_get_len(&self, id: u32) -> u32;
|
||||
fn message_get_data(&self, id: u32, dst: &mut [u8]);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct PanelId(pub(crate) usize);
|
||||
|
||||
pub trait ScriptInstance {
|
||||
fn bind_panel(&mut self) -> PanelId;
|
||||
fn bind_panel(&mut self, msg: Vec<u8>) -> PanelId;
|
||||
fn update(&mut self, panel: PanelId, dt: f32);
|
||||
fn draw(&mut self, panel: PanelId, f: impl FnOnce(&[DrawCommand]));
|
||||
fn on_cursor_event(&mut self, panel: PanelId, kind: CursorEventKind, at: Vec2);
|
||||
|
@ -87,7 +92,7 @@ impl WasmtimeRuntime {
|
|||
pub struct WasmtimeScript<T> {
|
||||
store: wasmtime::Store<T>,
|
||||
panel_datas: Slab<u32>,
|
||||
bind_panel: wasmtime::TypedFunc<u32, u32>,
|
||||
bind_panel: wasmtime::TypedFunc<(u32, u32), u32>,
|
||||
update: wasmtime::TypedFunc<(u32, f32), ()>,
|
||||
draw: wasmtime::TypedFunc<u32, ()>,
|
||||
on_cursor_event: wasmtime::TypedFunc<(u32, u32, f32, f32), ()>,
|
||||
|
@ -162,6 +167,25 @@ impl<T: ScriptAbi> WasmtimeScript<T> {
|
|||
},
|
||||
)?;
|
||||
|
||||
linker.func_wrap(
|
||||
module,
|
||||
"message_get_len",
|
||||
|caller: wasmtime::Caller<'_, T>, id: u32| -> u32 {
|
||||
caller.data().message_get_len(id)
|
||||
}
|
||||
)?;
|
||||
|
||||
linker.func_wrap(
|
||||
module,
|
||||
"message_get_data",
|
||||
|mut caller: wasmtime::Caller<'_, T>, id: u32, ptr: u32| {
|
||||
let ptr = ptr as usize;
|
||||
let len = caller.data().message_get_len(id) as usize;
|
||||
let dst = Self::get_memory_slice_bytes(&mut caller, ptr, len);
|
||||
caller.data().message_get_data(id, dst)
|
||||
}
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -215,9 +239,11 @@ impl<T: ScriptAbi> WasmtimeScript<T> {
|
|||
}
|
||||
|
||||
impl<T: ScriptAbi> ScriptInstance for WasmtimeScript<T> {
|
||||
fn bind_panel(&mut self) -> PanelId {
|
||||
fn bind_panel(&mut self, msg: Vec<u8>) -> PanelId {
|
||||
let id = self.panel_datas.insert(0);
|
||||
let data = self.bind_panel.call(&mut self.store, id as u32).unwrap();
|
||||
let msg = self.store.data().message_new(msg);
|
||||
let args = (id as u32, msg);
|
||||
let data = self.bind_panel.call(&mut self.store, args).unwrap();
|
||||
*self.panel_datas.get_mut(id).unwrap() = data;
|
||||
PanelId(id)
|
||||
}
|
||||
|
@ -250,6 +276,7 @@ pub struct ScriptAbiImpl {
|
|||
font_families: Mutex<HashMap<String, u32>>,
|
||||
loaded_fonts: RwLock<Vec<Arc<text::Font>>>,
|
||||
text_layouts: RwLock<Slab<text::TextLayout>>,
|
||||
message_store: RwLock<Slab<Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl ScriptAbi for ScriptAbiImpl {
|
||||
|
@ -310,4 +337,25 @@ impl ScriptAbi for ScriptAbiImpl {
|
|||
let src = self.text_layouts.read().get(id as usize).unwrap().bounds;
|
||||
let _ = std::mem::replace(dst, src);
|
||||
}
|
||||
|
||||
fn message_new(&self, data: Vec<u8>) -> u32 {
|
||||
let mut store = self.message_store.write();
|
||||
let id = store.insert(data) as u32;
|
||||
id
|
||||
}
|
||||
|
||||
fn message_free(&self, id: u32) {
|
||||
let mut store = self.message_store.write();
|
||||
store.remove(id as usize);
|
||||
}
|
||||
|
||||
fn message_get_len(&self, id: u32) -> u32 {
|
||||
self.message_store.read().get(id as usize).unwrap().len() as u32
|
||||
}
|
||||
|
||||
fn message_get_data(&self, id: u32, dst: &mut [u8]) {
|
||||
let store = self.message_store.read();
|
||||
let src = store.get(id as usize).unwrap();
|
||||
dst.copy_from_slice(src);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue