From b7a6413c21d81caddbc3c904f2170329869a6264 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Fri, 13 Aug 2021 19:24:50 -0700 Subject: [PATCH 1/4] Refactor ViewportPosition from u32 (UVec2) to f64 (DVec2) --- editor/src/communication/dispatcher.rs | 10 ++++----- editor/src/communication/mod.rs | 2 +- editor/src/document/document_file.rs | 4 ++-- editor/src/document/movement_handler.rs | 19 ++++++++-------- editor/src/input/input_preprocessor.rs | 29 ++++++++++++++++++++++--- editor/src/input/mouse.rs | 13 ++++++----- editor/src/misc/test_utils.rs | 24 ++++++++++---------- editor/src/tool/tools/eyedropper.rs | 2 +- editor/src/tool/tools/fill.rs | 2 +- editor/src/tool/tools/line.rs | 4 ++-- editor/src/tool/tools/pen.rs | 2 +- editor/src/tool/tools/resize.rs | 4 ++-- editor/src/tool/tools/select.rs | 10 ++++----- frontend/wasm/src/document.rs | 9 ++++---- 14 files changed, 79 insertions(+), 55 deletions(-) diff --git a/editor/src/communication/dispatcher.rs b/editor/src/communication/dispatcher.rs index d7974cf61a..0e2316865e 100644 --- a/editor/src/communication/dispatcher.rs +++ b/editor/src/communication/dispatcher.rs @@ -100,11 +100,11 @@ mod test { })); editor.select_primary_color(Color::RED); - editor.draw_rect(100, 200, 300, 400); + editor.draw_rect(100., 200., 300., 400.); editor.select_primary_color(Color::BLUE); - editor.draw_shape(10, 1200, 1300, 400); + editor.draw_shape(10., 1200., 1300., 400.); editor.select_primary_color(Color::GREEN); - editor.draw_ellipse(104, 1200, 1300, 400); + editor.draw_ellipse(104., 1200., 1300., 400.); editor } @@ -278,7 +278,7 @@ mod test { editor.handle_message(DocumentMessage::SelectLayers(vec![vec![rect_id], vec![ellipse_id]])).unwrap(); editor.handle_message(DocumentsMessage::CopySelectedLayers).unwrap(); editor.handle_message(DocumentMessage::DeleteSelectedLayers).unwrap(); - editor.draw_rect(0, 800, 12, 200); + editor.draw_rect(0., 800., 12., 200.); editor.handle_message(DocumentsMessage::PasteLayers { path: vec![], insert_index: -1 }).unwrap(); editor.handle_message(DocumentsMessage::PasteLayers { path: vec![], insert_index: -1 }).unwrap(); @@ -303,7 +303,7 @@ mod test { /// - create rect, shape and ellipse /// - select ellipse and rect /// - move them down and back up again - fn move_seletion() { + fn move_selection() { init_logger(); let mut editor = create_editor_with_three_layers(); diff --git a/editor/src/communication/mod.rs b/editor/src/communication/mod.rs index 8229ac261d..0e1dfb1879 100644 --- a/editor/src/communication/mod.rs +++ b/editor/src/communication/mod.rs @@ -28,7 +28,7 @@ where pub fn generate_hash<'a>(messages: impl IntoIterator, ipp: &InputPreprocessor, document_hash: u64) -> u64 { let mut s = DefaultHasher::new(); document_hash.hash(&mut s); - ipp.hash(&mut s); + ipp.pseudo_hash(); for message in messages { message.pseudo_hash().hash(&mut s); } diff --git a/editor/src/document/document_file.rs b/editor/src/document/document_file.rs index 8e613ca59f..23ebc35d60 100644 --- a/editor/src/document/document_file.rs +++ b/editor/src/document/document_file.rs @@ -225,7 +225,7 @@ impl DocumentMessageHandler { } /// Returns a list of `LayerPanelEntry`s intended for display purposes. These don't contain - /// any actual data, but ratfolderch as visibility and names of the layers. + /// any actual data, but rather attributes such as visibility and names of the layers. pub fn layer_panel(&mut self, path: &[LayerId]) -> Result, EditorError> { let folder = self.document.folder(path)?; let paths: Vec> = folder.layer_ids.iter().map(|id| [path, &[*id]].concat()).collect(); @@ -267,7 +267,7 @@ impl MessageHandler for DocumentMessageHand } CommitTransaction => self.document_backup = None, ExportDocument => { - let bbox = self.document.visible_layers_bounding_box().unwrap_or([DVec2::ZERO, ipp.viewport_size.as_f64()]); + let bbox = self.document.visible_layers_bounding_box().unwrap_or([DVec2::ZERO, ipp.viewport_size]); let size = bbox[1] - bbox[0]; responses.push_back( FrontendMessage::ExportDocument { diff --git a/editor/src/document/movement_handler.rs b/editor/src/document/movement_handler.rs index d28d604e7e..03bf542cd5 100644 --- a/editor/src/document/movement_handler.rs +++ b/editor/src/document/movement_handler.rs @@ -32,7 +32,7 @@ pub enum MovementMessage { ZoomCanvasToFitAll, } -#[derive(Debug, Clone, Hash, Default, PartialEq)] +#[derive(Debug, Clone, Default, PartialEq)] pub struct MovementMessageHandler { translating: bool, rotating: bool, @@ -43,7 +43,7 @@ pub struct MovementMessageHandler { impl MovementMessageHandler { fn create_document_transform_from_layerdata(&self, layerdata: &LayerData, viewport_size: &ViewportPosition, responses: &mut VecDeque) { - let half_viewport = viewport_size.as_f64() / 2.; + let half_viewport = *viewport_size / 2.; let scaled_half_viewport = half_viewport / layerdata.scale; responses.push_back( DocumentOperation::SetLayerTransform { @@ -64,7 +64,6 @@ impl MessageHandler { self.rotating = true; self.snapping = snap; @@ -86,17 +85,17 @@ impl MessageHandler { if self.translating { - let delta = ipp.mouse.position.as_f64() - self.mouse_pos.as_f64(); + let delta = ipp.mouse.position - self.mouse_pos; let transformed_delta = document.root.transform.inverse().transform_vector2(delta); layerdata.translation += transformed_delta; self.create_document_transform_from_layerdata(layerdata, &ipp.viewport_size, responses); } if self.rotating { - let half_viewport = ipp.viewport_size.as_f64() / 2.; + let half_viewport = ipp.viewport_size / 2.; let rotation = { - let start_vec = self.mouse_pos.as_f64() - half_viewport; - let end_vec = ipp.mouse.position.as_f64() - half_viewport; + let start_vec = self.mouse_pos - half_viewport; + let end_vec = ipp.mouse.position - half_viewport; start_vec.angle_between(end_vec) }; @@ -140,8 +139,8 @@ impl MessageHandler { let scroll = ipp.mouse.scroll_delta.scroll_delta(); - let mouse = ipp.mouse.position.as_f64(); - let viewport_size = ipp.viewport_size.as_f64(); + let mouse = ipp.mouse.position; + let viewport_size = ipp.viewport_size; let mut zoom_factor = 1. + scroll.abs() * VIEWPORT_ZOOM_WHEEL_RATE; if ipp.mouse.scroll_delta.y > 0 { zoom_factor = 1. / zoom_factor @@ -177,7 +176,7 @@ impl MessageHandler &[u8] { + core::slice::from_raw_parts(self as *const InputPreprocessor as *const u8, std::mem::size_of::()) + } + /// Returns a pseudo hash that should uniquely identify the message. + /// This is needed because `Hash` is not implemented for f64s + /// + /// # Safety + /// This function reads from uninitialized memory but the generated value should be fine. + pub fn pseudo_hash(&self) -> u64 { + let mut s = DefaultHasher::new(); + unsafe { self.as_slice() }.hash(&mut s); + s.finish() + } +} + enum KeyPosition { Pressed, Released, @@ -81,7 +104,7 @@ impl MessageHandler for InputPreprocessor { responses.push_back( graphene::Operation::TransformLayer { path: vec![], - transform: glam::DAffine2::from_translation((size.as_f64() - self.viewport_size.as_f64()) / 2.).to_cols_array(), + transform: glam::DAffine2::from_translation((size - self.viewport_size) / 2.).to_cols_array(), } .into(), ); @@ -141,7 +164,7 @@ mod test { #[test] fn process_action_mouse_move_handle_modifier_keys() { let mut input_preprocessor = InputPreprocessor::default(); - let message = InputPreprocessorMessage::MouseMove((4, 809).into(), ModifierKeys::ALT); + let message = InputPreprocessorMessage::MouseMove((4., 809.).into(), ModifierKeys::ALT); let mut responses = VecDeque::new(); input_preprocessor.process_action(message, (), &mut responses); diff --git a/editor/src/input/mouse.rs b/editor/src/input/mouse.rs index 1d6bf7e9ae..925c487ab1 100644 --- a/editor/src/input/mouse.rs +++ b/editor/src/input/mouse.rs @@ -1,8 +1,8 @@ use bitflags::bitflags; use glam::DVec2; -// origin is top left -pub type ViewportPosition = glam::UVec2; +// Origin is top left +pub type ViewportPosition = DVec2; #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)] pub struct ScrollDelta { @@ -23,7 +23,7 @@ impl ScrollDelta { } } -#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)] +#[derive(Debug, Copy, Clone, Default, PartialEq)] pub struct MouseState { pub position: ViewportPosition, pub mouse_keys: MouseKeys, @@ -31,17 +31,18 @@ pub struct MouseState { } impl MouseState { - pub fn new() -> MouseState { + pub fn new() -> Self { Self::default() } - pub fn from_pos(x: u32, y: u32) -> MouseState { - MouseState { + pub fn from_pos(x: f64, y: f64) -> Self { + Self { position: (x, y).into(), mouse_keys: MouseKeys::default(), scroll_delta: ScrollDelta::default(), } } + pub fn from_u8_pos(keys: u8, position: ViewportPosition) -> Self { let mouse_keys = MouseKeys::from_bits(keys).expect("invalid modifier keys"); Self { diff --git a/editor/src/misc/test_utils.rs b/editor/src/misc/test_utils.rs index fe91dbcc3f..89c0d6711e 100644 --- a/editor/src/misc/test_utils.rs +++ b/editor/src/misc/test_utils.rs @@ -11,35 +11,35 @@ use graphene::color::Color; /// A set of utility functions to make the writing of editor test more declarative pub trait EditorTestUtils { - fn draw_rect(&mut self, x1: u32, y1: u32, x2: u32, y2: u32); - fn draw_shape(&mut self, x1: u32, y1: u32, x2: u32, y2: u32); - fn draw_ellipse(&mut self, x1: u32, y1: u32, x2: u32, y2: u32); + fn draw_rect(&mut self, x1: f64, y1: f64, x2: f64, y2: f64); + fn draw_shape(&mut self, x1: f64, y1: f64, x2: f64, y2: f64); + fn draw_ellipse(&mut self, x1: f64, y1: f64, x2: f64, y2: f64); /// Select given tool and drag it from (x1, y1) to (x2, y2) - fn drag_tool(&mut self, typ: ToolType, x1: u32, y1: u32, x2: u32, y2: u32); - fn move_mouse(&mut self, x: u32, y: u32); + fn drag_tool(&mut self, typ: ToolType, x1: f64, y1: f64, x2: f64, y2: f64); + fn move_mouse(&mut self, x: f64, y: f64); fn mousedown(&mut self, state: MouseState); fn mouseup(&mut self, state: MouseState); - fn lmb_mousedown(&mut self, x: u32, y: u32); + fn lmb_mousedown(&mut self, x: f64, y: f64); fn input(&mut self, message: InputPreprocessorMessage); fn select_tool(&mut self, typ: ToolType); fn select_primary_color(&mut self, color: Color); } impl EditorTestUtils for Editor { - fn draw_rect(&mut self, x1: u32, y1: u32, x2: u32, y2: u32) { + fn draw_rect(&mut self, x1: f64, y1: f64, x2: f64, y2: f64) { self.drag_tool(ToolType::Rectangle, x1, y1, x2, y2); } - fn draw_shape(&mut self, x1: u32, y1: u32, x2: u32, y2: u32) { + fn draw_shape(&mut self, x1: f64, y1: f64, x2: f64, y2: f64) { self.drag_tool(ToolType::Shape, x1, y1, x2, y2); } - fn draw_ellipse(&mut self, x1: u32, y1: u32, x2: u32, y2: u32) { + fn draw_ellipse(&mut self, x1: f64, y1: f64, x2: f64, y2: f64) { self.drag_tool(ToolType::Ellipse, x1, y1, x2, y2); } - fn drag_tool(&mut self, typ: ToolType, x1: u32, y1: u32, x2: u32, y2: u32) { + fn drag_tool(&mut self, typ: ToolType, x1: f64, y1: f64, x2: f64, y2: f64) { self.select_tool(typ); self.move_mouse(x1, y1); self.lmb_mousedown(x1, y1); @@ -51,7 +51,7 @@ impl EditorTestUtils for Editor { }); } - fn move_mouse(&mut self, x: u32, y: u32) { + fn move_mouse(&mut self, x: f64, y: f64) { self.input(InputPreprocessorMessage::MouseMove((x, y).into(), ModifierKeys::default())); } @@ -63,7 +63,7 @@ impl EditorTestUtils for Editor { self.handle_message(InputPreprocessorMessage::MouseUp(state, ModifierKeys::default())).unwrap() } - fn lmb_mousedown(&mut self, x: u32, y: u32) { + fn lmb_mousedown(&mut self, x: f64, y: f64) { self.mousedown(MouseState { position: (x, y).into(), mouse_keys: MouseKeys::LEFT, diff --git a/editor/src/tool/tools/eyedropper.rs b/editor/src/tool/tools/eyedropper.rs index 615780b4f6..f61e6bac07 100644 --- a/editor/src/tool/tools/eyedropper.rs +++ b/editor/src/tool/tools/eyedropper.rs @@ -19,7 +19,7 @@ impl<'a> MessageHandler> for Eyedropper { fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque) { let mouse_pos = data.2.mouse.position; let tolerance = DVec2::splat(SELECTION_TOLERANCE); - let quad = Quad::from_box([mouse_pos.as_f64() - tolerance, mouse_pos.as_f64() + tolerance]); + let quad = Quad::from_box([mouse_pos - tolerance, mouse_pos + tolerance]); if let Some(path) = data.0.document.intersects_quad_root(quad).last() { if let Ok(layer) = data.0.document.layer(path) { diff --git a/editor/src/tool/tools/fill.rs b/editor/src/tool/tools/fill.rs index f37c5d729a..0bc6f2fc63 100644 --- a/editor/src/tool/tools/fill.rs +++ b/editor/src/tool/tools/fill.rs @@ -17,7 +17,7 @@ impl<'a> MessageHandler> for Fill { fn process_action(&mut self, _action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque) { let mouse_pos = data.2.mouse.position; let tolerance = DVec2::splat(SELECTION_TOLERANCE); - let quad = Quad::from_box([mouse_pos.as_f64() - tolerance, mouse_pos.as_f64() + tolerance]); + let quad = Quad::from_box([mouse_pos - tolerance, mouse_pos + tolerance]); if let Some(path) = data.0.document.intersects_quad_root(quad).last() { responses.push_back( diff --git a/editor/src/tool/tools/line.rs b/editor/src/tool/tools/line.rs index 5a1a59b330..fdb63ce570 100644 --- a/editor/src/tool/tools/line.rs +++ b/editor/src/tool/tools/line.rs @@ -122,8 +122,8 @@ impl Fsm for LineToolFsmState { } fn generate_transform(data: &mut LineToolData, lock: bool, snap: bool, center: bool) -> Message { - let mut start = data.drag_start.as_f64(); - let stop = data.drag_current.as_f64(); + let mut start = data.drag_start; + let stop = data.drag_current; let dir = stop - start; diff --git a/editor/src/tool/tools/pen.rs b/editor/src/tool/tools/pen.rs index f2bff21c95..977dd2d060 100644 --- a/editor/src/tool/tools/pen.rs +++ b/editor/src/tool/tools/pen.rs @@ -65,7 +65,7 @@ impl Fsm for PenToolFsmState { responses: &mut VecDeque, ) -> Self { let transform = document.document.root.transform; - let pos = transform.inverse() * DAffine2::from_translation(input.mouse.position.as_f64()); + let pos = transform.inverse() * DAffine2::from_translation(input.mouse.position); use PenMessage::*; use PenToolFsmState::*; diff --git a/editor/src/tool/tools/resize.rs b/editor/src/tool/tools/resize.rs index a7a2fc564b..20edc0939a 100644 --- a/editor/src/tool/tools/resize.rs +++ b/editor/src/tool/tools/resize.rs @@ -11,8 +11,8 @@ pub struct Resize { } impl Resize { pub fn calculate_transform(&self, center: Key, lock_ratio: Key, ipp: &InputPreprocessor) -> Option { - let mut start = self.drag_start.as_f64(); - let stop = ipp.mouse.position.as_f64(); + let mut start = self.drag_start; + let stop = ipp.mouse.position; let mut size = stop - start; if ipp.keyboard.get(lock_ratio as usize) { diff --git a/editor/src/tool/tools/select.rs b/editor/src/tool/tools/select.rs index 4ad62dc549..0c60be281e 100644 --- a/editor/src/tool/tools/select.rs +++ b/editor/src/tool/tools/select.rs @@ -79,9 +79,9 @@ impl SelectToolData { fn selection_box(&self) -> [DVec2; 2] { if self.drag_current == self.drag_start { let tolerance = DVec2::splat(SELECTION_TOLERANCE); - [self.drag_start.as_f64() - tolerance, self.drag_start.as_f64() + tolerance] + [self.drag_start - tolerance, self.drag_start + tolerance] } else { - [self.drag_start.as_f64(), self.drag_current.as_f64()] + [self.drag_start, self.drag_current] } } } @@ -139,7 +139,7 @@ impl Fsm for SelectToolFsmState { responses.push_back( Operation::TransformLayerInViewport { path: path.clone(), - transform: DAffine2::from_translation(input.mouse.position.as_f64() - data.drag_current.as_f64()).to_cols_array(), + transform: DAffine2::from_translation(input.mouse.position - data.drag_current).to_cols_array(), } .into(), ); @@ -149,8 +149,8 @@ impl Fsm for SelectToolFsmState { } (DrawingBox, MouseMove) => { data.drag_current = input.mouse.position; - let start = data.drag_start.as_f64(); - let size = data.drag_current.as_f64() - start; + let start = data.drag_start; + let size = data.drag_current - start; responses.push_back( Operation::SetLayerTransformInViewport { diff --git a/frontend/wasm/src/document.rs b/frontend/wasm/src/document.rs index 7f2f2f13fe..5818929c2a 100644 --- a/frontend/wasm/src/document.rs +++ b/frontend/wasm/src/document.rs @@ -92,7 +92,7 @@ pub fn close_all_documents_with_confirmation() -> Result<(), JsValue> { // TODO: Call event when the panels are resized /// Viewport resized #[wasm_bindgen] -pub fn viewport_resize(new_width: u32, new_height: u32) -> Result<(), JsValue> { +pub fn viewport_resize(new_width: f64, new_height: f64) -> Result<(), JsValue> { let ev = InputPreprocessorMessage::ViewportResize((new_width, new_height).into()); EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error) } @@ -100,8 +100,9 @@ pub fn viewport_resize(new_width: u32, new_height: u32) -> Result<(), JsValue> { // TODO: When a mouse button is down that started in the viewport, this should trigger even when the mouse is outside the viewport (or even the browser window if the browser supports it) /// Mouse movement within the screenspace bounds of the viewport #[wasm_bindgen] -pub fn on_mouse_move(x: u32, y: u32, modifiers: u8) -> Result<(), JsValue> { +pub fn on_mouse_move(x: f64, y: f64, modifiers: u8) -> Result<(), JsValue> { let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys"); + // TODO: Convert these screenspace viewport coordinates to canvas coordinates based on the current zoom and pan let ev = InputPreprocessorMessage::MouseMove((x, y).into(), mods); EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error) @@ -118,7 +119,7 @@ pub fn on_mouse_scroll(delta_x: i32, delta_y: i32, delta_z: i32, modifiers: u8) /// A mouse button depressed within screenspace the bounds of the viewport #[wasm_bindgen] -pub fn on_mouse_down(x: u32, y: u32, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> { +pub fn on_mouse_down(x: f64, y: f64, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> { let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys"); let ev = InputPreprocessorMessage::MouseDown(MouseState::from_u8_pos(mouse_keys, (x, y).into()), mods); EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error) @@ -126,7 +127,7 @@ pub fn on_mouse_down(x: u32, y: u32, mouse_keys: u8, modifiers: u8) -> Result<() /// A mouse button released #[wasm_bindgen] -pub fn on_mouse_up(x: u32, y: u32, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> { +pub fn on_mouse_up(x: f64, y: f64, mouse_keys: u8, modifiers: u8) -> Result<(), JsValue> { let mods = ModifierKeys::from_bits(modifiers).expect("invalid modifier keys"); let ev = InputPreprocessorMessage::MouseUp(MouseState::from_u8_pos(mouse_keys, (x, y).into()), mods); EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(ev)).map_err(convert_error) From a06d076a795b563fb924c30c0f3e575373ddd6cb Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Sat, 14 Aug 2021 01:34:19 -0700 Subject: [PATCH 2/4] Fix pseudo_hash call --- editor/src/communication/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/communication/mod.rs b/editor/src/communication/mod.rs index 0e1dfb1879..a9de074559 100644 --- a/editor/src/communication/mod.rs +++ b/editor/src/communication/mod.rs @@ -28,7 +28,7 @@ where pub fn generate_hash<'a>(messages: impl IntoIterator, ipp: &InputPreprocessor, document_hash: u64) -> u64 { let mut s = DefaultHasher::new(); document_hash.hash(&mut s); - ipp.pseudo_hash(); + ipp.pseudo_hash().hash(&mut s); for message in messages { message.pseudo_hash().hash(&mut s); } From 0549f8ba6cb53133fc44866654e33ee5b942dee4 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Sat, 14 Aug 2021 11:25:22 +0200 Subject: [PATCH 3/4] Replace hash function with proper function for uuid generation --- Cargo.lock | 48 ++++++++++++++++++++++++++ editor/Cargo.toml | 2 ++ editor/src/communication/mod.rs | 19 +++++----- editor/src/input/input_preprocessor.rs | 23 ------------ editor/src/lib.rs | 2 +- editor/src/tool/tools/ellipse.rs | 4 +-- editor/src/tool/tools/line.rs | 4 +-- editor/src/tool/tools/pen.rs | 2 +- editor/src/tool/tools/rectangle.rs | 4 +-- editor/src/tool/tools/select.rs | 2 +- editor/src/tool/tools/shape.rs | 4 +-- 11 files changed, 70 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c56b9a347..e619d8a7ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,7 +98,9 @@ dependencies = [ "graphite-graphene", "graphite-proc-macros", "log", + "rand_chacha", "serde", + "spin", "thiserror", ] @@ -186,6 +188,15 @@ version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" +[[package]] +name = "lock_api" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" @@ -201,6 +212,12 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + [[package]] name = "proc-macro2" version = "1.0.27" @@ -219,6 +236,22 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" + [[package]] name = "regex" version = "1.5.4" @@ -248,6 +281,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.126" @@ -279,6 +318,15 @@ dependencies = [ "serde", ] +[[package]] +name = "spin" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +dependencies = [ + "lock_api", +] + [[package]] name = "syn" version = "1.0.73" diff --git a/editor/Cargo.toml b/editor/Cargo.toml index 8079cfb9c9..318c2aabe5 100644 --- a/editor/Cargo.toml +++ b/editor/Cargo.toml @@ -15,6 +15,8 @@ thiserror = "1.0.24" serde = { version = "1.0", features = ["derive"] } graphite-proc-macros = { path = "../proc-macros" } glam = { version="0.17", features = ["serde"] } +rand_chacha = "0.3.1" +spin = "0.9.2" [dependencies.graphene] path = "../graphene" diff --git a/editor/src/communication/mod.rs b/editor/src/communication/mod.rs index a9de074559..8c7d8ad535 100644 --- a/editor/src/communication/mod.rs +++ b/editor/src/communication/mod.rs @@ -1,16 +1,17 @@ -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; - pub mod dispatcher; pub mod message; use crate::message_prelude::*; pub use dispatcher::*; +use rand_chacha::{rand_core::{SeedableRng, RngCore}, ChaCha20Rng}; +use spin::Mutex; pub use crate::input::InputPreprocessor; use std::collections::VecDeque; pub type ActionList = Vec>; +static RNG: Mutex> = Mutex::new(None); + // TODO: Add Send + Sync requirement // Use something like rw locks for synchronization pub trait MessageHandlerData {} @@ -25,12 +26,10 @@ where fn actions(&self) -> ActionList; } -pub fn generate_hash<'a>(messages: impl IntoIterator, ipp: &InputPreprocessor, document_hash: u64) -> u64 { - let mut s = DefaultHasher::new(); - document_hash.hash(&mut s); - ipp.pseudo_hash().hash(&mut s); - for message in messages { - message.pseudo_hash().hash(&mut s); +pub fn generate_uuid() -> u64 { + let mut lock = RNG.lock(); + if lock.is_none() { + *lock = Some(ChaCha20Rng::seed_from_u64(0)); } - s.finish() + lock.as_mut().map(ChaCha20Rng::next_u64).unwrap() } diff --git a/editor/src/input/input_preprocessor.rs b/editor/src/input/input_preprocessor.rs index 5bd517838c..097dfe0ce9 100644 --- a/editor/src/input/input_preprocessor.rs +++ b/editor/src/input/input_preprocessor.rs @@ -1,11 +1,9 @@ -use std::collections::hash_map::DefaultHasher; use std::usize; use super::keyboard::{Key, KeyStates}; use super::mouse::{MouseKeys, MouseState, ScrollDelta, ViewportPosition}; use crate::message_prelude::*; use bitflags::bitflags; -use std::hash::{Hash, Hasher}; #[doc(inline)] pub use graphene::DocumentResponse; @@ -39,27 +37,6 @@ pub struct InputPreprocessor { pub viewport_size: ViewportPosition, } -impl InputPreprocessor { - /// Returns the byte representation of the message. - /// - /// # Safety - /// This function reads from uninitialized memory!!! - /// Only use if you know what you are doing - unsafe fn as_slice(&self) -> &[u8] { - core::slice::from_raw_parts(self as *const InputPreprocessor as *const u8, std::mem::size_of::()) - } - /// Returns a pseudo hash that should uniquely identify the message. - /// This is needed because `Hash` is not implemented for f64s - /// - /// # Safety - /// This function reads from uninitialized memory but the generated value should be fine. - pub fn pseudo_hash(&self) -> u64 { - let mut s = DefaultHasher::new(); - unsafe { self.as_slice() }.hash(&mut s); - s.finish() - } -} - enum KeyPosition { Pressed, Released, diff --git a/editor/src/lib.rs b/editor/src/lib.rs index 98cb4b4ab1..da77963231 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -50,7 +50,7 @@ impl Editor { } pub mod message_prelude { - pub use crate::communication::generate_hash; + pub use crate::communication::generate_uuid; pub use crate::communication::message::{AsMessage, Message, MessageDiscriminant}; pub use crate::communication::{ActionList, MessageHandler}; pub use crate::document::{DocumentMessage, DocumentMessageDiscriminant}; diff --git a/editor/src/tool/tools/ellipse.rs b/editor/src/tool/tools/ellipse.rs index 32aef27543..e1e11d901f 100644 --- a/editor/src/tool/tools/ellipse.rs +++ b/editor/src/tool/tools/ellipse.rs @@ -58,7 +58,7 @@ impl Fsm for EllipseToolFsmState { fn transition( self, event: ToolMessage, - document: &DocumentMessageHandler, + _document: &DocumentMessageHandler, tool_data: &DocumentToolData, data: &mut Self::ToolData, input: &InputPreprocessor, @@ -72,7 +72,7 @@ impl Fsm for EllipseToolFsmState { (Ready, DragStart) => { shape_data.drag_start = input.mouse.position; responses.push_back(DocumentMessage::StartTransaction.into()); - shape_data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]); + shape_data.path = Some(vec![generate_uuid()]); responses.push_back(DocumentMessage::DeselectAllLayers.into()); responses.push_back( diff --git a/editor/src/tool/tools/line.rs b/editor/src/tool/tools/line.rs index fdb63ce570..00a3785f91 100644 --- a/editor/src/tool/tools/line.rs +++ b/editor/src/tool/tools/line.rs @@ -59,7 +59,7 @@ impl Fsm for LineToolFsmState { fn transition( self, event: ToolMessage, - document: &DocumentMessageHandler, + _document: &DocumentMessageHandler, tool_data: &DocumentToolData, data: &mut Self::ToolData, input: &InputPreprocessor, @@ -72,7 +72,7 @@ impl Fsm for LineToolFsmState { (Ready, DragStart) => { data.drag_start = input.mouse.position; responses.push_back(DocumentMessage::StartTransaction.into()); - data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]); + data.path = Some(vec![generate_uuid()]); responses.push_back(DocumentMessage::DeselectAllLayers.into()); responses.push_back( diff --git a/editor/src/tool/tools/pen.rs b/editor/src/tool/tools/pen.rs index 977dd2d060..991c36e7c6 100644 --- a/editor/src/tool/tools/pen.rs +++ b/editor/src/tool/tools/pen.rs @@ -74,7 +74,7 @@ impl Fsm for PenToolFsmState { (Ready, DragStart) => { responses.push_back(DocumentMessage::StartTransaction.into()); responses.push_back(DocumentMessage::DeselectAllLayers.into()); - data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]); + data.path = Some(vec![generate_uuid()]); data.points.push(pos); data.next_point = pos; diff --git a/editor/src/tool/tools/rectangle.rs b/editor/src/tool/tools/rectangle.rs index 659577d9d8..ce562ce7d1 100644 --- a/editor/src/tool/tools/rectangle.rs +++ b/editor/src/tool/tools/rectangle.rs @@ -58,7 +58,7 @@ impl Fsm for RectangleToolFsmState { fn transition( self, event: ToolMessage, - document: &DocumentMessageHandler, + _document: &DocumentMessageHandler, tool_data: &DocumentToolData, data: &mut Self::ToolData, input: &InputPreprocessor, @@ -72,7 +72,7 @@ impl Fsm for RectangleToolFsmState { (Ready, DragStart) => { shape_data.drag_start = input.mouse.position; responses.push_back(DocumentMessage::StartTransaction.into()); - shape_data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]); + shape_data.path = Some(vec![generate_uuid()]); responses.push_back(DocumentMessage::DeselectAllLayers.into()); responses.push_back( diff --git a/editor/src/tool/tools/select.rs b/editor/src/tool/tools/select.rs index 0c60be281e..2fcb36c9b7 100644 --- a/editor/src/tool/tools/select.rs +++ b/editor/src/tool/tools/select.rs @@ -122,7 +122,7 @@ impl Fsm for SelectToolFsmState { Dragging } else { responses.push_back(DocumentMessage::DeselectAllLayers.into()); - data.box_id = Some(vec![generate_hash(&*responses, input, document.document.hash())]); + data.box_id = Some(vec![generate_uuid()]); responses.push_back( Operation::AddBoundingBox { path: data.box_id.clone().unwrap(), diff --git a/editor/src/tool/tools/shape.rs b/editor/src/tool/tools/shape.rs index a2149eb820..c9fbc17952 100644 --- a/editor/src/tool/tools/shape.rs +++ b/editor/src/tool/tools/shape.rs @@ -58,7 +58,7 @@ impl Fsm for ShapeToolFsmState { fn transition( self, event: ToolMessage, - document: &DocumentMessageHandler, + _document: &DocumentMessageHandler, tool_data: &DocumentToolData, data: &mut Self::ToolData, input: &InputPreprocessor, @@ -72,7 +72,7 @@ impl Fsm for ShapeToolFsmState { (Ready, DragStart) => { shape_data.drag_start = input.mouse.position; responses.push_back(DocumentMessage::StartTransaction.into()); - shape_data.path = Some(vec![generate_hash(&*responses, input, document.document.hash())]); + shape_data.path = Some(vec![generate_uuid()]); responses.push_back(DocumentMessage::DeselectAllLayers.into()); data.sides = match tool_data.tool_options.get(&ToolType::Shape) { Some(&ToolOptions::Shape { From 75294334b993c4fc622f4d18970a94e0dd7b29d5 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Sat, 14 Aug 2021 11:31:32 +0200 Subject: [PATCH 4/4] Cargo fmt --- editor/src/communication/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/editor/src/communication/mod.rs b/editor/src/communication/mod.rs index 8c7d8ad535..47a881ac67 100644 --- a/editor/src/communication/mod.rs +++ b/editor/src/communication/mod.rs @@ -2,7 +2,10 @@ pub mod dispatcher; pub mod message; use crate::message_prelude::*; pub use dispatcher::*; -use rand_chacha::{rand_core::{SeedableRng, RngCore}, ChaCha20Rng}; +use rand_chacha::{ + rand_core::{RngCore, SeedableRng}, + ChaCha20Rng, +}; use spin::Mutex; pub use crate::input::InputPreprocessor; @@ -27,7 +30,7 @@ where } pub fn generate_uuid() -> u64 { - let mut lock = RNG.lock(); + let mut lock = RNG.lock(); if lock.is_none() { *lock = Some(ChaCha20Rng::seed_from_u64(0)); }