Skip to content

Commit 8bb8abc

Browse files
committed
Fixes the Path tool snapping to the X or Y axis with Shift held for handles (#2969)
1 parent 57055e3 commit 8bb8abc

File tree

1 file changed

+44
-20
lines changed

1 file changed

+44
-20
lines changed

editor/src/messages/tool/tool_messages/path_tool.rs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,8 +1149,6 @@ impl PathToolData {
11491149
let drag_start = self.drag_start_pos;
11501150
let opposite_delta = drag_start - current_mouse;
11511151

1152-
shape_editor.move_selected_points_and_segments(None, document, opposite_delta, false, true, false, None, false, responses);
1153-
11541152
// Calculate the projected delta and shift the points along that delta
11551153
let delta = current_mouse - drag_start;
11561154
let axis = if delta.x.abs() >= delta.y.abs() { Axis::X } else { Axis::Y };
@@ -1161,7 +1159,8 @@ impl PathToolData {
11611159
_ => DVec2::new(delta.x, 0.),
11621160
};
11631161

1164-
shape_editor.move_selected_points_and_segments(None, document, projected_delta, false, true, false, None, false, responses);
1162+
// Apply the two deltas combined
1163+
shape_editor.move_selected_points_and_segments(None, document, opposite_delta + projected_delta, false, true, false, None, false, responses);
11651164
}
11661165

11671166
fn stop_snap_along_axis(&mut self, shape_editor: &mut ShapeState, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) {
@@ -1177,12 +1176,11 @@ impl PathToolData {
11771176
_ => DVec2::new(opposite_delta.x, 0.),
11781177
};
11791178

1180-
shape_editor.move_selected_points_and_segments(None, document, opposite_projected_delta, false, true, false, None, false, responses);
1181-
11821179
// Calculate what actually would have been the original delta for the point, and apply that
11831180
let delta = current_mouse - drag_start;
11841181

1185-
shape_editor.move_selected_points_and_segments(None, document, delta, false, true, false, None, false, responses);
1182+
// Apply the two deltas combined
1183+
shape_editor.move_selected_points_and_segments(None, document, opposite_projected_delta + delta, false, true, false, None, false, responses);
11861184

11871185
self.snapping_axis = None;
11881186
}
@@ -1509,24 +1507,50 @@ impl PathToolData {
15091507
self.previous_mouse_position += document_to_viewport.inverse().transform_vector2(snapped_delta);
15101508
} else {
15111509
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);
1519-
}
15201510

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 };
1511+
// Constantly checking and changing the snapping axis based on current mouse position
15241512
let total_delta = self.drag_start_pos - input.mouse.position;
1513+
let mut current_axis = axis;
1514+
if (total_delta.x.abs() > total_delta.y.abs() && axis == Axis::Y) || (total_delta.y.abs() > total_delta.x.abs() && axis == Axis::X) {
1515+
current_axis = if axis == Axis::X { Axis::Y } else { Axis::X };
1516+
}
1517+
1518+
let document_to_viewport = document.metadata().document_to_viewport;
15251519

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);
1520+
// Correct the position from the old axis projection to the new one
1521+
if current_axis != axis {
1522+
let previous_delta = previous_mouse - self.drag_start_pos;
1523+
let current_delta = current_mouse - self.drag_start_pos;
1524+
1525+
// Where the shape currently IS
1526+
let previous_projected = match axis {
1527+
Axis::X => DVec2::new(previous_delta.x, 0.),
1528+
Axis::Y => DVec2::new(0., previous_delta.y),
1529+
_ => DVec2::new(previous_delta.x, 0.),
1530+
};
1531+
1532+
// Where we want to GO
1533+
let current_projected = match current_axis {
1534+
Axis::X => DVec2::new(current_delta.x, 0.),
1535+
Axis::Y => DVec2::new(0., current_delta.y),
1536+
_ => DVec2::new(current_delta.x, 0.),
1537+
};
1538+
1539+
let snap_delta = current_projected - previous_projected;
1540+
shape_editor.move_selected_points_and_segments(handle_lengths, document, snap_delta, equidistant, true, false, opposite, false, responses);
1541+
1542+
self.snapping_axis = Some(current_axis);
1543+
} else {
1544+
// Standard incremental move along the same axis
1545+
let projected_delta = match axis {
1546+
Axis::X => DVec2::new(unsnapped_delta.x, 0.),
1547+
Axis::Y => DVec2::new(0., unsnapped_delta.y),
1548+
_ => DVec2::new(unsnapped_delta.x, 0.),
1549+
};
1550+
shape_editor.move_selected_points_and_segments(handle_lengths, document, projected_delta, equidistant, true, false, opposite, false, responses);
15291551
}
1552+
1553+
self.previous_mouse_position += document_to_viewport.inverse().transform_vector2(unsnapped_delta);
15301554
}
15311555
}
15321556

0 commit comments

Comments
 (0)