@@ -603,6 +603,8 @@ struct PathToolData {
603603 started_drawing_from_inside : bool ,
604604 first_selected_with_single_click : bool ,
605605 stored_selection : Option < HashMap < LayerNodeIdentifier , SelectedLayerState > > ,
606+ snap_offset : DVec2 ,
607+
606608 last_drill_through_click_position : Option < DVec2 > ,
607609 drill_through_cycle_index : usize ,
608610 drill_through_cycle_count : usize ,
@@ -735,6 +737,7 @@ impl PathToolData {
735737 self . opposing_handle_lengths = None ;
736738
737739 self . drag_start_pos = input. mouse . position ;
740+ self . snap_offset = DVec2 :: ZERO ;
738741
739742 if input. time - self . last_click_time > DOUBLE_CLICK_MILLISECONDS {
740743 self . saved_points_before_anchor_convert_smooth_sharp . clear ( ) ;
@@ -1148,50 +1151,6 @@ impl PathToolData {
11481151 document. metadata ( ) . document_to_viewport . transform_vector2 ( snap_result. snapped_point_document - handle_position)
11491152 }
11501153
1151- fn start_snap_along_axis ( & mut self , shape_editor : & mut ShapeState , document : & DocumentMessageHandler , input : & InputPreprocessorMessageHandler , responses : & mut VecDeque < Message > ) {
1152- // Find the negative delta to take the point to the drag start position
1153- let current_mouse = input. mouse . position ;
1154- let drag_start = self . drag_start_pos ;
1155- let opposite_delta = drag_start - current_mouse;
1156-
1157- shape_editor. move_selected_points_and_segments ( None , document, opposite_delta, false , true , false , None , false , responses) ;
1158-
1159- // Calculate the projected delta and shift the points along that delta
1160- let delta = current_mouse - drag_start;
1161- let axis = if delta. x . abs ( ) >= delta. y . abs ( ) { Axis :: X } else { Axis :: Y } ;
1162- self . snapping_axis = Some ( axis) ;
1163- let projected_delta = match axis {
1164- Axis :: X => DVec2 :: new ( delta. x , 0. ) ,
1165- Axis :: Y => DVec2 :: new ( 0. , delta. y ) ,
1166- _ => DVec2 :: new ( delta. x , 0. ) ,
1167- } ;
1168-
1169- shape_editor. move_selected_points_and_segments ( None , document, projected_delta, false , true , false , None , false , responses) ;
1170- }
1171-
1172- fn stop_snap_along_axis ( & mut self , shape_editor : & mut ShapeState , document : & DocumentMessageHandler , input : & InputPreprocessorMessageHandler , responses : & mut VecDeque < Message > ) {
1173- // Calculate the negative delta of the selection and move it back to the drag start
1174- let current_mouse = input. mouse . position ;
1175- let drag_start = self . drag_start_pos ;
1176-
1177- let opposite_delta = drag_start - current_mouse;
1178- let Some ( axis) = self . snapping_axis else { return } ;
1179- let opposite_projected_delta = match axis {
1180- Axis :: X => DVec2 :: new ( opposite_delta. x , 0. ) ,
1181- Axis :: Y => DVec2 :: new ( 0. , opposite_delta. y ) ,
1182- _ => DVec2 :: new ( opposite_delta. x , 0. ) ,
1183- } ;
1184-
1185- shape_editor. move_selected_points_and_segments ( None , document, opposite_projected_delta, false , true , false , None , false , responses) ;
1186-
1187- // Calculate what actually would have been the original delta for the point, and apply that
1188- let delta = current_mouse - drag_start;
1189-
1190- shape_editor. move_selected_points_and_segments ( None , document, delta, false , true , false , None , false , responses) ;
1191-
1192- self . snapping_axis = None ;
1193- }
1194-
11951154 fn get_normalized_tangent ( & mut self , point : PointId , segment : SegmentId , vector : & Vector ) -> Option < DVec2 > {
11961155 let other_point = vector. other_point ( segment, point) ?;
11971156 let position = ManipulatorPointId :: Anchor ( point) . get_position ( vector) ?;
@@ -1409,10 +1368,15 @@ impl PathToolData {
14091368 . any ( |point| matches ! ( point, ManipulatorPointId :: EndHandle ( _) | ManipulatorPointId :: PrimaryHandle ( _) ) ) ;
14101369
14111370 // This is where it starts snapping along axis
1412- if snap_axis && self . snapping_axis . is_none ( ) && !single_handle_selected {
1413- self . start_snap_along_axis ( shape_editor, document, input, responses) ;
1414- } else if !snap_axis && self . snapping_axis . is_some ( ) {
1415- self . stop_snap_along_axis ( shape_editor, document, input, responses) ;
1371+ if snap_axis && !single_handle_selected {
1372+ let total_delta = self . drag_start_pos - input. mouse . position ;
1373+ if total_delta. x . abs ( ) > total_delta. y . abs ( ) {
1374+ self . snapping_axis = Some ( Axis :: X ) ;
1375+ } else {
1376+ self . snapping_axis = Some ( Axis :: Y ) ;
1377+ }
1378+ } else {
1379+ self . snapping_axis = None ;
14161380 }
14171381
14181382 let document_to_viewport = document. metadata ( ) . document_to_viewport ;
@@ -1452,87 +1416,74 @@ impl PathToolData {
14521416 viewport,
14531417 )
14541418 } else {
1455- shape_editor. snap ( & mut self . snap_manager , & self . snap_cache , document, input, viewport, previous_mouse)
1419+ let constraint = if let Some ( axis) = self . snapping_axis {
1420+ match axis {
1421+ Axis :: X => SnapConstraint :: Direction ( DVec2 :: X ) ,
1422+ Axis :: Y => SnapConstraint :: Direction ( DVec2 :: Y ) ,
1423+ _ => SnapConstraint :: None ,
1424+ }
1425+ } else {
1426+ SnapConstraint :: None
1427+ } ;
1428+ shape_editor. snap ( & mut self . snap_manager , & self . snap_cache , document, input, viewport, previous_mouse, constraint, self . snap_offset )
14561429 } ;
14571430
14581431 let handle_lengths = if equidistant { None } else { self . opposing_handle_lengths . take ( ) } ;
14591432 let opposite = if lock_angle { None } else { self . opposite_handle_position } ;
1460- let unsnapped_delta = current_mouse - previous_mouse;
14611433 let mut was_alt_dragging = false ;
14621434
1463- if self . snapping_axis . is_none ( ) {
1464- if self . alt_clicked_on_anchor && !self . alt_dragging_from_anchor && self . drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD {
1465- // Checking which direction the dragging begins
1466- self . alt_dragging_from_anchor = true ;
1467- let Some ( layer) = document. network_interface . selected_nodes ( ) . selected_layers ( document. metadata ( ) ) . next ( ) else {
1435+ if self . alt_clicked_on_anchor && !self . alt_dragging_from_anchor && self . drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD {
1436+ // Checking which direction the dragging begins
1437+ self . alt_dragging_from_anchor = true ;
1438+ let Some ( layer) = document. network_interface . selected_nodes ( ) . selected_layers ( document. metadata ( ) ) . next ( ) else {
1439+ return ;
1440+ } ;
1441+ let Some ( vector) = document. network_interface . compute_modified_vector ( layer) else { return } ;
1442+ let Some ( point_id) = shape_editor. selected_points ( ) . next ( ) . unwrap ( ) . get_anchor ( & vector) else {
1443+ return ;
1444+ } ;
1445+
1446+ if vector. connected_count ( point_id) == 2 {
1447+ let connected_segments: Vec < HandleId > = vector. all_connected ( point_id) . collect ( ) ;
1448+ let segment1 = connected_segments[ 0 ] ;
1449+ let Some ( tangent1) = self . get_normalized_tangent ( point_id, segment1. segment , & vector) else {
14681450 return ;
14691451 } ;
1470- let Some ( vector ) = document . network_interface . compute_modified_vector ( layer ) else { return } ;
1471- let Some ( point_id ) = shape_editor . selected_points ( ) . next ( ) . unwrap ( ) . get_anchor ( & vector) else {
1452+ let segment2 = connected_segments [ 1 ] ;
1453+ let Some ( tangent2 ) = self . get_normalized_tangent ( point_id , segment2 . segment , & vector) else {
14721454 return ;
14731455 } ;
14741456
1475- if vector. connected_count ( point_id) == 2 {
1476- let connected_segments: Vec < HandleId > = vector. all_connected ( point_id) . collect ( ) ;
1477- let segment1 = connected_segments[ 0 ] ;
1478- let Some ( tangent1) = self . get_normalized_tangent ( point_id, segment1. segment , & vector) else {
1479- return ;
1480- } ;
1481- let segment2 = connected_segments[ 1 ] ;
1482- let Some ( tangent2) = self . get_normalized_tangent ( point_id, segment2. segment , & vector) else {
1483- return ;
1484- } ;
1485-
1486- let delta = input. mouse . position - self . drag_start_pos ;
1487- let handle = if delta. dot ( tangent1) >= delta. dot ( tangent2) {
1488- segment1. to_manipulator_point ( )
1489- } else {
1490- segment2. to_manipulator_point ( )
1491- } ;
1492-
1493- // Now change the selection to this handle
1494- shape_editor. deselect_all_points ( ) ;
1495- shape_editor. select_point_by_layer_and_id ( handle, layer) ;
1496-
1497- responses. add ( PathToolMessage :: SelectionChanged ) ;
1498- }
1499- }
1457+ let delta = input. mouse . position - self . drag_start_pos ;
1458+ let handle = if delta. dot ( tangent1) >= delta. dot ( tangent2) {
1459+ segment1. to_manipulator_point ( )
1460+ } else {
1461+ segment2. to_manipulator_point ( )
1462+ } ;
15001463
1501- if self . alt_dragging_from_anchor && !equidistant && self . alt_clicked_on_anchor {
1502- was_alt_dragging = true ;
1503- self . alt_dragging_from_anchor = false ;
1504- self . alt_clicked_on_anchor = false ;
1505- }
1464+ // Now change the selection to this handle
1465+ shape_editor. deselect_all_points ( ) ;
1466+ shape_editor. select_point_by_layer_and_id ( handle, layer) ;
15061467
1507- let mut skip_opposite = false ;
1508- if self . temporary_colinear_handles && !lock_angle {
1509- shape_editor. disable_colinear_handles_state_on_selected ( & document. network_interface , responses) ;
1510- self . temporary_colinear_handles = false ;
1511- skip_opposite = true ;
1468+ responses. add ( PathToolMessage :: SelectionChanged ) ;
15121469 }
1513- shape_editor. move_selected_points_and_segments ( handle_lengths, document, snapped_delta, equidistant, true , was_alt_dragging, opposite, skip_opposite, responses) ;
1514- self . previous_mouse_position += document_to_viewport. inverse ( ) . transform_vector2 ( snapped_delta) ;
1515- } else {
1516- let Some ( axis) = self . snapping_axis else { return } ;
1517- let projected_delta = match axis {
1518- Axis :: X => DVec2 :: new ( unsnapped_delta. x , 0. ) ,
1519- Axis :: Y => DVec2 :: new ( 0. , unsnapped_delta. y ) ,
1520- _ => DVec2 :: new ( unsnapped_delta. x , 0. ) ,
1521- } ;
1522- shape_editor. move_selected_points_and_segments ( handle_lengths, document, projected_delta, equidistant, true , false , opposite, false , responses) ;
1523- self . previous_mouse_position += document_to_viewport. inverse ( ) . transform_vector2 ( unsnapped_delta) ;
15241470 }
15251471
1526- // Constantly checking and changing the snapping axis based on current mouse position
1527- if snap_axis && self . snapping_axis . is_some ( ) {
1528- let Some ( current_axis) = self . snapping_axis else { return } ;
1529- let total_delta = self . drag_start_pos - input. mouse . position ;
1472+ if self . alt_dragging_from_anchor && !equidistant && self . alt_clicked_on_anchor {
1473+ was_alt_dragging = true ;
1474+ self . alt_dragging_from_anchor = false ;
1475+ self . alt_clicked_on_anchor = false ;
1476+ }
15301477
1531- 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 ) {
1532- self . stop_snap_along_axis ( shape_editor, document, input, responses) ;
1533- self . start_snap_along_axis ( shape_editor, document, input, responses) ;
1534- }
1478+ let mut skip_opposite = false ;
1479+ if self . temporary_colinear_handles && !lock_angle {
1480+ shape_editor. disable_colinear_handles_state_on_selected ( & document. network_interface , responses) ;
1481+ self . temporary_colinear_handles = false ;
1482+ skip_opposite = true ;
15351483 }
1484+ shape_editor. move_selected_points_and_segments ( handle_lengths, document, snapped_delta, equidistant, true , was_alt_dragging, opposite, skip_opposite, responses) ;
1485+ self . previous_mouse_position += document_to_viewport. inverse ( ) . transform_vector2 ( snapped_delta) ;
1486+ self . snap_offset += document_to_viewport. inverse ( ) . transform_vector2 ( snapped_delta) ;
15361487 }
15371488
15381489 fn pivot_gizmo ( & self ) -> PivotGizmo {
0 commit comments