Skip to content

Commit da38f67

Browse files
4adexKeavon
andauthored
Insert point on segment by clicking once (no more sliding) and Alt+click to delete a segment (#2495)
* segment overlay change * Segment split and delete * Cleanup * graceful handling of edge cases * Moved constants to conts.rs and tuned the threshold * Remove going into another state * Insert point mode cleanup * Linting fix * Code review * Added hints * Added field for delete segment * Change controls and fix too far logic * Fixes * Code review --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
1 parent 478ace3 commit da38f67

File tree

4 files changed

+138
-127
lines changed

4 files changed

+138
-127
lines changed

editor/src/consts.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@ pub const MIN_LENGTH_FOR_SKEW_TRIANGLE_VISIBILITY: f64 = 48.;
9999
pub const MANIPULATOR_GROUP_MARKER_SIZE: f64 = 6.;
100100
pub const SELECTION_THRESHOLD: f64 = 10.;
101101
pub const HIDE_HANDLE_DISTANCE: f64 = 3.;
102-
pub const INSERT_POINT_ON_SEGMENT_TOO_FAR_DISTANCE: f64 = 50.;
103102
pub const HANDLE_ROTATE_SNAP_ANGLE: f64 = 15.;
103+
pub const SEGMENT_INSERTION_DISTANCE: f64 = 7.5;
104+
pub const SEGMENT_OVERLAY_SIZE: f64 = 10.;
104105

105106
// PEN TOOL
106107
pub const CREATE_CURVE_THRESHOLD: f64 = 5.;

editor/src/messages/input_mapper/input_mappings.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,13 @@ pub fn input_mappings() -> Mapping {
212212
entry!(KeyDown(Delete); modifiers=[Shift], action_dispatch=PathToolMessage::BreakPath),
213213
entry!(KeyDown(Backspace); modifiers=[Shift], action_dispatch=PathToolMessage::BreakPath),
214214
entry!(KeyDownNoRepeat(Tab); action_dispatch=PathToolMessage::SwapSelectedHandles),
215-
entry!(KeyDown(MouseLeft); action_dispatch=PathToolMessage::MouseDown { direct_insert_without_sliding: Control, extend_selection: Shift, lasso_select: Control, handle_drag_from_anchor: Alt }),
215+
entry!(KeyDown(MouseLeft); action_dispatch=PathToolMessage::MouseDown { extend_selection: Shift, lasso_select: Control, handle_drag_from_anchor: Alt }),
216216
entry!(KeyDown(MouseRight); action_dispatch=PathToolMessage::RightClick),
217217
entry!(KeyDown(Escape); action_dispatch=PathToolMessage::Escape),
218218
entry!(KeyDown(KeyG); action_dispatch=PathToolMessage::GRS { key: KeyG }),
219219
entry!(KeyDown(KeyR); action_dispatch=PathToolMessage::GRS { key: KeyR }),
220220
entry!(KeyDown(KeyS); action_dispatch=PathToolMessage::GRS { key: KeyS }),
221-
entry!(PointerMove; refresh_keys=[KeyC, Space, Control, Shift, Alt], action_dispatch=PathToolMessage::PointerMove { toggle_colinear: KeyC, equidistant: Alt, move_anchor_with_handles: Space, snap_angle: Shift, lock_angle: Control }),
221+
entry!(PointerMove; refresh_keys=[KeyC, Space, Control, Shift, Alt], action_dispatch=PathToolMessage::PointerMove { toggle_colinear: KeyC, equidistant: Alt, move_anchor_with_handles: Space, snap_angle: Shift, lock_angle: Control, delete_segment: Alt }),
222222
entry!(KeyDown(Delete); action_dispatch=PathToolMessage::Delete),
223223
entry!(KeyDown(KeyA); modifiers=[Accel], action_dispatch=PathToolMessage::SelectAllAnchors),
224224
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=PathToolMessage::DeselectAllPoints),

editor/src/messages/tool/common_functionality/shape_editor.rs

+54-3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ impl ClosestSegment {
104104
self.layer
105105
}
106106

107+
pub fn segment(&self) -> SegmentId {
108+
self.segment
109+
}
110+
111+
pub fn points(&self) -> [PointId; 2] {
112+
self.points
113+
}
114+
107115
pub fn closest_point_to_viewport(&self) -> DVec2 {
108116
self.bezier_point_to_viewport
109117
}
@@ -128,9 +136,7 @@ impl ClosestSegment {
128136
pub fn too_far(&self, mouse_position: DVec2, tolerance: f64, document_metadata: &DocumentMetadata) -> bool {
129137
let dist_sq = self.distance_squared(mouse_position);
130138
let stroke_width = document_metadata.document_to_viewport.decompose_scale().x.max(1.) * self.stroke_width;
131-
let stroke_width_sq = stroke_width * stroke_width;
132-
let tolerance_sq = tolerance * tolerance;
133-
(stroke_width_sq + tolerance_sq) < dist_sq
139+
(stroke_width + tolerance).powi(2) < dist_sq
134140
}
135141

136142
pub fn handle_positions(&self, document_metadata: &DocumentMetadata) -> (Option<DVec2>, Option<DVec2>) {
@@ -199,6 +205,28 @@ impl ClosestSegment {
199205
let id = self.adjusted_insert(responses);
200206
shape_editor.select_anchor_point_by_id(self.layer, id, extend_selection)
201207
}
208+
209+
pub fn calculate_perp(&self, document: &DocumentMessageHandler) -> DVec2 {
210+
let tangent = if let (Some(handle1), Some(handle2)) = self.handle_positions(document.metadata()) {
211+
(handle1 - handle2).try_normalize()
212+
} else {
213+
let [first_point, last_point] = self.points();
214+
if let Some(vector_data) = document.network_interface.compute_modified_vector(self.layer()) {
215+
if let (Some(pos1), Some(pos2)) = (
216+
ManipulatorPointId::Anchor(first_point).get_position(&vector_data),
217+
ManipulatorPointId::Anchor(last_point).get_position(&vector_data),
218+
) {
219+
(pos1 - pos2).try_normalize()
220+
} else {
221+
None
222+
}
223+
} else {
224+
None
225+
}
226+
}
227+
.unwrap_or(DVec2::ZERO);
228+
tangent.perp()
229+
}
202230
}
203231

204232
// TODO Consider keeping a list of selected manipulators to minimize traversals of the layers
@@ -900,6 +928,29 @@ impl ShapeState {
900928
.collect::<HashMap<_, _>>()
901929
}
902930

931+
pub fn dissolve_segment(&self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData, segment: SegmentId, points: [PointId; 2]) {
932+
// Checking which point is terminal point
933+
let is_point1_terminal = vector_data.connected_count(points[0]) == 1;
934+
let is_point2_terminal = vector_data.connected_count(points[1]) == 1;
935+
936+
// Delete the segment and terminal points
937+
let modification_type = VectorModificationType::RemoveSegment { id: segment };
938+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
939+
for &handles in vector_data.colinear_manipulators.iter().filter(|handles| handles.iter().any(|handle| handle.segment == segment)) {
940+
let modification_type = VectorModificationType::SetG1Continuous { handles, enabled: false };
941+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
942+
}
943+
944+
if is_point1_terminal {
945+
let modification_type = VectorModificationType::RemovePoint { id: points[0] };
946+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
947+
}
948+
if is_point2_terminal {
949+
let modification_type = VectorModificationType::RemovePoint { id: points[1] };
950+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
951+
}
952+
}
953+
903954
fn dissolve_anchor(anchor: PointId, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData) -> Option<[(HandleId, PointId); 2]> {
904955
// Delete point
905956
let modification_type = VectorModificationType::RemovePoint { id: anchor };

0 commit comments

Comments
 (0)