diff --git a/client/web/wasm/src/document.rs b/client/web/wasm/src/document.rs index 6de20fc1..9fed5774 100644 --- a/client/web/wasm/src/document.rs +++ b/client/web/wasm/src/document.rs @@ -7,7 +7,34 @@ use wasm_bindgen::prelude::*; fn convert_error(err: editor_core::EditorError) -> JsValue { Error::new(&err.to_string()).into() } +mod mouse_state { + pub(super) type MouseKeys = u8; + use editor_core::events::{self, Event, MouseState, ViewportPosition}; + static mut MOUSE_STATE: MouseKeys = 0; + pub(super) fn translate_mouse_down(mod_keys: MouseKeys, position: ViewportPosition) -> Event { + translate_mouse_event(mod_keys, position, true) + } + pub(super) fn translate_mouse_up(mod_keys: MouseKeys, position: ViewportPosition) -> Event { + translate_mouse_event(mod_keys, position, false) + } + + fn translate_mouse_event(mod_keys: MouseKeys, position: ViewportPosition, down: bool) -> Event { + let diff = unsafe { MOUSE_STATE } ^ mod_keys; + unsafe { MOUSE_STATE = mod_keys }; + let mouse_keys = events::MouseKeys::from_bits(mod_keys).expect("invalid modifier keys"); + let state = MouseState { position, mouse_keys }; + match (down, diff) { + (true, 1) => Event::LmbDown(state), + (true, 2) => Event::RmbDown(state), + (true, 4) => Event::MmbDown(state), + (false, 1) => Event::LmbUp(state), + (false, 2) => Event::RmbUp(state), + (false, 4) => Event::MmbUp(state), + _ => panic!("two buttons where modified at the same time. modification: {:#010b}", diff), + } + } +} /// Modify the currently selected tool in the document state store #[wasm_bindgen] pub fn select_tool(tool: String) -> Result<(), JsValue> { @@ -30,11 +57,8 @@ pub fn on_mouse_move(x: u32, y: u32) -> Result<(), JsValue> { #[wasm_bindgen] pub fn on_mouse_down(x: u32, y: u32, mouse_keys: u8) -> Result<(), JsValue> { // TODO: Convert these screenspace viewport coordinates to canvas coordinates based on the current zoom and pan - let mouse_keys = events::MouseKeys::from_bits(mouse_keys).expect("invalid modifier keys"); - let ev = events::Event::MouseDown(events::MouseState { - position: events::ViewportPosition { x, y }, - mouse_keys, - }); + let pos = events::ViewportPosition { x, y }; + let ev = mouse_state::translate_mouse_down(mouse_keys, pos); EDITOR_STATE.with(|editor| editor.borrow_mut().handle_event(ev)).map_err(convert_error) } @@ -42,11 +66,8 @@ pub fn on_mouse_down(x: u32, y: u32, mouse_keys: u8) -> Result<(), JsValue> { #[wasm_bindgen] pub fn on_mouse_up(x: u32, y: u32, mouse_keys: u8) -> Result<(), JsValue> { // TODO: Convert these screenspace viewport coordinates to canvas coordinates based on the current zoom and pan - let mouse_keys = events::MouseKeys::from_bits(mouse_keys).expect("invalid modifier keys"); - let ev = events::Event::MouseUp(events::MouseState { - position: events::ViewportPosition { x, y }, - mouse_keys, - }); + let pos = events::ViewportPosition { x, y }; + let ev = mouse_state::translate_mouse_up(mouse_keys, pos); EDITOR_STATE.with(|editor| editor.borrow_mut().handle_event(ev)).map_err(convert_error) } diff --git a/core/editor/src/dispatcher/events.rs b/core/editor/src/dispatcher/events.rs index a2c8e60d..d47caf8f 100644 --- a/core/editor/src/dispatcher/events.rs +++ b/core/editor/src/dispatcher/events.rs @@ -14,8 +14,12 @@ pub enum Event { SelectSecondaryColor(Color), SwapColors, ResetColors, - MouseDown(MouseState), - MouseUp(MouseState), + LmbDown(MouseState), + RmbDown(MouseState), + MmbDown(MouseState), + LmbUp(MouseState), + RmbUp(MouseState), + MmbUp(MouseState), MouseMove(ViewportPosition), KeyUp(Key), KeyDown(Key), diff --git a/core/editor/src/dispatcher/mod.rs b/core/editor/src/dispatcher/mod.rs index d90096d5..b5b40312 100644 --- a/core/editor/src/dispatcher/mod.rs +++ b/core/editor/src/dispatcher/mod.rs @@ -30,16 +30,28 @@ impl Dispatcher { editor_state.tool_state.document_tool_data.primary_color = Color::BLACK; editor_state.tool_state.document_tool_data.secondary_color = Color::WHITE; } - Event::MouseDown(mouse_state) => { + Event::LmbDown(mouse_state) => { editor_state.tool_state.document_tool_data.mouse_state = *mouse_state; } - Event::MouseUp(mouse_state) => { + Event::RmbDown(mouse_state) => { + editor_state.tool_state.document_tool_data.mouse_state = *mouse_state; + } + Event::MmbDown(mouse_state) => { + editor_state.tool_state.document_tool_data.mouse_state = *mouse_state; + } + Event::LmbUp(mouse_state) => { + editor_state.tool_state.document_tool_data.mouse_state = *mouse_state; + } + Event::RmbUp(mouse_state) => { + editor_state.tool_state.document_tool_data.mouse_state = *mouse_state; + } + Event::MmbUp(mouse_state) => { editor_state.tool_state.document_tool_data.mouse_state = *mouse_state; } Event::MouseMove(pos) => { editor_state.tool_state.document_tool_data.mouse_state.position = *pos; } - Event::KeyUp(key) => (), + Event::KeyUp(_key) => (), Event::KeyDown(key) => { log::trace!("pressed key {:?}", key); log::debug!("pressed key {:?}", key); @@ -102,7 +114,7 @@ impl Dispatcher { .handle_input(event, &editor_state.document, &editor_state.tool_state.document_tool_data); self.dispatch_operations(&mut editor_state.document, operations); - // TODO - Dispatch Responses + self.dispatch_responses(responses); Ok(()) } @@ -128,7 +140,6 @@ impl Dispatcher { pub fn dispatch_response(&self, response: Response) { let func = &self.callback; - // TODO - Remove clone if possible func(response) } diff --git a/core/editor/src/tools/ellipse.rs b/core/editor/src/tools/ellipse.rs index 53263f85..f62b00c8 100644 --- a/core/editor/src/tools/ellipse.rs +++ b/core/editor/src/tools/ellipse.rs @@ -1,5 +1,5 @@ use crate::events::{Event, Response}; -use crate::events::{Key, MouseKeys, ViewportPosition}; +use crate::events::{Key, ViewportPosition}; use crate::tools::{Fsm, Tool}; use crate::Document; use document_core::layers::style; @@ -42,9 +42,9 @@ struct EllipseToolData { impl Fsm for EllipseToolFsmState { type ToolData = EllipseToolData; - fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, responses: &mut Vec, operations: &mut Vec) -> Self { + fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, _responses: &mut Vec, operations: &mut Vec) -> Self { match (self, event) { - (EllipseToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => { + (EllipseToolFsmState::Ready, Event::LmbDown(mouse_state)) => { data.drag_start = mouse_state.position; operations.push(Operation::MountWorkingFolder { path: vec![] }); EllipseToolFsmState::LmbDown @@ -71,8 +71,7 @@ impl Fsm for EllipseToolFsmState { EllipseToolFsmState::LmbDown } - // TODO - Check for left mouse button - (EllipseToolFsmState::LmbDown, Event::MouseUp(mouse_state)) => { + (EllipseToolFsmState::LmbDown, Event::LmbUp(mouse_state)) => { let r = data.drag_start.distance(&mouse_state.position); log::info!("draw ellipse with radius: {:.2}", r); operations.push(Operation::ClearWorkingFolder); diff --git a/core/editor/src/tools/line.rs b/core/editor/src/tools/line.rs index acd019bd..6d841b13 100644 --- a/core/editor/src/tools/line.rs +++ b/core/editor/src/tools/line.rs @@ -1,5 +1,5 @@ use crate::events::{Event, Response}; -use crate::events::{Key, MouseKeys, ViewportPosition}; +use crate::events::{Key, ViewportPosition}; use crate::tools::{Fsm, Tool}; use crate::Document; use document_core::layers::style; @@ -42,9 +42,9 @@ struct LineToolData { impl Fsm for LineToolFsmState { type ToolData = LineToolData; - fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, responses: &mut Vec, operations: &mut Vec) -> Self { + fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, _responses: &mut Vec, operations: &mut Vec) -> Self { match (self, event) { - (LineToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => { + (LineToolFsmState::Ready, Event::LmbDown(mouse_state)) => { data.drag_start = mouse_state.position; operations.push(Operation::MountWorkingFolder { path: vec![] }); LineToolFsmState::LmbDown @@ -71,8 +71,7 @@ impl Fsm for LineToolFsmState { LineToolFsmState::LmbDown } - // TODO - Check for left mouse button - (LineToolFsmState::LmbDown, Event::MouseUp(mouse_state)) => { + (LineToolFsmState::LmbDown, Event::LmbUp(mouse_state)) => { let distance = data.drag_start.distance(&mouse_state.position); log::info!("draw Line with distance: {:.2}", distance); operations.push(Operation::ClearWorkingFolder); diff --git a/core/editor/src/tools/pen.rs b/core/editor/src/tools/pen.rs index 5d72a478..74e96666 100644 --- a/core/editor/src/tools/pen.rs +++ b/core/editor/src/tools/pen.rs @@ -1,5 +1,5 @@ use crate::events::{Event, Response}; -use crate::events::{Key, MouseKeys, ViewportPosition}; +use crate::events::{Key, ViewportPosition}; use crate::tools::{Fsm, Tool}; use crate::Document; @@ -49,7 +49,7 @@ impl Fsm for PenToolFsmState { let style = style::PathStyle::new(Some(stroke), Some(fill)); match (self, event) { - (PenToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => { + (PenToolFsmState::Ready, Event::LmbDown(mouse_state)) => { operations.push(Operation::MountWorkingFolder { path: vec![] }); data.points.push(mouse_state.position); PenToolFsmState::LmbDown @@ -60,8 +60,7 @@ impl Fsm for PenToolFsmState { } PenToolFsmState::Ready } - // TODO - Check for left mouse button - (PenToolFsmState::LmbDown, Event::MouseDown(mouse_state)) => { + (PenToolFsmState::LmbDown, Event::LmbUp(mouse_state)) => { data.points.push(mouse_state.position); PenToolFsmState::LmbDown } diff --git a/core/editor/src/tools/rectangle.rs b/core/editor/src/tools/rectangle.rs index be5734da..060da7a5 100644 --- a/core/editor/src/tools/rectangle.rs +++ b/core/editor/src/tools/rectangle.rs @@ -1,5 +1,5 @@ use crate::events::{Event, Response}; -use crate::events::{Key, MouseKeys, ViewportPosition}; +use crate::events::{Key, ViewportPosition}; use crate::tools::{Fsm, Tool}; use crate::Document; use document_core::layers::style; @@ -42,9 +42,9 @@ struct RectangleToolData { impl Fsm for RectangleToolFsmState { type ToolData = RectangleToolData; - fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, responses: &mut Vec, operations: &mut Vec) -> Self { + fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, _responses: &mut Vec, operations: &mut Vec) -> Self { match (self, event) { - (RectangleToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => { + (RectangleToolFsmState::Ready, Event::LmbDown(mouse_state)) => { data.drag_start = mouse_state.position; operations.push(Operation::MountWorkingFolder { path: vec![] }); RectangleToolFsmState::LmbDown @@ -71,8 +71,7 @@ impl Fsm for RectangleToolFsmState { RectangleToolFsmState::LmbDown } - // TODO - Check for left mouse button - (RectangleToolFsmState::LmbDown, Event::MouseUp(mouse_state)) => { + (RectangleToolFsmState::LmbDown, Event::LmbUp(mouse_state)) => { let r = data.drag_start.distance(&mouse_state.position); log::info!("draw rectangle with radius: {:.2}", r); operations.push(Operation::ClearWorkingFolder); diff --git a/core/editor/src/tools/select.rs b/core/editor/src/tools/select.rs index a1585f76..33da717a 100644 --- a/core/editor/src/tools/select.rs +++ b/core/editor/src/tools/select.rs @@ -1,4 +1,3 @@ -use crate::events::MouseKeys; use crate::events::{Event, Response}; use crate::tools::{Fsm, Tool}; use crate::Document; @@ -41,17 +40,17 @@ struct SelectToolData; impl Fsm for SelectToolFsmState { type ToolData = SelectToolData; - fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, responses: &mut Vec, operations: &mut Vec) -> Self { + fn transition(self, event: &Event, _document: &Document, _tool_data: &DocumentToolData, _data: &mut Self::ToolData, _responses: &mut Vec, _operations: &mut Vec) -> Self { match (self, event) { - (SelectToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => SelectToolFsmState::LmbDown, + (SelectToolFsmState::Ready, Event::LmbDown(_mouse_state)) => SelectToolFsmState::LmbDown, - (SelectToolFsmState::LmbDown, Event::MouseUp(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => SelectToolFsmState::Ready, + (SelectToolFsmState::LmbDown, Event::LmbUp(_mouse_state)) => SelectToolFsmState::Ready, - (SelectToolFsmState::LmbDown, Event::MouseMove(mouse_state)) => SelectToolFsmState::TransformSelected, + (SelectToolFsmState::LmbDown, Event::MouseMove(_mouse_state)) => SelectToolFsmState::TransformSelected, - (SelectToolFsmState::TransformSelected, Event::MouseMove(mouse_state)) => self, + (SelectToolFsmState::TransformSelected, Event::MouseMove(_mouse_state)) => self, - (SelectToolFsmState::TransformSelected, Event::MouseUp(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => SelectToolFsmState::Ready, + (SelectToolFsmState::TransformSelected, Event::LmbUp(_mouse_state)) => SelectToolFsmState::Ready, _ => self, } diff --git a/core/editor/src/tools/shape.rs b/core/editor/src/tools/shape.rs index e925a9d5..bdc05dd1 100644 --- a/core/editor/src/tools/shape.rs +++ b/core/editor/src/tools/shape.rs @@ -1,5 +1,5 @@ use crate::events::{Event, Response}; -use crate::events::{Key, MouseKeys, ViewportPosition}; +use crate::events::{Key, ViewportPosition}; use crate::tools::{Fsm, Tool}; use crate::Document; use document_core::layers::style; @@ -43,9 +43,9 @@ struct ShapeToolData { impl Fsm for ShapeToolFsmState { type ToolData = ShapeToolData; - fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, responses: &mut Vec, operations: &mut Vec) -> Self { + fn transition(self, event: &Event, document: &Document, tool_data: &DocumentToolData, data: &mut Self::ToolData, _responses: &mut Vec, operations: &mut Vec) -> Self { match (self, event) { - (ShapeToolFsmState::Ready, Event::MouseDown(mouse_state)) if mouse_state.mouse_keys.contains(MouseKeys::LEFT) => { + (ShapeToolFsmState::Ready, Event::LmbDown(mouse_state)) => { data.drag_start = mouse_state.position; operations.push(Operation::MountWorkingFolder { path: vec![] }); ShapeToolFsmState::LmbDown @@ -73,15 +73,15 @@ impl Fsm for ShapeToolFsmState { ShapeToolFsmState::LmbDown } - // TODO - Check for left mouse button - (ShapeToolFsmState::LmbDown, Event::MouseUp(mouse_state)) => { + (ShapeToolFsmState::LmbDown, Event::LmbUp(mouse_state)) => { let r = data.drag_start.distance(&mouse_state.position); log::info!("Draw Shape with radius: {:.2}", r); let start = data.drag_start; let end = mouse_state.position; // TODO: Set the sides value and use it for the operation. - let sides = data.sides; + // let sides = data.sides; + let sides = 6; operations.push(Operation::ClearWorkingFolder); operations.push(Operation::AddShape { path: vec![], @@ -90,7 +90,7 @@ impl Fsm for ShapeToolFsmState { y0: start.y as f64, x1: end.x as f64, y1: end.y as f64, - sides: 6, + sides, style: style::PathStyle::new(None, Some(style::Fill::new(tool_data.primary_color))), }); operations.push(Operation::CommitTransaction);