From d037e956e8d0fedf0f3843f796785424c75e8761 Mon Sep 17 00:00:00 2001 From: T0mstone <39707032+T0mstone@users.noreply.github.com> Date: Mon, 29 Mar 2021 01:44:34 +0200 Subject: [PATCH] Implement basic circle stamping (#53) --- Cargo.lock | 7 --- .../src/components/panels/ViewportPanel.vue | 9 +++- client/web/src/wasm-callback-processor.js | 4 +- client/web/wasm/src/lib.rs | 6 +-- client/web/wasm/src/viewport.rs | 2 +- core/document/Cargo.toml | 1 + core/document/src/lib.rs | 30 +++++++++-- core/editor/src/dispatcher/events.rs | 2 +- core/editor/src/dispatcher/mod.rs | 50 +++++++++++-------- core/editor/src/lib.rs | 20 ++++++-- 10 files changed, 85 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc2858c3..ccf75d18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,7 +49,6 @@ name = "graphite-document-core" version = "0.1.0" dependencies = [ "kurbo", - "svg_fmt", ] [[package]] @@ -132,12 +131,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -[[package]] -name = "svg_fmt" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" - [[package]] name = "syn" version = "1.0.64" diff --git a/client/web/src/components/panels/ViewportPanel.vue b/client/web/src/components/panels/ViewportPanel.vue index 13907a4b..2c73e04d 100644 --- a/client/web/src/components/panels/ViewportPanel.vue +++ b/client/web/src/components/panels/ViewportPanel.vue @@ -17,7 +17,9 @@ @mousedown="canvasMouseDown" @mouseup="canvasMouseUp" @mousemove="canvasMouseMove" - > + > + + @@ -65,6 +67,11 @@ .canvas { background: #111; flex: 1 1 100%; + + svg { + width: 100%; + height: 100%; + } } } } diff --git a/client/web/src/wasm-callback-processor.js b/client/web/src/wasm-callback-processor.js index 3701dfa5..ed24414a 100644 --- a/client/web/src/wasm-callback-processor.js +++ b/client/web/src/wasm-callback-processor.js @@ -1,3 +1,3 @@ -export function update_canvas() { - console.log("update_canvas") +export function update_canvas(svg) { + document.querySelector(".canvas svg").innerHTML = svg; } diff --git a/client/web/wasm/src/lib.rs b/client/web/wasm/src/lib.rs index e56b01e0..74caaecc 100644 --- a/client/web/wasm/src/lib.rs +++ b/client/web/wasm/src/lib.rs @@ -9,7 +9,7 @@ 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(Box::new(handle_response)))} +thread_local! { pub static EDITOR_STATE: RefCell = RefCell::new(Editor::new(Box::new(handle_response))) } #[wasm_bindgen(start)] pub fn init() { @@ -18,13 +18,13 @@ pub fn init() { fn handle_response(response: Response) { match response { - Response::UpdateCanvas => update_canvas(), + Response::UpdateCanvas { document } => update_canvas(document), } } #[wasm_bindgen(module = "/../src/wasm-callback-processor.js")] extern "C" { - fn update_canvas(); + fn update_canvas(svg: String); } #[wasm_bindgen] diff --git a/client/web/wasm/src/viewport.rs b/client/web/wasm/src/viewport.rs index 6dcb50e4..8fe90b16 100644 --- a/client/web/wasm/src/viewport.rs +++ b/client/web/wasm/src/viewport.rs @@ -35,7 +35,7 @@ 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> { let mouse_keys = events::MouseKeys::from_bits(mouse_keys).expect("invalid modifier keys"); - let ev = events::Event::MouseDown(events::MouseState { + let ev = events::Event::MouseUp(events::MouseState { position: events::CanvasPosition { x, y }, mouse_keys, }); diff --git a/core/document/Cargo.toml b/core/document/Cargo.toml index 109121d3..bf7812d6 100644 --- a/core/document/Cargo.toml +++ b/core/document/Cargo.toml @@ -9,3 +9,4 @@ repository = "https://github.com/GraphiteEditor/Graphite" license = "Apache-2.0" [dependencies] +kurbo = "0.8.0" diff --git a/core/document/src/lib.rs b/core/document/src/lib.rs index 909562f6..de74d511 100644 --- a/core/document/src/lib.rs +++ b/core/document/src/lib.rs @@ -1,7 +1,27 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); +pub use kurbo::{Circle, Point}; + +#[derive(Debug, Clone, PartialEq)] +pub enum SvgElement { + Circle(Circle), +} + +impl SvgElement { + pub fn render(&self) -> String { + match self { + Self::Circle(c) => { + format!(r#""#, c.center.x, c.center.y, c.radius) + } + } + } +} + +#[derive(Default, Debug, Clone, PartialEq)] +pub struct Document { + pub svg: Vec, +} + +impl Document { + pub fn render(&self) -> String { + self.svg.iter().map(|element| element.render()).collect::>().join("\n") } } diff --git a/core/editor/src/dispatcher/events.rs b/core/editor/src/dispatcher/events.rs index 08459cc1..63389e15 100644 --- a/core/editor/src/dispatcher/events.rs +++ b/core/editor/src/dispatcher/events.rs @@ -22,7 +22,7 @@ pub enum Event { #[derive(Debug, Clone)] #[repr(C)] pub enum Response { - UpdateCanvas, + UpdateCanvas { document: String }, } #[derive(Debug, Clone, Default)] diff --git a/core/editor/src/dispatcher/mod.rs b/core/editor/src/dispatcher/mod.rs index 1c787953..d3aeec02 100644 --- a/core/editor/src/dispatcher/mod.rs +++ b/core/editor/src/dispatcher/mod.rs @@ -1,6 +1,6 @@ pub mod events; -use crate::tools::ToolState; -use crate::{Color, EditorError}; +use crate::{Color, EditorError, EditorState}; +use document_core::{Circle, Point, SvgElement}; use events::{Event, Response}; pub type Callback = Box; @@ -9,60 +9,68 @@ pub struct Dispatcher { } impl Dispatcher { - pub fn handle_event(&self, tool_state: &mut ToolState, event: Event) -> Result<(), EditorError> { + pub fn handle_event(&self, state: &mut EditorState, event: Event) -> Result<(), EditorError> { match event { Event::SelectTool(tool_type) => { - tool_state.active_tool = tool_type; + state.tools.active_tool = tool_type; Ok(()) } Event::SelectPrimaryColor(color) => { - tool_state.primary_color = color; + state.tools.primary_color = color; Ok(()) } Event::SelectSecondaryColor(color) => { - tool_state.secondary_color = color; + state.tools.secondary_color = color; Ok(()) } Event::SwapColors => { - std::mem::swap(&mut tool_state.primary_color, &mut tool_state.secondary_color); + std::mem::swap(&mut state.tools.primary_color, &mut state.tools.secondary_color); Ok(()) } Event::ResetColors => { - tool_state.primary_color = Color::BLACK; - tool_state.secondary_color = Color::WHITE; + state.tools.primary_color = Color::BLACK; + state.tools.secondary_color = Color::WHITE; Ok(()) } Event::MouseDown(mouse_state) => { - tool_state.mouse_state = mouse_state; + state.tools.mouse_state = mouse_state; // the state has changed so we add a trace point - tool_state.record_trace_point(); + state.tools.record_trace_point(); - self.emit_response(Response::UpdateCanvas); + // self.emit_response(Response::UpdateCanvas { document: state.document.render() }); Ok(()) } Event::MouseUp(mouse_state) => { - tool_state.mouse_state = mouse_state; + state.tools.mouse_state = mouse_state; // the state has changed so we add a trace point - tool_state.record_trace_point(); + state.tools.record_trace_point(); - self.emit_response(Response::UpdateCanvas); + state.document.svg.push(SvgElement::Circle(Circle { + center: Point { + x: mouse_state.position.x as f64, + y: mouse_state.position.y as f64, + }, + radius: 10.0, + })); + + self.emit_response(Response::UpdateCanvas { document: state.document.render() }); Ok(()) } Event::MouseMovement(pos) => { - tool_state.mouse_state.position = pos; - tool_state.record_trace_point(); + state.tools.mouse_state.position = pos; + state.tools.record_trace_point(); Ok(()) } Event::ModifierKeyDown(mod_keys) => { - tool_state.mod_keys = mod_keys; + state.tools.mod_keys = mod_keys; // the state has changed so we add a trace point - tool_state.record_trace_point(); + state.tools.record_trace_point(); Ok(()) } Event::ModifierKeyUp(mod_keys) => { - tool_state.mod_keys = mod_keys; + state.tools.mod_keys = mod_keys; // the state has changed so we add a trace point - tool_state.record_trace_point(); + state.tools.record_trace_point(); Ok(()) } Event::KeyPress(key) => todo!(), diff --git a/core/editor/src/lib.rs b/core/editor/src/lib.rs index 00f4daad..da17d39a 100644 --- a/core/editor/src/lib.rs +++ b/core/editor/src/lib.rs @@ -17,25 +17,35 @@ pub use dispatcher::events; pub use dispatcher::Callback; use dispatcher::Dispatcher; +use document_core::Document; use tools::ToolState; use workspace::Workspace; -// TODO: serialize with serde to save the current editor state -pub struct Editor { +pub struct EditorState { tools: ToolState, workspace: Workspace, + document: Document, +} + +// TODO: serialize with serde to save the current editor state +pub struct Editor { + state: EditorState, dispatcher: Dispatcher, } impl Editor { pub fn new(callback: Callback) -> Self { Self { - tools: ToolState::new(), - workspace: Workspace::new(), + state: EditorState { + tools: ToolState::new(), + workspace: Workspace::new(), + document: Document::default(), + }, dispatcher: Dispatcher::new(callback), } } + pub fn handle_event(&mut self, event: events::Event) -> Result<(), EditorError> { - self.dispatcher.handle_event(&mut self.tools, event) + self.dispatcher.handle_event(&mut self.state, event) } }