@@ -598,6 +598,8 @@ struct PathToolData {
598598 started_drawing_from_inside : bool ,
599599 first_selected_with_single_click : bool ,
600600 stored_selection : Option < HashMap < LayerNodeIdentifier , SelectedLayerState > > ,
601+ snap_offset : DVec2 ,
602+
601603 last_drill_through_click_position : Option < DVec2 > ,
602604 drill_through_cycle_index : usize ,
603605 drill_through_cycle_count : usize ,
@@ -730,6 +732,7 @@ impl PathToolData {
730732 self . opposing_handle_lengths = None ;
731733
732734 self . drag_start_pos = input. mouse . position ;
735+ self . snap_offset = DVec2 :: ZERO ;
733736
734737 if input. time - self . last_click_time > DOUBLE_CLICK_MILLISECONDS {
735738 self . saved_points_before_anchor_convert_smooth_sharp . clear ( ) ;
@@ -1143,50 +1146,6 @@ impl PathToolData {
11431146 document. metadata ( ) . document_to_viewport . transform_vector2 ( snap_result. snapped_point_document - handle_position)
11441147 }
11451148
1146- fn start_snap_along_axis ( & mut self , shape_editor : & mut ShapeState , document : & DocumentMessageHandler , input : & InputPreprocessorMessageHandler , responses : & mut VecDeque < Message > ) {
1147- // Find the negative delta to take the point to the drag start position
1148- let current_mouse = input. mouse . position ;
1149- let drag_start = self . drag_start_pos ;
1150- let opposite_delta = drag_start - current_mouse;
1151-
1152- shape_editor. move_selected_points_and_segments ( None , document, opposite_delta, false , true , false , None , false , responses) ;
1153-
1154- // Calculate the projected delta and shift the points along that delta
1155- let delta = current_mouse - drag_start;
1156- let axis = if delta. x . abs ( ) >= delta. y . abs ( ) { Axis :: X } else { Axis :: Y } ;
1157- self . snapping_axis = Some ( axis) ;
1158- let projected_delta = match axis {
1159- Axis :: X => DVec2 :: new ( delta. x , 0. ) ,
1160- Axis :: Y => DVec2 :: new ( 0. , delta. y ) ,
1161- _ => DVec2 :: new ( delta. x , 0. ) ,
1162- } ;
1163-
1164- shape_editor. move_selected_points_and_segments ( None , document, projected_delta, false , true , false , None , false , responses) ;
1165- }
1166-
1167- fn stop_snap_along_axis ( & mut self , shape_editor : & mut ShapeState , document : & DocumentMessageHandler , input : & InputPreprocessorMessageHandler , responses : & mut VecDeque < Message > ) {
1168- // Calculate the negative delta of the selection and move it back to the drag start
1169- let current_mouse = input. mouse . position ;
1170- let drag_start = self . drag_start_pos ;
1171-
1172- let opposite_delta = drag_start - current_mouse;
1173- let Some ( axis) = self . snapping_axis else { return } ;
1174- let opposite_projected_delta = match axis {
1175- Axis :: X => DVec2 :: new ( opposite_delta. x , 0. ) ,
1176- Axis :: Y => DVec2 :: new ( 0. , opposite_delta. y ) ,
1177- _ => DVec2 :: new ( opposite_delta. x , 0. ) ,
1178- } ;
1179-
1180- shape_editor. move_selected_points_and_segments ( None , document, opposite_projected_delta, false , true , false , None , false , responses) ;
1181-
1182- // Calculate what actually would have been the original delta for the point, and apply that
1183- let delta = current_mouse - drag_start;
1184-
1185- shape_editor. move_selected_points_and_segments ( None , document, delta, false , true , false , None , false , responses) ;
1186-
1187- self . snapping_axis = None ;
1188- }
1189-
11901149 fn get_normalized_tangent ( & mut self , point : PointId , segment : SegmentId , vector : & Vector ) -> Option < DVec2 > {
11911150 let other_point = vector. other_point ( segment, point) ?;
11921151 let position = ManipulatorPointId :: Anchor ( point) . get_position ( vector) ?;
@@ -1404,10 +1363,15 @@ impl PathToolData {
14041363 . any ( |point| matches ! ( point, ManipulatorPointId :: EndHandle ( _) | ManipulatorPointId :: PrimaryHandle ( _) ) ) ;
14051364
14061365 // This is where it starts snapping along axis
1407- if snap_axis && self . snapping_axis . is_none ( ) && !single_handle_selected {
1408- self . start_snap_along_axis ( shape_editor, document, input, responses) ;
1409- } else if !snap_axis && self . snapping_axis . is_some ( ) {
1410- self . stop_snap_along_axis ( shape_editor, document, input, responses) ;
1366+ if snap_axis && !single_handle_selected {
1367+ let total_delta = self . drag_start_pos - input. mouse . position ;
1368+ if total_delta. x . abs ( ) > total_delta. y . abs ( ) {
1369+ self . snapping_axis = Some ( Axis :: X ) ;
1370+ } else {
1371+ self . snapping_axis = Some ( Axis :: Y ) ;
1372+ }
1373+ } else {
1374+ self . snapping_axis = None ;
14111375 }
14121376
14131377 let document_to_viewport = document. metadata ( ) . document_to_viewport ;
@@ -1447,87 +1411,74 @@ impl PathToolData {
14471411 viewport,
14481412 )
14491413 } else {
1450- shape_editor. snap ( & mut self . snap_manager , & self . snap_cache , document, input, viewport, previous_mouse)
1414+ let constraint = if let Some ( axis) = self . snapping_axis {
1415+ match axis {
1416+ Axis :: X => SnapConstraint :: Direction ( DVec2 :: X ) ,
1417+ Axis :: Y => SnapConstraint :: Direction ( DVec2 :: Y ) ,
1418+ _ => SnapConstraint :: None ,
1419+ }
1420+ } else {
1421+ SnapConstraint :: None
1422+ } ;
1423+ shape_editor. snap ( & mut self . snap_manager , & self . snap_cache , document, input, viewport, previous_mouse, constraint, self . snap_offset )
14511424 } ;
14521425
14531426 let handle_lengths = if equidistant { None } else { self . opposing_handle_lengths . take ( ) } ;
14541427 let opposite = if lock_angle { None } else { self . opposite_handle_position } ;
1455- let unsnapped_delta = current_mouse - previous_mouse;
14561428 let mut was_alt_dragging = false ;
14571429
1458- if self . snapping_axis . is_none ( ) {
1459- if self . alt_clicked_on_anchor && !self . alt_dragging_from_anchor && self . drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD {
1460- // Checking which direction the dragging begins
1461- self . alt_dragging_from_anchor = true ;
1462- let Some ( layer) = document. network_interface . selected_nodes ( ) . selected_layers ( document. metadata ( ) ) . next ( ) else {
1430+ if self . alt_clicked_on_anchor && !self . alt_dragging_from_anchor && self . drag_start_pos . distance ( input. mouse . position ) > DRAG_THRESHOLD {
1431+ // Checking which direction the dragging begins
1432+ self . alt_dragging_from_anchor = true ;
1433+ let Some ( layer) = document. network_interface . selected_nodes ( ) . selected_layers ( document. metadata ( ) ) . next ( ) else {
1434+ return ;
1435+ } ;
1436+ let Some ( vector) = document. network_interface . compute_modified_vector ( layer) else { return } ;
1437+ let Some ( point_id) = shape_editor. selected_points ( ) . next ( ) . unwrap ( ) . get_anchor ( & vector) else {
1438+ return ;
1439+ } ;
1440+
1441+ if vector. connected_count ( point_id) == 2 {
1442+ let connected_segments: Vec < HandleId > = vector. all_connected ( point_id) . collect ( ) ;
1443+ let segment1 = connected_segments[ 0 ] ;
1444+ let Some ( tangent1) = self . get_normalized_tangent ( point_id, segment1. segment , & vector) else {
14631445 return ;
14641446 } ;
1465- let Some ( vector ) = document . network_interface . compute_modified_vector ( layer ) else { return } ;
1466- let Some ( point_id ) = shape_editor . selected_points ( ) . next ( ) . unwrap ( ) . get_anchor ( & vector) else {
1447+ let segment2 = connected_segments [ 1 ] ;
1448+ let Some ( tangent2 ) = self . get_normalized_tangent ( point_id , segment2 . segment , & vector) else {
14671449 return ;
14681450 } ;
14691451
1470- if vector. connected_count ( point_id) == 2 {
1471- let connected_segments: Vec < HandleId > = vector. all_connected ( point_id) . collect ( ) ;
1472- let segment1 = connected_segments[ 0 ] ;
1473- let Some ( tangent1) = self . get_normalized_tangent ( point_id, segment1. segment , & vector) else {
1474- return ;
1475- } ;
1476- let segment2 = connected_segments[ 1 ] ;
1477- let Some ( tangent2) = self . get_normalized_tangent ( point_id, segment2. segment , & vector) else {
1478- return ;
1479- } ;
1480-
1481- let delta = input. mouse . position - self . drag_start_pos ;
1482- let handle = if delta. dot ( tangent1) >= delta. dot ( tangent2) {
1483- segment1. to_manipulator_point ( )
1484- } else {
1485- segment2. to_manipulator_point ( )
1486- } ;
1487-
1488- // Now change the selection to this handle
1489- shape_editor. deselect_all_points ( ) ;
1490- shape_editor. select_point_by_layer_and_id ( handle, layer) ;
1491-
1492- responses. add ( PathToolMessage :: SelectionChanged ) ;
1493- }
1494- }
1452+ let delta = input. mouse . position - self . drag_start_pos ;
1453+ let handle = if delta. dot ( tangent1) >= delta. dot ( tangent2) {
1454+ segment1. to_manipulator_point ( )
1455+ } else {
1456+ segment2. to_manipulator_point ( )
1457+ } ;
14951458
1496- if self . alt_dragging_from_anchor && !equidistant && self . alt_clicked_on_anchor {
1497- was_alt_dragging = true ;
1498- self . alt_dragging_from_anchor = false ;
1499- self . alt_clicked_on_anchor = false ;
1500- }
1459+ // Now change the selection to this handle
1460+ shape_editor. deselect_all_points ( ) ;
1461+ shape_editor. select_point_by_layer_and_id ( handle, layer) ;
15011462
1502- let mut skip_opposite = false ;
1503- if self . temporary_colinear_handles && !lock_angle {
1504- shape_editor. disable_colinear_handles_state_on_selected ( & document. network_interface , responses) ;
1505- self . temporary_colinear_handles = false ;
1506- skip_opposite = true ;
1463+ responses. add ( PathToolMessage :: SelectionChanged ) ;
15071464 }
1508- shape_editor. move_selected_points_and_segments ( handle_lengths, document, snapped_delta, equidistant, true , was_alt_dragging, opposite, skip_opposite, responses) ;
1509- self . previous_mouse_position += document_to_viewport. inverse ( ) . transform_vector2 ( snapped_delta) ;
1510- } else {
1511- let Some ( axis) = self . snapping_axis else { return } ;
1512- let projected_delta = match axis {
1513- Axis :: X => DVec2 :: new ( unsnapped_delta. x , 0. ) ,
1514- Axis :: Y => DVec2 :: new ( 0. , unsnapped_delta. y ) ,
1515- _ => DVec2 :: new ( unsnapped_delta. x , 0. ) ,
1516- } ;
1517- shape_editor. move_selected_points_and_segments ( handle_lengths, document, projected_delta, equidistant, true , false , opposite, false , responses) ;
1518- self . previous_mouse_position += document_to_viewport. inverse ( ) . transform_vector2 ( unsnapped_delta) ;
15191465 }
15201466
1521- // Constantly checking and changing the snapping axis based on current mouse position
1522- if snap_axis && self . snapping_axis . is_some ( ) {
1523- let Some ( current_axis) = self . snapping_axis else { return } ;
1524- let total_delta = self . drag_start_pos - input. mouse . position ;
1467+ if self . alt_dragging_from_anchor && !equidistant && self . alt_clicked_on_anchor {
1468+ was_alt_dragging = true ;
1469+ self . alt_dragging_from_anchor = false ;
1470+ self . alt_clicked_on_anchor = false ;
1471+ }
15251472
1526- 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 ) {
1527- self . stop_snap_along_axis ( shape_editor, document, input, responses) ;
1528- self . start_snap_along_axis ( shape_editor, document, input, responses) ;
1529- }
1473+ let mut skip_opposite = false ;
1474+ if self . temporary_colinear_handles && !lock_angle {
1475+ shape_editor. disable_colinear_handles_state_on_selected ( & document. network_interface , responses) ;
1476+ self . temporary_colinear_handles = false ;
1477+ skip_opposite = true ;
15301478 }
1479+ shape_editor. move_selected_points_and_segments ( handle_lengths, document, snapped_delta, equidistant, true , was_alt_dragging, opposite, skip_opposite, responses) ;
1480+ self . previous_mouse_position += document_to_viewport. inverse ( ) . transform_vector2 ( snapped_delta) ;
1481+ self . snap_offset += document_to_viewport. inverse ( ) . transform_vector2 ( snapped_delta) ;
15311482 }
15321483
15331484 fn pivot_gizmo ( & self ) -> PivotGizmo {
0 commit comments