Add Message and bind_panel() message

This commit is contained in:
mars 2022-08-16 18:11:56 -06:00
parent 9aa71b4cea
commit 237ef96dfa
5 changed files with 102 additions and 15 deletions

View File

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

View File

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

View File

@ -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 {

View File

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

View File

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