@@ -55,6 +55,7 @@ pub struct PathToolOptions {
5555pub enum PathToolMessage {
5656 // Standard messages
5757 Abort ,
58+ CanvasTransformed ,
5859 SelectionChanged ,
5960 Overlays {
6061 context : OverlayContext ,
@@ -511,6 +512,7 @@ impl ToolTransition for PathTool {
511512 fn event_to_message_map ( & self ) -> EventToMessageMap {
512513 EventToMessageMap {
513514 tool_abort : Some ( PathToolMessage :: Abort . into ( ) ) ,
515+ canvas_transformed : Some ( PathToolMessage :: CanvasTransformed . into ( ) ) ,
514516 selection_changed : Some ( PathToolMessage :: SelectionChanged . into ( ) ) ,
515517 overlay_provider : Some ( |context| PathToolMessage :: Overlays { context } . into ( ) ) ,
516518 ..Default :: default ( )
@@ -561,7 +563,7 @@ struct PathToolData {
561563 snap_manager : SnapManager ,
562564 lasso_polygon : Vec < DVec2 > ,
563565 selection_mode : Option < SelectionMode > ,
564- drag_start_pos : DVec2 ,
566+ drag_start_doc : DVec2 ,
565567 previous_mouse_position : DVec2 ,
566568 toggle_colinear_debounce : bool ,
567569 opposing_handle_lengths : Option < OpposingHandleLengths > ,
@@ -611,6 +613,7 @@ struct PathToolData {
611613 hovered_layers : Vec < LayerNodeIdentifier > ,
612614 ghost_outline : Vec < ( Vec < ClickTargetType > , LayerNodeIdentifier ) > ,
613615 make_path_editable_is_allowed : bool ,
616+ last_pointer_move : Option < PathToolMessage > ,
614617}
615618
616619impl PathToolData {
@@ -645,14 +648,19 @@ impl PathToolData {
645648 // Convert previous mouse position to viewport space first
646649 let document_to_viewport = metadata. document_to_viewport ;
647650 let previous_mouse = document_to_viewport. transform_point2 ( self . previous_mouse_position ) ;
648- if previous_mouse == self . drag_start_pos {
651+ let drag_start_vp = document_to_viewport. transform_point2 ( self . drag_start_doc ) ;
652+ if previous_mouse == drag_start_vp {
649653 let tolerance = DVec2 :: splat ( SELECTION_TOLERANCE ) ;
650- [ self . drag_start_pos - tolerance, self . drag_start_pos + tolerance]
654+ [ drag_start_vp - tolerance, drag_start_vp + tolerance]
651655 } else {
652- [ self . drag_start_pos , previous_mouse]
656+ [ drag_start_vp , previous_mouse]
653657 }
654658 }
655659
660+ fn drag_start_viewport ( & self , document : & DocumentMessageHandler ) -> DVec2 {
661+ document. metadata ( ) . document_to_viewport . transform_point2 ( self . drag_start_doc )
662+ }
663+
656664 fn update_selection_status ( & mut self , shape_editor : & mut ShapeState , document : & DocumentMessageHandler ) {
657665 let selection_status = get_selection_status ( & document. network_interface , shape_editor) ;
658666
@@ -736,7 +744,7 @@ impl PathToolData {
736744 self . double_click_handled = false ;
737745 self . opposing_handle_lengths = None ;
738746
739- self . drag_start_pos = input. mouse . position ;
747+ self . drag_start_doc = document . metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
740748
741749 if input. time - self . last_click_time > DOUBLE_CLICK_MILLISECONDS {
742750 self . saved_points_before_anchor_convert_smooth_sharp . clear ( ) ;
@@ -784,7 +792,7 @@ impl PathToolData {
784792 }
785793
786794 if let Some ( selected_points) = selection_info {
787- self . drag_start_pos = input. mouse . position ;
795+ self . drag_start_doc = document . metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
788796
789797 // If selected points contain only handles and there was some selection before, then it is stored and becomes restored upon release
790798 let mut dragging_only_handles = true ;
@@ -871,7 +879,7 @@ impl PathToolData {
871879 // TODO: If the segment connected to one of the endpoints is also selected then select that point
872880 }
873881
874- self . drag_start_pos = input. mouse . position ;
882+ self . drag_start_doc = document . metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
875883 let viewport_to_document = document. metadata ( ) . document_to_viewport . inverse ( ) ;
876884 self . previous_mouse_position = viewport_to_document. transform_point2 ( input. mouse . position ) ;
877885
@@ -900,15 +908,15 @@ impl PathToolData {
900908
901909 self . started_drawing_from_inside = true ;
902910
903- self . drag_start_pos = input. mouse . position ;
911+ self . drag_start_doc = document . metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
904912 self . previous_mouse_position = document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
905913
906914 let selection_shape = if lasso_select { SelectionShapeType :: Lasso } else { SelectionShapeType :: Box } ;
907915 PathToolFsmState :: Drawing { selection_shape }
908916 }
909917 // Start drawing
910918 else {
911- self . drag_start_pos = input. mouse . position ;
919+ self . drag_start_doc = document . metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
912920 self . previous_mouse_position = document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
913921
914922 let selection_shape = if lasso_select { SelectionShapeType :: Lasso } else { SelectionShapeType :: Box } ;
@@ -1153,7 +1161,7 @@ impl PathToolData {
11531161 fn start_snap_along_axis ( & mut self , shape_editor : & mut ShapeState , document : & DocumentMessageHandler , input : & InputPreprocessorMessageHandler , responses : & mut VecDeque < Message > ) {
11541162 // Find the negative delta to take the point to the drag start position
11551163 let current_mouse = input. mouse . position ;
1156- let drag_start = self . drag_start_pos ;
1164+ let drag_start = self . drag_start_viewport ( document ) ;
11571165 let opposite_delta = drag_start - current_mouse;
11581166
11591167 shape_editor. move_selected_points_and_segments ( None , document, opposite_delta, false , true , false , None , false , responses) ;
@@ -1174,7 +1182,7 @@ impl PathToolData {
11741182 fn stop_snap_along_axis ( & mut self , shape_editor : & mut ShapeState , document : & DocumentMessageHandler , input : & InputPreprocessorMessageHandler , responses : & mut VecDeque < Message > ) {
11751183 // Calculate the negative delta of the selection and move it back to the drag start
11761184 let current_mouse = input. mouse . position ;
1177- let drag_start = self . drag_start_pos ;
1185+ let drag_start = self . drag_start_viewport ( document ) ;
11781186
11791187 let opposite_delta = drag_start - current_mouse;
11801188 let Some ( axis) = self . snapping_axis else { return } ;
@@ -1463,7 +1471,7 @@ impl PathToolData {
14631471 let mut was_alt_dragging = false ;
14641472
14651473 if self . snapping_axis . is_none ( ) {
1466- if self . alt_clicked_on_anchor && !self . alt_dragging_from_anchor && self . drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD {
1474+ if self . alt_clicked_on_anchor && !self . alt_dragging_from_anchor && self . drag_start_viewport ( document ) . distance ( input. mouse . position ) > DRAG_THRESHOLD {
14671475 // Checking which direction the dragging begins
14681476 self . alt_dragging_from_anchor = true ;
14691477 let Some ( layer) = document. network_interface . selected_nodes ( ) . selected_layers ( document. metadata ( ) ) . next ( ) else {
@@ -1485,7 +1493,7 @@ impl PathToolData {
14851493 return ;
14861494 } ;
14871495
1488- let delta = input. mouse . position - self . drag_start_pos ;
1496+ let delta = input. mouse . position - self . drag_start_viewport ( document ) ;
14891497 let handle = if delta. dot ( tangent1) >= delta. dot ( tangent2) {
14901498 segment1. to_manipulator_point ( )
14911499 } else {
@@ -1528,7 +1536,7 @@ impl PathToolData {
15281536 // Constantly checking and changing the snapping axis based on current mouse position
15291537 if snap_axis && self . snapping_axis . is_some ( ) {
15301538 let Some ( current_axis) = self . snapping_axis else { return } ;
1531- let total_delta = self . drag_start_pos - input. mouse . position ;
1539+ let total_delta = self . drag_start_viewport ( document ) - input. mouse . position ;
15321540
15331541 if ( total_delta. x . abs ( ) > total_delta. y . abs ( ) && current_axis == Axis :: Y ) || ( total_delta. y . abs ( ) > total_delta. x . abs ( ) && current_axis == Axis :: X ) {
15341542 self . stop_snap_along_axis ( shape_editor, document, input, responses) ;
@@ -1706,7 +1714,7 @@ impl Fsm for PathToolFsmState {
17061714 }
17071715 ( _, PathToolMessage :: Overlays { context : mut overlay_context } ) => {
17081716 // Set this to show ghost line only if drag actually happened
1709- if matches ! ( self , Self :: Dragging ( _) ) && tool_data. drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD {
1717+ if matches ! ( self , Self :: Dragging ( _) ) && tool_data. drag_start_viewport ( document ) . distance ( input. mouse . position ) > DRAG_THRESHOLD {
17101718 for ( outline, layer) in & tool_data. ghost_outline {
17111719 let transform = document. metadata ( ) . transform_to_viewport ( * layer) ;
17121720 overlay_context. outline ( outline. iter ( ) , transform, Some ( COLOR_OVERLAY_GRAY ) ) ;
@@ -1904,7 +1912,8 @@ impl Fsm for PathToolFsmState {
19041912 let ( points_inside, segments_inside) = match selection_shape {
19051913 SelectionShapeType :: Box => {
19061914 let previous_mouse = document. metadata ( ) . document_to_viewport . transform_point2 ( tool_data. previous_mouse_position ) ;
1907- let bbox = Rect :: new ( tool_data. drag_start_pos . x , tool_data. drag_start_pos . y , previous_mouse. x , previous_mouse. y ) . abs ( ) ;
1915+ let drag_start_vp = tool_data. drag_start_viewport ( document) ;
1916+ let bbox = Rect :: new ( drag_start_vp. x , drag_start_vp. y , previous_mouse. x , previous_mouse. y ) . abs ( ) ;
19081917 shape_editor. get_inside_points_and_segments (
19091918 & document. network_interface ,
19101919 SelectionShape :: Box ( bbox) ,
@@ -1971,7 +1980,7 @@ impl Fsm for PathToolFsmState {
19711980 // Draw the snapping axis lines
19721981 if tool_data. snapping_axis . is_some ( ) {
19731982 let Some ( axis) = tool_data. snapping_axis else { return self } ;
1974- let origin = tool_data. drag_start_pos ;
1983+ let origin = tool_data. drag_start_viewport ( document ) ;
19751984 let viewport_diagonal = viewport. size ( ) . into_dvec2 ( ) . length ( ) ;
19761985
19771986 match axis {
@@ -2096,14 +2105,24 @@ impl Fsm for PathToolFsmState {
20962105 segment_editing_modifier,
20972106 } ,
20982107 ) => {
2108+ tool_data. last_pointer_move = Some ( PathToolMessage :: PointerMove {
2109+ equidistant,
2110+ toggle_colinear,
2111+ move_anchor_with_handles,
2112+ snap_angle,
2113+ lock_angle,
2114+ delete_segment,
2115+ break_colinear_molding,
2116+ segment_editing_modifier,
2117+ } ) ;
20992118 let selected_only_handles = !shape_editor. selected_points ( ) . any ( |point| matches ! ( point, ManipulatorPointId :: Anchor ( _) ) ) ;
21002119 tool_data. stored_selection = None ;
21012120
2102- if !tool_data. saved_selection_before_handle_drag . is_empty ( ) && ( tool_data. drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD ) && ( selected_only_handles) {
2121+ if !tool_data. saved_selection_before_handle_drag . is_empty ( ) && ( tool_data. drag_start_viewport ( document ) . distance ( input. mouse . position ) > DRAG_THRESHOLD ) && ( selected_only_handles) {
21032122 tool_data. handle_drag_toggle = true ;
21042123 }
21052124
2106- if tool_data. drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD {
2125+ if tool_data. drag_start_viewport ( document ) . distance ( input. mouse . position ) > DRAG_THRESHOLD {
21072126 tool_data. molding_segment = true ;
21082127 }
21092128
@@ -2243,19 +2262,11 @@ impl Fsm for PathToolFsmState {
22432262 self
22442263 }
22452264 ( PathToolFsmState :: Drawing { selection_shape : selection_type } , PathToolMessage :: PointerOutsideViewport { .. } ) => {
2246- // Auto-panning
2247- if let Some ( offset) = tool_data. auto_panning . shift_viewport ( input, viewport, responses) {
2248- tool_data. drag_start_pos += offset;
2249- }
2250-
2265+ let _ = tool_data. auto_panning . shift_viewport ( input, viewport, responses) ;
22512266 PathToolFsmState :: Drawing { selection_shape : selection_type }
22522267 }
22532268 ( PathToolFsmState :: Dragging ( dragging_state) , PathToolMessage :: PointerOutsideViewport { .. } ) => {
2254- // Auto-panning
2255- if let Some ( offset) = tool_data. auto_panning . shift_viewport ( input, viewport, responses) {
2256- tool_data. drag_start_pos += offset;
2257- }
2258-
2269+ let _ = tool_data. auto_panning . shift_viewport ( input, viewport, responses) ;
22592270 PathToolFsmState :: Dragging ( dragging_state)
22602271 }
22612272 (
@@ -2314,7 +2325,7 @@ impl Fsm for PathToolFsmState {
23142325
23152326 let document_to_viewport = document. metadata ( ) . document_to_viewport ;
23162327 let previous_mouse = document_to_viewport. transform_point2 ( tool_data. previous_mouse_position ) ;
2317- if tool_data. drag_start_pos == previous_mouse {
2328+ if tool_data. drag_start_viewport ( document ) == previous_mouse {
23182329 responses. add ( NodeGraphMessage :: SelectedNodesSet { nodes : vec ! [ ] } ) ;
23192330 } else {
23202331 let selection_mode = match tool_action_data. preferences . get_selection_mode ( ) {
@@ -2324,7 +2335,8 @@ impl Fsm for PathToolFsmState {
23242335
23252336 match selection_shape {
23262337 SelectionShapeType :: Box => {
2327- let bbox = Rect :: new ( tool_data. drag_start_pos . x , tool_data. drag_start_pos . y , previous_mouse. x , previous_mouse. y ) . abs ( ) ;
2338+ let drag_start_vp = tool_data. drag_start_viewport ( document) ;
2339+ let bbox = Rect :: new ( drag_start_vp. x , drag_start_vp. y , previous_mouse. x , previous_mouse. y ) . abs ( ) ;
23282340
23292341 shape_editor. select_all_in_shape (
23302342 & document. network_interface ,
@@ -2355,7 +2367,7 @@ impl Fsm for PathToolFsmState {
23552367 PathToolFsmState :: Ready
23562368 }
23572369 ( PathToolFsmState :: Dragging { .. } , PathToolMessage :: Escape | PathToolMessage :: RightClick ) => {
2358- if tool_data. handle_drag_toggle && tool_data. drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD {
2370+ if tool_data. handle_drag_toggle && tool_data. drag_start_viewport ( document ) . distance ( input. mouse . position ) > DRAG_THRESHOLD {
23592371 shape_editor. deselect_all_points ( ) ;
23602372 shape_editor. deselect_all_segments ( ) ;
23612373
@@ -2410,7 +2422,7 @@ impl Fsm for PathToolFsmState {
24102422 } ;
24112423 tool_data. started_drawing_from_inside = false ;
24122424
2413- if tool_data. drag_start_pos . distance ( previous_mouse) < 1e-8 {
2425+ if tool_data. drag_start_viewport ( document ) . distance ( previous_mouse) < 1e-8 {
24142426 // Clicked inside or outside the shape then deselect all of the points/segments
24152427 if document. click ( input, viewport) . is_some ( ) && tool_data. stored_selection . is_none ( ) {
24162428 tool_data. stored_selection = Some ( shape_editor. selected_shape_state . clone ( ) ) ;
@@ -2421,7 +2433,8 @@ impl Fsm for PathToolFsmState {
24212433 } else {
24222434 match selection_shape {
24232435 SelectionShapeType :: Box => {
2424- let bbox = Rect :: new ( tool_data. drag_start_pos . x , tool_data. drag_start_pos . y , previous_mouse. x , previous_mouse. y ) . abs ( ) ;
2436+ let drag_start_vp = tool_data. drag_start_viewport ( document) ;
2437+ let bbox = Rect :: new ( drag_start_vp. x , drag_start_vp. y , previous_mouse. x , previous_mouse. y ) . abs ( ) ;
24252438
24262439 shape_editor. select_all_in_shape (
24272440 & document. network_interface ,
@@ -2454,7 +2467,7 @@ impl Fsm for PathToolFsmState {
24542467 ( _, PathToolMessage :: DragStop { extend_selection, .. } ) => {
24552468 tool_data. ghost_outline . clear ( ) ;
24562469 let extend_selection = input. keyboard . get ( extend_selection as usize ) ;
2457- let drag_occurred = tool_data. drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD ;
2470+ let drag_occurred = tool_data. drag_start_viewport ( document ) . distance ( input. mouse . position ) > DRAG_THRESHOLD ;
24582471 let mut segment_dissolved = false ;
24592472 let mut point_inserted = false ;
24602473
@@ -2585,7 +2598,7 @@ impl Fsm for PathToolFsmState {
25852598 }
25862599 }
25872600 // Deselect all points if the user clicks the filled region of the shape
2588- else if tool_data. drag_start_pos . distance ( input. mouse . position ) <= DRAG_THRESHOLD {
2601+ else if tool_data. drag_start_viewport ( document ) . distance ( input. mouse . position ) <= DRAG_THRESHOLD {
25892602 shape_editor. deselect_all_points ( ) ;
25902603 shape_editor. deselect_all_segments ( ) ;
25912604 }
@@ -3037,7 +3050,7 @@ impl Fsm for PathToolFsmState {
30373050
30383051 if nearest_point. is_some ( ) {
30393052 // Flip the selected point between smooth and sharp
3040- if !tool_data. double_click_handled && tool_data. drag_start_pos . distance ( input. mouse . position ) <= DRAG_THRESHOLD {
3053+ if !tool_data. double_click_handled && tool_data. drag_start_viewport ( document ) . distance ( input. mouse . position ) <= DRAG_THRESHOLD {
30413054 responses. add ( DocumentMessage :: StartTransaction ) ;
30423055
30433056 shape_editor. select_points_by_layer_and_id ( & tool_data. saved_points_before_anchor_convert_smooth_sharp ) ;
@@ -3119,6 +3132,14 @@ impl Fsm for PathToolFsmState {
31193132
31203133 PathToolFsmState :: Ready
31213134 }
3135+ ( PathToolFsmState :: Dragging ( _) | PathToolFsmState :: Drawing { .. } | PathToolFsmState :: SlidingPoint , PathToolMessage :: CanvasTransformed ) => {
3136+ if let Some ( msg) = tool_data. last_pointer_move . clone ( ) {
3137+ responses. add ( msg) ;
3138+ }
3139+ responses. add ( OverlaysMessage :: Draw ) ;
3140+ self
3141+ }
3142+ ( _, PathToolMessage :: CanvasTransformed ) => self ,
31223143 ( _, PathToolMessage :: Abort ) => {
31233144 responses. add ( OverlaysMessage :: Draw ) ;
31243145 PathToolFsmState :: Ready
0 commit comments