From 0d139d284c7ec14e6356ef5312a555fb40334f1d Mon Sep 17 00:00:00 2001 From: 0SlowPoke0 Date: Sat, 26 Apr 2025 03:23:00 +0530 Subject: [PATCH 1/4] implement check-drag and angle-lock --- .../messages/input_mapper/input_mappings.rs | 2 +- .../messages/tool/tool_messages/path_tool.rs | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/editor/src/messages/input_mapper/input_mappings.rs b/editor/src/messages/input_mapper/input_mappings.rs index b75940bf09..4aaea7068c 100644 --- a/editor/src/messages/input_mapper/input_mappings.rs +++ b/editor/src/messages/input_mapper/input_mappings.rs @@ -212,7 +212,7 @@ pub fn input_mappings() -> Mapping { entry!(KeyDown(Delete); modifiers=[Shift], action_dispatch=PathToolMessage::BreakPath), entry!(KeyDown(Backspace); modifiers=[Shift], action_dispatch=PathToolMessage::BreakPath), entry!(KeyDownNoRepeat(Tab); action_dispatch=PathToolMessage::SwapSelectedHandles), - entry!(KeyDown(MouseLeft); action_dispatch=PathToolMessage::MouseDown { direct_insert_without_sliding: Control, extend_selection: Shift, lasso_select: Control, handle_drag_from_anchor: Alt }), + entry!(KeyDown(MouseLeft); action_dispatch=PathToolMessage::MouseDown { direct_insert_without_sliding: Control, extend_selection: Shift, lasso_select: Control, handle_drag_from_anchor: Alt, drag_zero_handle: Control }), entry!(KeyDown(MouseRight); action_dispatch=PathToolMessage::RightClick), entry!(KeyDown(Escape); action_dispatch=PathToolMessage::Escape), entry!(KeyDown(KeyG); action_dispatch=PathToolMessage::GRS { key: KeyG }), diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 3954bf96f6..92b7d9b380 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -68,6 +68,7 @@ pub enum PathToolMessage { extend_selection: Key, lasso_select: Key, handle_drag_from_anchor: Key, + drag_zero_handle: Key, }, NudgeSelectedPoints { delta_x: f64, @@ -498,6 +499,7 @@ impl PathToolData { direct_insert_without_sliding: bool, lasso_select: bool, handle_drag_from_anchor: bool, + drag_zero_handle: bool, ) -> PathToolFsmState { self.double_click_handled = false; self.opposing_handle_lengths = None; @@ -560,6 +562,24 @@ impl PathToolData { } } + if let Some((Some(point), Some(vector_data))) = shape_editor + .find_nearest_point_indices(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD) + .and_then(|(layer, point)| Some((point.as_anchor(), document.network_interface.compute_modified_vector(layer)))) + { + let handles = vector_data + .all_connected(point) + .filter(|handle| handle.length(&vector_data) < 1e-6) + .map(|handle| handle.to_manipulator_point()) + .collect::>(); + let endpoint = vector_data.extendable_points(false).any(|anchor| point == anchor); + + if drag_zero_handle && (handles.len() == 1 && !endpoint) { + shape_editor.deselect_all_points(); + shape_editor.select_points_by_manipulator_id(&handles); + shape_editor.convert_selected_manipulators_to_colinear_handles(responses, document); + } + } + self.start_dragging_point(selected_points, input, document, shape_editor); responses.add(OverlaysMessage::Draw); } @@ -1160,12 +1180,14 @@ impl Fsm for PathToolFsmState { extend_selection, lasso_select, handle_drag_from_anchor, + drag_zero_handle, }, ) => { let extend_selection = input.keyboard.get(extend_selection as usize); let lasso_select = input.keyboard.get(lasso_select as usize); let direct_insert_without_sliding = input.keyboard.get(direct_insert_without_sliding as usize); let handle_drag_from_anchor = input.keyboard.get(handle_drag_from_anchor as usize); + let drag_zero_handle = input.keyboard.get(drag_zero_handle as usize); tool_data.selection_mode = None; tool_data.lasso_polygon.clear(); @@ -1179,6 +1201,7 @@ impl Fsm for PathToolFsmState { direct_insert_without_sliding, lasso_select, handle_drag_from_anchor, + drag_zero_handle, ) } ( @@ -1467,6 +1490,7 @@ impl Fsm for PathToolFsmState { tool_data.alt_dragging_from_anchor = false; tool_data.alt_clicked_on_anchor = false; + tool_data.angle_locked = false; if tool_data.select_anchor_toggled { shape_editor.deselect_all_points(); From be3d48f0b44b5eba99f191f61ea5cd9d58cf6f47 Mon Sep 17 00:00:00 2001 From: 0SlowPoke0 Date: Sat, 26 Apr 2025 03:49:56 +0530 Subject: [PATCH 2/4] track bool --- editor/src/messages/tool/tool_messages/path_tool.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 92b7d9b380..8a80b738a1 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -1422,6 +1422,7 @@ impl Fsm for PathToolFsmState { tool_data.saved_points_before_handle_drag.clear(); tool_data.handle_drag_toggle = false; } + tool_data.angle_locked = false; responses.add(DocumentMessage::AbortTransaction); tool_data.snap_manager.cleanup(responses); PathToolFsmState::Ready From a2f96b10326f929f298e1a5d5115e2500bdd797e Mon Sep 17 00:00:00 2001 From: 0SlowPoke0 Date: Sat, 26 Apr 2025 18:36:15 +0530 Subject: [PATCH 3/4] flip-smooth-sharp --- .../messages/tool/common_functionality/shape_editor.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editor/src/messages/tool/common_functionality/shape_editor.rs b/editor/src/messages/tool/common_functionality/shape_editor.rs index db61db5221..60109f4be7 100644 --- a/editor/src/messages/tool/common_functionality/shape_editor.rs +++ b/editor/src/messages/tool/common_functionality/shape_editor.rs @@ -1384,13 +1384,13 @@ impl ShapeState { let (id, anchor) = result?; let handles = vector_data.all_connected(id); - let mut positions = handles + let positions = handles .filter_map(|handle| handle.to_manipulator_point().get_position(&vector_data)) - .filter(|&handle| !anchor.abs_diff_eq(handle, 1e-5)); + .filter(|&handle| anchor.abs_diff_eq(handle, 1e-5)) + .count(); // Check by comparing the handle positions to the anchor if this manipulator group is a point - let already_sharp = positions.next().is_none(); - if already_sharp { + if positions != 0 { self.convert_manipulator_handles_to_colinear(&vector_data, id, responses, layer); } else { for handle in vector_data.all_connected(id) { From 13c5db1057af58e4cbe47ed816a3a8952942de28 Mon Sep 17 00:00:00 2001 From: 0SlowPoke0 Date: Tue, 13 May 2025 11:20:04 +0530 Subject: [PATCH 4/4] fixed bugs --- editor/src/messages/tool/tool_messages/path_tool.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 184316f90e..74c57c1b73 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -721,13 +721,14 @@ impl PathToolData { if relative_vector.length() < 25. && lock_angle && !self.angle_locked { if let Some(angle) = calculate_lock_angle(self, shape_editor, responses, document, &vector_data, handle_id) { self.angle = angle; + self.angle_locked = true; + self.current_selected_handle_id = Some(handle_id); return angle; } } } // When the angle is locked we use the old angle - if self.current_selected_handle_id == Some(handle_id) && lock_angle { self.angle_locked = true; return self.angle; @@ -767,6 +768,7 @@ impl PathToolData { origin: anchor_position, direction: handle_direction.normalize_or_zero(), }; + self.snap_manager.constrained_snap(&snap_data, &snap_point, snap_constraint, Default::default()) } false => self.snap_manager.free_snap(&snap_data, &snap_point, Default::default()),