From 1c11ebcc4efe336e7b6108120cf392930d9c8ca5 Mon Sep 17 00:00:00 2001 From: Dhruv Date: Fri, 11 Aug 2023 14:51:39 +0530 Subject: [PATCH] Correct snapping offsets after canvas transformation when using snap-reliant tools (#1370) * fix: pen, spline tool incorrect snap offsets - re-render snapping offsets if canvas transformed during line draw * [wip]feat: add CanvasTransformed global message * [wip]fix: synchronize line tool snap offsets * fix: update offsets for shape tools on canvas transform * chore: remove unneeded function parameter * [wip]fix: use line tool at canvas level * refactor: revert line tool changes --- editor/src/messages/broadcast/broadcast_event.rs | 1 + .../document/navigation/navigation_message_handler.rs | 2 ++ editor/src/messages/tool/common_functionality/resize.rs | 6 ++++++ editor/src/messages/tool/tool_messages/ellipse_tool.rs | 7 +++++++ editor/src/messages/tool/tool_messages/line_tool.rs | 6 +++++- editor/src/messages/tool/tool_messages/pen_tool.rs | 7 +++++++ editor/src/messages/tool/tool_messages/polygon_tool.rs | 7 +++++++ editor/src/messages/tool/tool_messages/rectangle_tool.rs | 7 +++++++ editor/src/messages/tool/tool_messages/spline_tool.rs | 7 +++++++ editor/src/messages/tool/tool_messages/text_tool.rs | 1 + editor/src/messages/tool/utility_types.rs | 3 +++ 11 files changed, 53 insertions(+), 1 deletion(-) diff --git a/editor/src/messages/broadcast/broadcast_event.rs b/editor/src/messages/broadcast/broadcast_event.rs index 3ffcf775..86d2d122 100644 --- a/editor/src/messages/broadcast/broadcast_event.rs +++ b/editor/src/messages/broadcast/broadcast_event.rs @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize}; #[impl_message(Message, BroadcastMessage, TriggerEvent)] pub enum BroadcastEvent { DocumentIsDirty, + CanvasTransformed, ToolAbort, SelectionChanged, WorkingColorChanged, diff --git a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs index dce9e67a..c5d41338 100644 --- a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs +++ b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs @@ -211,6 +211,7 @@ impl MessageHandler, &InputPre TransformCanvasEnd => { self.tilt = self.snapped_angle(); self.zoom = self.snapped_scale(); + responses.add(BroadcastEvent::CanvasTransformed); responses.add(BroadcastEvent::DocumentIsDirty); responses.add(ToolMessage::UpdateCursor); responses.add(ToolMessage::UpdateHints); @@ -225,6 +226,7 @@ impl MessageHandler, &InputPre let transformed_delta = document.root.transform.inverse().transform_vector2(delta); self.pan += transformed_delta; + responses.add(BroadcastEvent::CanvasTransformed); responses.add(BroadcastEvent::DocumentIsDirty); self.create_document_transform(&ipp.viewport_bounds, responses); } diff --git a/editor/src/messages/tool/common_functionality/resize.rs b/editor/src/messages/tool/common_functionality/resize.rs index 3db810ac..da7ce3f5 100644 --- a/editor/src/messages/tool/common_functionality/resize.rs +++ b/editor/src/messages/tool/common_functionality/resize.rs @@ -24,6 +24,12 @@ impl Resize { self.drag_start = root_transform.inverse().transform_point2(self.snap_manager.snap_position(responses, document, input.mouse.position)); } + /// Recalculates snap targets without snapping the starting position. + pub fn recalculate_snaps(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, render_data: &RenderData) { + self.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); + self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); + } + /// Calculate the drag start position in viewport space. pub fn viewport_drag_start(&self, document: &DocumentMessageHandler) -> DVec2 { let root_transform = document.document_legacy.root.transform; diff --git a/editor/src/messages/tool/tool_messages/ellipse_tool.rs b/editor/src/messages/tool/tool_messages/ellipse_tool.rs index f13d31c3..1418c3dd 100644 --- a/editor/src/messages/tool/tool_messages/ellipse_tool.rs +++ b/editor/src/messages/tool/tool_messages/ellipse_tool.rs @@ -54,6 +54,8 @@ pub enum EllipseOptionsUpdate { pub enum EllipseToolMessage { // Standard messages #[remain::unsorted] + CanvasTransformed, + #[remain::unsorted] Abort, #[remain::unsorted] WorkingColorChanged, @@ -165,6 +167,7 @@ impl<'a> MessageHandler> for Ellipse impl ToolTransition for EllipseTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { + canvas_transformed: Some(EllipseToolMessage::CanvasTransformed.into()), tool_abort: Some(EllipseToolMessage::Abort.into()), working_color_changed: Some(EllipseToolMessage::WorkingColorChanged.into()), ..Default::default() @@ -209,6 +212,10 @@ impl Fsm for EllipseToolFsmState { if let ToolMessage::Ellipse(event) = event { match (self, event) { + (Drawing, CanvasTransformed) => { + tool_data.data.recalculate_snaps(document, input, render_data); + self + } (Ready, DragStart) => { shape_data.start(responses, document, input, render_data); responses.add(DocumentMessage::StartTransaction); diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index 2b0f79e4..340800c8 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -44,6 +44,10 @@ impl Default for LineOptions { pub enum LineToolMessage { // Standard messages #[remain::unsorted] + DocumentIsDirty, + #[remain::unsorted] + CanvasTransformed, + #[remain::unsorted] Abort, #[remain::unsorted] WorkingColorChanged, @@ -140,6 +144,7 @@ impl<'a> MessageHandler> for LineToo impl ToolTransition for LineTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { + canvas_transformed: Some(LineToolMessage::CanvasTransformed.into()), tool_abort: Some(LineToolMessage::Abort.into()), working_color_changed: Some(LineToolMessage::WorkingColorChanged.into()), ..Default::default() @@ -219,7 +224,6 @@ impl Fsm for LineToolFsmState { tool_data.snap_manager.cleanup(responses); input.mouse.finish_transaction(tool_data.drag_start, responses); tool_data.path = None; - Ready } (Drawing, Abort) => { diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index 09b68669..8a68d0d1 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -52,6 +52,8 @@ impl Default for PenOptions { pub enum PenToolMessage { // Standard messages #[remain::unsorted] + CanvasTransformed, + #[remain::unsorted] DocumentIsDirty, #[remain::unsorted] Abort, @@ -193,6 +195,7 @@ impl<'a> MessageHandler> for PenTool impl ToolTransition for PenTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { + canvas_transformed: Some(PenToolMessage::CanvasTransformed.into()), document_dirty: Some(PenToolMessage::DocumentIsDirty.into()), tool_abort: Some(PenToolMessage::Abort.into()), selection_changed: Some(PenToolMessage::SelectionChanged.into()), @@ -589,6 +592,10 @@ impl Fsm for PenToolFsmState { if let ToolMessage::Pen(event) = event { match (self, event) { + (_, PenToolMessage::CanvasTransformed) => { + tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); + self + } (_, PenToolMessage::DocumentIsDirty) => { // When the document has moved / needs to be redraw, re-render the overlays // TODO the overlay system should probably receive this message instead of the tool diff --git a/editor/src/messages/tool/tool_messages/polygon_tool.rs b/editor/src/messages/tool/tool_messages/polygon_tool.rs index 6e36b85b..3abbe6f2 100644 --- a/editor/src/messages/tool/tool_messages/polygon_tool.rs +++ b/editor/src/messages/tool/tool_messages/polygon_tool.rs @@ -47,6 +47,8 @@ impl Default for PolygonOptions { pub enum PolygonToolMessage { // Standard messages #[remain::unsorted] + CanvasTransformed, + #[remain::unsorted] Abort, #[remain::unsorted] WorkingColorChanged, @@ -205,6 +207,7 @@ impl<'a> MessageHandler> for Polygon impl ToolTransition for PolygonTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { + canvas_transformed: Some(PolygonToolMessage::CanvasTransformed.into()), tool_abort: Some(PolygonToolMessage::Abort.into()), working_color_changed: Some(PolygonToolMessage::WorkingColorChanged.into()), ..Default::default() @@ -249,6 +252,10 @@ impl Fsm for PolygonToolFsmState { if let ToolMessage::Polygon(event) = event { match (self, event) { + (Drawing, CanvasTransformed) => { + tool_data.data.recalculate_snaps(document, input, render_data); + self + } (Ready, DragStart) => { polygon_data.start(responses, document, input, render_data); responses.add(DocumentMessage::StartTransaction); diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index 8885e7e1..65286f61 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -53,6 +53,8 @@ pub enum RectangleOptionsUpdate { pub enum RectangleToolMessage { // Standard messages #[remain::unsorted] + CanvasTransformed, + #[remain::unsorted] Abort, #[remain::unsorted] WorkingColorChanged, @@ -164,6 +166,7 @@ impl ToolMetadata for RectangleTool { impl ToolTransition for RectangleTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { + canvas_transformed: Some(RectangleToolMessage::CanvasTransformed.into()), tool_abort: Some(RectangleToolMessage::Abort.into()), working_color_changed: Some(RectangleToolMessage::WorkingColorChanged.into()), ..Default::default() @@ -208,6 +211,10 @@ impl Fsm for RectangleToolFsmState { if let ToolMessage::Rectangle(event) = event { match (self, event) { + (Drawing, CanvasTransformed) => { + tool_data.data.recalculate_snaps(document, input, render_data); + self + } (Ready, DragStart) => { shape_data.start(responses, document, input, render_data); diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index 370e0b17..22c2f491 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -45,6 +45,8 @@ impl Default for SplineOptions { pub enum SplineToolMessage { // Standard messages #[remain::unsorted] + CanvasTransformed, + #[remain::unsorted] Abort, #[remain::unsorted] WorkingColorChanged, @@ -178,6 +180,7 @@ impl<'a> MessageHandler> for SplineT impl ToolTransition for SplineTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { + canvas_transformed: Some(SplineToolMessage::CanvasTransformed.into()), tool_abort: Some(SplineToolMessage::Abort.into()), working_color_changed: Some(SplineToolMessage::WorkingColorChanged.into()), ..Default::default() @@ -219,6 +222,10 @@ impl Fsm for SplineToolFsmState { if let ToolMessage::Spline(event) = event { match (self, event) { + (_, CanvasTransformed) => { + tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); + self + } (Ready, DragStart) => { responses.add(DocumentMessage::StartTransaction); responses.add(DocumentMessage::DeselectAllLayers); diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 1315ebf6..b32bac9e 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -200,6 +200,7 @@ impl<'a> MessageHandler> for TextToo impl ToolTransition for TextTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { + canvas_transformed: None, document_dirty: Some(TextToolMessage::DocumentIsDirty.into()), tool_abort: Some(TextToolMessage::Abort.into()), selection_changed: Some(TextToolMessage::DocumentIsDirty.into()), diff --git a/editor/src/messages/tool/utility_types.rs b/editor/src/messages/tool/utility_types.rs index e5d8adcf..c58b631f 100644 --- a/editor/src/messages/tool/utility_types.rs +++ b/editor/src/messages/tool/utility_types.rs @@ -169,6 +169,7 @@ impl DocumentToolData { #[derive(Clone, Debug, Default)] pub struct EventToMessageMap { + pub canvas_transformed: Option, pub document_dirty: Option, pub selection_changed: Option, pub tool_abort: Option, @@ -189,6 +190,7 @@ pub trait ToolTransition { }; let event_to_tool_map = self.event_to_message_map(); + subscribe_message(event_to_tool_map.canvas_transformed, BroadcastEvent::CanvasTransformed); subscribe_message(event_to_tool_map.document_dirty, BroadcastEvent::DocumentIsDirty); subscribe_message(event_to_tool_map.tool_abort, BroadcastEvent::ToolAbort); subscribe_message(event_to_tool_map.selection_changed, BroadcastEvent::SelectionChanged); @@ -206,6 +208,7 @@ pub trait ToolTransition { }; let event_to_tool_map = self.event_to_message_map(); + unsubscribe_message(event_to_tool_map.canvas_transformed, BroadcastEvent::CanvasTransformed); unsubscribe_message(event_to_tool_map.document_dirty, BroadcastEvent::DocumentIsDirty); unsubscribe_message(event_to_tool_map.tool_abort, BroadcastEvent::ToolAbort); unsubscribe_message(event_to_tool_map.selection_changed, BroadcastEvent::SelectionChanged);