Skip to content
38 changes: 36 additions & 2 deletions editor/src/messages/tool/tool_messages/path_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ struct PathToolData {
last_clicked_point_was_selected: bool,
last_clicked_segment_was_selected: bool,
snapping_axis: Option<Axis>,
snap_axis_origin: Option<DVec2>,
alt_clicked_on_anchor: bool,
alt_dragging_from_anchor: bool,
angle_locked: bool,
Expand Down Expand Up @@ -1970,7 +1971,7 @@ impl Fsm for PathToolFsmState {
// Draw the snapping axis lines
if tool_data.snapping_axis.is_some() {
let Some(axis) = tool_data.snapping_axis else { return self };
let origin = tool_data.drag_start_pos;
let origin = tool_data.snap_axis_origin.or_else(|| tool_data.snap_manager.indicator_pos()).unwrap_or(tool_data.drag_start_pos);
let viewport_diagonal = viewport.size().into_dvec2().length();

match axis {
Expand Down Expand Up @@ -2107,16 +2108,43 @@ impl Fsm for PathToolFsmState {
}

let break_molding = input.keyboard.get(break_colinear_molding as usize);
let snap_axis_state = input.keyboard.get(snap_angle as usize);

// Logic for molding segment
if let Some(segment) = &mut tool_data.segment
&& let Some(molding_segment_handles) = tool_data.molding_info
{
// Constrain molding to a single axis when Shift is held
let mouse_position = if snap_axis_state {
// Calculate the midpoint along the actual bezier curve for the axis overlay.
// This uses the curve captured at mouse-down (which includes all prior modifications),
// so after a previous bulge the axis origin reflects the updated curve shape.
let transform = document.metadata().transform_to_viewport(segment.layer());
let curve_midpoint = point_to_dvec2(segment.pathseg().eval(0.5));
let midpoint = transform.transform_point2(curve_midpoint);
tool_data.snap_axis_origin = Some(midpoint);

// Constrain mouse movement relative to drag start so molding delta stays correct
let drag_start = tool_data.drag_start_pos;
let delta = input.mouse.position - drag_start;
let axis = if delta.x.abs() >= delta.y.abs() { Axis::X } else { Axis::Y };
tool_data.snapping_axis = Some(axis);
match axis {
Axis::X => DVec2::new(input.mouse.position.x, drag_start.y),
Axis::Y => DVec2::new(drag_start.x, input.mouse.position.y),
_ => input.mouse.position,
}
} else {
tool_data.snapping_axis = None;
tool_data.snap_axis_origin = None;
input.mouse.position
};

tool_data.temporary_adjacent_handles_while_molding = segment.mold_handle_positions(
document,
responses,
molding_segment_handles,
input.mouse.position,
mouse_position,
break_molding,
tool_data.temporary_adjacent_handles_while_molding,
);
Expand Down Expand Up @@ -2371,6 +2399,10 @@ impl Fsm for PathToolFsmState {
tool_data.molding_segment = false;
tool_data.temporary_adjacent_handles_while_molding = None;
tool_data.angle_locked = false;
tool_data.snapping_axis = None;
tool_data.snap_axis_origin = None;
tool_data.snapping_axis = None;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you setting this to NONE twice ??

tool_data.snap_axis_origin = None;
responses.add(DocumentMessage::AbortTransaction);
tool_data.snap_manager.cleanup(responses);
PathToolFsmState::Ready
Expand Down Expand Up @@ -2619,6 +2651,8 @@ impl Fsm for PathToolFsmState {
}

tool_data.snapping_axis = None;
tool_data.snap_axis_origin = None;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here !

tool_data.snap_axis_origin = None;
tool_data.sliding_point_info = None;

if drag_occurred || extend_selection {
Expand Down
Loading