Support multiple panels per script

This commit is contained in:
mars 2022-07-31 00:15:04 -06:00
parent d54a59b3e8
commit 0ccf787f99
3 changed files with 57 additions and 39 deletions

View File

@ -26,6 +26,7 @@ fn main() {
struct App {
script: canary::WasmtimeScript<canary::ScriptAbiImpl>,
panel: canary::PanelId,
last_update: Instant,
}
@ -34,10 +35,12 @@ impl App {
let runtime = canary::WasmtimeRuntime::new().unwrap();
let abi = canary::ScriptAbiImpl::default();
let module = std::fs::read(module_path).unwrap();
let script = runtime.load_module(abi, &module).unwrap();
let mut script = runtime.load_module(abi, &module).unwrap();
let panel = script.bind_panel();
Self {
script,
panel,
last_update: Instant::now(),
}
}
@ -49,7 +52,7 @@ impl eframe::App for App {
let dt = self.last_update.elapsed().as_secs_f32();
self.last_update = Instant::now();
self.script.update(dt);
self.script.update(self.panel, dt);
egui::Window::new("Panel").show(ctx, |ui| {
let size = egui::vec2(800.0, 800.0);
@ -78,14 +81,14 @@ impl eframe::App for App {
CursorEventKind::Hover
};
self.script.on_cursor_event(kind, pos);
self.script.on_cursor_event(self.panel, kind, pos);
}
let texture = egui::TextureId::Managed(0);
let uv = egui::pos2(0.0, 0.0);
let mut mesh = egui::Mesh::with_texture(texture);
self.script.draw(|commands| {
self.script.draw(self.panel, |commands| {
for command in commands.iter() {
let voff = mesh.vertices.len() as u32;

View File

@ -11,18 +11,18 @@ macro_rules! export_abi {
}
#[no_mangle]
pub extern "C" fn update(dt: f32) {
::canary_script::abi::update(dt)
pub extern "C" fn update(panel_data: u32, dt: f32) {
::canary_script::abi::update(panel_data, dt)
}
#[no_mangle]
pub extern "C" fn draw() {
::canary_script::abi::draw()
pub extern "C" fn draw(panel_data: u32) {
::canary_script::abi::draw(panel_data)
}
#[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 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)
}
};
}
@ -43,24 +43,18 @@ pub mod abi {
}
}
pub fn update(dt: f32) {
unsafe {
for panel in PANEL_IMPLS.iter_mut() {
panel.update(dt);
}
}
pub fn update(panel_data: u32, dt: f32) {
let panel = unsafe { &mut PANEL_IMPLS[panel_data as usize] };
panel.update(dt);
}
pub fn draw() {
unsafe {
for panel in PANEL_IMPLS.iter_mut() {
panel.draw();
}
}
pub fn draw(panel_data: u32) {
let panel = unsafe { &mut PANEL_IMPLS[panel_data as usize] };
panel.draw();
}
pub fn on_cursor_event(kind: u32, x: f32, y: f32) {
let panel = unsafe { &mut PANEL_IMPLS[0] };
pub fn on_cursor_event(panel_data: u32, kind: u32, x: f32, y: f32) {
let panel = unsafe { &mut PANEL_IMPLS[panel_data as usize] };
let at = canary_types::Vec2 { x, y };
let kind = CursorEventKind::from_u32(kind).unwrap();
panel.on_cursor_event(kind, at);

View File

@ -23,10 +23,14 @@ pub trait ScriptAbi {
fn text_layout_get_bounds(&self, id: u32, rect: &mut Rect);
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PanelId(pub(crate) usize);
pub trait ScriptInstance {
fn update(&mut self, dt: f32);
fn draw(&mut self, f: impl FnOnce(&[DrawCommand]));
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2);
fn bind_panel(&mut self) -> 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);
}
#[non_exhaustive]
@ -60,18 +64,19 @@ impl WasmtimeRuntime {
) -> anyhow::Result<WasmtimeScript<T>> {
let module = wasmtime::Module::new(&self.engine, module)?;
let mut store = wasmtime::Store::new(&self.engine, abi);
let panel_datas = Default::default();
let mut linker = wasmtime::Linker::new(&self.engine);
WasmtimeScript::link(&mut linker)?;
let instance = linker.instantiate(&mut store, &module)?;
let bind_panel = instance.get_typed_func(&mut store, "bind_panel")?;
let update = instance.get_typed_func(&mut store, "update")?;
let draw = instance.get_typed_func(&mut store, "draw")?;
let on_cursor_event = instance.get_typed_func(&mut store, "on_cursor_event")?;
let bind_panel = instance.get_typed_func::<u32, u32, _>(&mut store, "bind_panel")?;
bind_panel.call(&mut store, 0u32)?;
Ok(WasmtimeScript {
store,
panel_datas,
bind_panel,
update,
draw,
on_cursor_event,
@ -81,9 +86,11 @@ impl WasmtimeRuntime {
pub struct WasmtimeScript<T> {
store: wasmtime::Store<T>,
update: wasmtime::TypedFunc<f32, ()>,
draw: wasmtime::TypedFunc<(), ()>,
on_cursor_event: wasmtime::TypedFunc<(u32, f32, f32), ()>,
panel_datas: Slab<u32>,
bind_panel: wasmtime::TypedFunc<u32, u32>,
update: wasmtime::TypedFunc<(u32, f32), ()>,
draw: wasmtime::TypedFunc<u32, ()>,
on_cursor_event: wasmtime::TypedFunc<(u32, u32, f32, f32), ()>,
}
impl<T: ScriptAbi> WasmtimeScript<T> {
@ -158,6 +165,10 @@ impl<T: ScriptAbi> WasmtimeScript<T> {
Ok(())
}
fn get_panel_data(&self, panel: PanelId) -> u32 {
*self.panel_datas.get(panel.0).unwrap()
}
fn get_memory_ref<D: bytemuck::Pod>(
caller: &mut wasmtime::Caller<'_, T>,
ptr: u32,
@ -204,19 +215,29 @@ impl<T: ScriptAbi> WasmtimeScript<T> {
}
impl<T: ScriptAbi> ScriptInstance for WasmtimeScript<T> {
fn update(&mut self, dt: f32) {
self.update.call(&mut self.store, dt).unwrap();
fn bind_panel(&mut self) -> PanelId {
let id = self.panel_datas.insert(0);
let data = self.bind_panel.call(&mut self.store, id as u32).unwrap();
*self.panel_datas.get_mut(id).unwrap() = data;
PanelId(id)
}
fn draw(&mut self, f: impl FnOnce(&[DrawCommand])) {
fn update(&mut self, panel: PanelId, dt: f32) {
let data = self.get_panel_data(panel);
self.update.call(&mut self.store, (data, dt)).unwrap();
}
fn draw(&mut self, panel: PanelId, f: impl FnOnce(&[DrawCommand])) {
let data = self.get_panel_data(panel);
self.store.data().start_draw();
self.draw.call(&mut self.store, ()).unwrap();
self.draw.call(&mut self.store, data).unwrap();
self.store.data().with_draw_commands(f);
}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
fn on_cursor_event(&mut self, panel: PanelId, kind: CursorEventKind, at: Vec2) {
let data = self.get_panel_data(panel);
self.on_cursor_event
.call(&mut self.store, (kind as u32, at.x, at.y))
.call(&mut self.store, (data, kind as u32, at.x, at.y))
.unwrap();
}
}