From 0e553adb32bedfd1a470e06fcfd981fc0b449734 Mon Sep 17 00:00:00 2001 From: TrueDoctor Date: Sun, 28 Mar 2021 00:23:41 +0100 Subject: [PATCH] Implement event/response roundtrip (#49) --- .../src/components/panels/ViewportPanel.vue | 11 ++++- client/web/src/wasm-callback-processor.js | 3 ++ client/web/wasm/src/lib.rs | 18 +++++--- client/web/wasm/src/viewport.rs | 15 +++++- .../src/{scheduler => dispatcher}/events.rs | 46 +++++++++++++------ core/editor/src/dispatcher/mod.rs | 24 ++++++++++ core/editor/src/error.rs | 4 ++ core/editor/src/lib.rs | 16 ++++++- core/editor/src/scheduler/mod.rs | 1 - 9 files changed, 112 insertions(+), 26 deletions(-) create mode 100644 client/web/src/wasm-callback-processor.js rename core/editor/src/{scheduler => dispatcher}/events.rs (62%) create mode 100644 core/editor/src/dispatcher/mod.rs delete mode 100644 core/editor/src/scheduler/mod.rs diff --git a/client/web/src/components/panels/ViewportPanel.vue b/client/web/src/components/panels/ViewportPanel.vue index ae05110c4..34358d60e 100644 --- a/client/web/src/components/panels/ViewportPanel.vue +++ b/client/web/src/components/panels/ViewportPanel.vue @@ -12,7 +12,7 @@ - + @@ -70,12 +70,19 @@ import { defineComponent } from "vue"; import LayoutRow from "../layout/LayoutRow.vue"; import LayoutCol from "../layout/LayoutCol.vue"; +const wasm = import("../../../wasm/pkg"); + export default defineComponent({ components: { LayoutRow, LayoutCol, }, - props: { + methods: { + async canvasClick(e: MouseEvent) { + console.log(e); + const { on_mouse_click } = await wasm; + on_mouse_click(e.offsetX, e.offsetY); + } }, }); diff --git a/client/web/src/wasm-callback-processor.js b/client/web/src/wasm-callback-processor.js new file mode 100644 index 000000000..3701dfa57 --- /dev/null +++ b/client/web/src/wasm-callback-processor.js @@ -0,0 +1,3 @@ +export function update_canvas() { + console.log("update_canvas") +} diff --git a/client/web/wasm/src/lib.rs b/client/web/wasm/src/lib.rs index e12e68caf..d451348c7 100644 --- a/client/web/wasm/src/lib.rs +++ b/client/web/wasm/src/lib.rs @@ -4,23 +4,27 @@ pub mod viewport; pub mod window; pub mod wrappers; -use graphite_editor_core::Editor; +use graphite_editor_core::{events::Response, Callback, Editor}; use std::cell::RefCell; use wasm_bindgen::prelude::*; // the thread_local macro provides a way to initialize static variables with non-constant functions -thread_local! {pub static EDITOR_STATE: RefCell = RefCell::new(Editor::new())} +thread_local! {pub static EDITOR_STATE: RefCell = RefCell::new(Editor::new(Box::new(handle_response)))} #[wasm_bindgen(start)] pub fn init() { utils::set_panic_hook(); } -/// Send events -#[wasm_bindgen] -pub fn handle_event(event_name: String) { - // TODO: add payload - todo!() +fn handle_response(response: Response) { + match response { + Response::UpdateCanvas => update_canvas(), + } +} + +#[wasm_bindgen(module = "/../src/wasm-callback-processor.js")] +extern "C" { + fn update_canvas(); } #[wasm_bindgen] diff --git a/client/web/wasm/src/viewport.rs b/client/web/wasm/src/viewport.rs index 61f55d2df..2f24d0d9c 100644 --- a/client/web/wasm/src/viewport.rs +++ b/client/web/wasm/src/viewport.rs @@ -1,6 +1,7 @@ use crate::shims::Error; use crate::wrappers::{translate_tool, Color}; use crate::EDITOR_STATE; +use graphite_editor_core::events; use wasm_bindgen::prelude::*; /// Modify the currently selected tool in the document state store @@ -15,10 +16,22 @@ pub fn select_tool(tool: String) -> Result<(), JsValue> { }) } +static mut POS: (u32, u32) = (0, 0); + /// Mouse movement with the bounds of the canvas #[wasm_bindgen] pub fn on_mouse_move(x: u32, y: u32) { - todo!() + // SAFETY: This is safe because the code can only ever run in a single thread + unsafe { + POS = (x, y); + } +} + +/// Mouse click within the bounds of the canvas +#[wasm_bindgen] +pub fn on_mouse_click(x: u32, y: u32) -> Result<(), JsValue> { + let ev = events::Event::Click(events::MouseState::from_pos(x, y)); + EDITOR_STATE.with(|editor| editor.borrow_mut().handle_event(ev)).map_err(|err| Error::new(&err.to_string()).into()) } /// Update working colors diff --git a/core/editor/src/scheduler/events.rs b/core/editor/src/dispatcher/events.rs similarity index 62% rename from core/editor/src/scheduler/events.rs rename to core/editor/src/dispatcher/events.rs index e4eff7710..41e096c37 100644 --- a/core/editor/src/scheduler/events.rs +++ b/core/editor/src/dispatcher/events.rs @@ -11,25 +11,45 @@ pub enum Event { } #[derive(Debug, Clone)] -struct Trace(Vec); -#[derive(Debug, Clone)] -struct MouseState { - x: u32, - y: u32, - mod_keys: ModKeys, - mouse_keys: MouseKeys, +#[repr(C)] +pub enum Response { + UpdateCanvas, } #[derive(Debug, Clone)] -enum Key { +pub struct Trace(Vec); +#[derive(Debug, Clone, Default)] +pub struct MouseState { + x: u32, + y: u32, + mod_keys: ModKeysStorage, + mouse_keys: MouseKeysStorage, +} + +impl MouseState { + pub const fn new() -> MouseState { + MouseState { + x: 0, + y: 0, + mod_keys: 0, + mouse_keys: 0, + } + } + pub const fn from_pos(x: u32, y: u32) -> MouseState { + MouseState { x, y, mod_keys: 0, mouse_keys: 0 } + } +} + +#[derive(Debug, Clone)] +pub enum Key { None, } -type ModKeysStorage = u8; -type MouseKeysStorage = u8; +pub type ModKeysStorage = u8; +pub type MouseKeysStorage = u8; #[derive(Debug, Clone, Copy)] #[repr(transparent)] -struct ModKeys(ModKeysStorage); +pub struct ModKeys(ModKeysStorage); impl ModKeys { pub fn get_key(&self, key: ModKey) -> bool { @@ -55,7 +75,7 @@ impl MouseKeys { #[repr(u8)] #[derive(Debug, Clone)] -enum ModKey { +pub enum ModKey { Control = 1, Shift = 2, Alt = 4, @@ -63,7 +83,7 @@ enum ModKey { #[repr(u8)] #[derive(Debug, Clone)] -enum MouseKey { +pub enum MouseKey { LeftMouse = 1, RightMouse = 2, MiddleMouse = 4, diff --git a/core/editor/src/dispatcher/mod.rs b/core/editor/src/dispatcher/mod.rs new file mode 100644 index 000000000..42208860d --- /dev/null +++ b/core/editor/src/dispatcher/mod.rs @@ -0,0 +1,24 @@ +pub mod events; +use crate::EditorError; +use events::{Event, Response}; + +pub type Callback = Box; +pub struct Dispatcher { + callback: Callback, +} + +impl Dispatcher { + pub fn handle_event(&self, event: Event) -> Result<(), EditorError> { + match event { + Event::Click(_) => Ok(self.emit_response(Response::UpdateCanvas)), + _ => todo!(), + } + } + pub fn emit_response(&self, response: Response) { + let func = &self.callback; + func(response) + } + pub fn new(callback: Callback) -> Dispatcher { + Dispatcher { callback } + } +} diff --git a/core/editor/src/error.rs b/core/editor/src/error.rs index 00b19e976..b238bf893 100644 --- a/core/editor/src/error.rs +++ b/core/editor/src/error.rs @@ -1,3 +1,4 @@ +use crate::events::Event; use crate::Color; use std::error::Error; use std::fmt::{self, Display}; @@ -6,6 +7,7 @@ use std::fmt::{self, Display}; #[derive(Clone, Debug)] pub enum EditorError { InvalidOperation(String), + InvalidEvent(String), Misc(String), Color(String), } @@ -14,6 +16,7 @@ impl Display for EditorError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { EditorError::InvalidOperation(e) => write!(f, "Failed to execute operation: {}", e), + EditorError::InvalidEvent(e) => write!(f, "Failed to dispatch event: {}", e), EditorError::Misc(e) => write!(f, "{}", e), EditorError::Color(c) => write!(f, "Tried to construct an invalid color {:?}", c), } @@ -35,3 +38,4 @@ macro_rules! derive_from { derive_from!(&str, Misc); derive_from!(String, Misc); derive_from!(Color, Color); +derive_from!(Event, InvalidEvent); diff --git a/core/editor/src/lib.rs b/core/editor/src/lib.rs index 6c5412c42..9d37f08c6 100644 --- a/core/editor/src/lib.rs +++ b/core/editor/src/lib.rs @@ -1,6 +1,6 @@ mod color; +mod dispatcher; mod error; -mod scheduler; pub mod tools; pub mod workspace; @@ -10,6 +10,13 @@ pub use error::EditorError; #[doc(inline)] pub use color::Color; +#[doc(inline)] +pub use dispatcher::events; + +#[doc(inline)] +pub use dispatcher::Callback; + +use dispatcher::Dispatcher; use tools::ToolState; use workspace::Workspace; @@ -17,13 +24,18 @@ use workspace::Workspace; pub struct Editor { pub tools: ToolState, workspace: Workspace, + dispatcher: Dispatcher, } impl Editor { - pub fn new() -> Self { + pub fn new(callback: Callback) -> Self { Self { tools: ToolState::new(), workspace: Workspace::new(), + dispatcher: Dispatcher::new(callback), } } + pub fn handle_event(&mut self, event: events::Event) -> Result<(), EditorError> { + self.dispatcher.handle_event(event) + } } diff --git a/core/editor/src/scheduler/mod.rs b/core/editor/src/scheduler/mod.rs deleted file mode 100644 index a9970c28f..000000000 --- a/core/editor/src/scheduler/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod events;