Skip to content

Insert point on segment by clicking once (no more sliding) and Alt+click to delete a segment #2495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Apr 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7590fff
segment overlay change
4adex Mar 28, 2025
722079f
Segment split and delete
4adex Mar 31, 2025
b530d0b
Cleanup
4adex Mar 31, 2025
0ca2676
graceful handling of edge cases
4adex Mar 31, 2025
04f7634
Merge branch 'master' into segment_features_path_tool
4adex Mar 31, 2025
b4fb9bb
Merge branch 'master' into segment_features_path_tool
Keavon Apr 6, 2025
d2e40d5
Merge branch 'master' into segment_features_path_tool
4adex Apr 13, 2025
ab84190
Moved constants to conts.rs and tuned the threshold
4adex Apr 13, 2025
84c323a
Merge branch 'master' into segment_features_path_tool
Keavon Apr 14, 2025
660ce80
Merge branch 'master' into segment_features_path_tool
4adex Apr 17, 2025
177a374
Remove going into another state
4adex Apr 18, 2025
dc3d41f
Insert point mode cleanup
4adex Apr 18, 2025
e0a5f1b
Merge branch 'master' into segment_features_path_tool
4adex Apr 18, 2025
b09e475
Linting fix
4adex Apr 18, 2025
ddd05da
Code review
4adex Apr 18, 2025
c62edec
Added hints
4adex Apr 18, 2025
eb41b42
Added field for delete segment
4adex Apr 21, 2025
3ace632
Merge branch 'master' into segment_features_path_tool
Keavon Apr 23, 2025
8f1930e
Change controls and fix too far logic
4adex Apr 26, 2025
6659b1c
Merge branch 'segment_features_path_tool' of github.com:4adex/Graphit…
4adex Apr 26, 2025
cd3ddc7
Merge branch 'master' into segment_features_path_tool
4adex Apr 26, 2025
4d612ed
Merge branch 'master' into segment_features_path_tool
Keavon Apr 29, 2025
eb12696
Fixes
Keavon Apr 29, 2025
a587596
Merge branch 'master' into segment_features_path_tool
Keavon Apr 29, 2025
b582aa0
Code review
Keavon Apr 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion editor/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ pub const MIN_LENGTH_FOR_SKEW_TRIANGLE_VISIBILITY: f64 = 48.;
pub const MANIPULATOR_GROUP_MARKER_SIZE: f64 = 6.;
pub const SELECTION_THRESHOLD: f64 = 10.;
pub const HIDE_HANDLE_DISTANCE: f64 = 3.;
pub const INSERT_POINT_ON_SEGMENT_TOO_FAR_DISTANCE: f64 = 50.;
pub const HANDLE_ROTATE_SNAP_ANGLE: f64 = 15.;
pub const SEGMENT_INSERTION_DISTANCE: f64 = 7.5;
pub const SEGMENT_OVERLAY_SIZE: f64 = 10.;

// PEN TOOL
pub const CREATE_CURVE_THRESHOLD: f64 = 5.;
Expand Down
4 changes: 2 additions & 2 deletions editor/src/messages/input_mapper/input_mappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,13 @@ 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 { extend_selection: Shift, lasso_select: Control, handle_drag_from_anchor: Alt }),
entry!(KeyDown(MouseRight); action_dispatch=PathToolMessage::RightClick),
entry!(KeyDown(Escape); action_dispatch=PathToolMessage::Escape),
entry!(KeyDown(KeyG); action_dispatch=PathToolMessage::GRS { key: KeyG }),
entry!(KeyDown(KeyR); action_dispatch=PathToolMessage::GRS { key: KeyR }),
entry!(KeyDown(KeyS); action_dispatch=PathToolMessage::GRS { key: KeyS }),
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 }),
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 }),
entry!(KeyDown(Delete); action_dispatch=PathToolMessage::Delete),
entry!(KeyDown(KeyA); modifiers=[Accel], action_dispatch=PathToolMessage::SelectAllAnchors),
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=PathToolMessage::DeselectAllPoints),
Expand Down
57 changes: 54 additions & 3 deletions editor/src/messages/tool/common_functionality/shape_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ impl ClosestSegment {
self.layer
}

pub fn segment(&self) -> SegmentId {
self.segment
}

pub fn points(&self) -> [PointId; 2] {
self.points
}

pub fn closest_point_to_viewport(&self) -> DVec2 {
self.bezier_point_to_viewport
}
Expand All @@ -128,9 +136,7 @@ impl ClosestSegment {
pub fn too_far(&self, mouse_position: DVec2, tolerance: f64, document_metadata: &DocumentMetadata) -> bool {
let dist_sq = self.distance_squared(mouse_position);
let stroke_width = document_metadata.document_to_viewport.decompose_scale().x.max(1.) * self.stroke_width;
let stroke_width_sq = stroke_width * stroke_width;
let tolerance_sq = tolerance * tolerance;
(stroke_width_sq + tolerance_sq) < dist_sq
(stroke_width + tolerance).powi(2) < dist_sq
}

pub fn handle_positions(&self, document_metadata: &DocumentMetadata) -> (Option<DVec2>, Option<DVec2>) {
Expand Down Expand Up @@ -199,6 +205,28 @@ impl ClosestSegment {
let id = self.adjusted_insert(responses);
shape_editor.select_anchor_point_by_id(self.layer, id, extend_selection)
}

pub fn calculate_perp(&self, document: &DocumentMessageHandler) -> DVec2 {
let tangent = if let (Some(handle1), Some(handle2)) = self.handle_positions(document.metadata()) {
(handle1 - handle2).try_normalize()
} else {
let [first_point, last_point] = self.points();
if let Some(vector_data) = document.network_interface.compute_modified_vector(self.layer()) {
if let (Some(pos1), Some(pos2)) = (
ManipulatorPointId::Anchor(first_point).get_position(&vector_data),
ManipulatorPointId::Anchor(last_point).get_position(&vector_data),
) {
(pos1 - pos2).try_normalize()
} else {
None
}
} else {
None
}
}
.unwrap_or(DVec2::ZERO);
tangent.perp()
}
}

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

pub fn dissolve_segment(&self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData, segment: SegmentId, points: [PointId; 2]) {
// Checking which point is terminal point
let is_point1_terminal = vector_data.connected_count(points[0]) == 1;
let is_point2_terminal = vector_data.connected_count(points[1]) == 1;

// Delete the segment and terminal points
let modification_type = VectorModificationType::RemoveSegment { id: segment };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
for &handles in vector_data.colinear_manipulators.iter().filter(|handles| handles.iter().any(|handle| handle.segment == segment)) {
let modification_type = VectorModificationType::SetG1Continuous { handles, enabled: false };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
}

if is_point1_terminal {
let modification_type = VectorModificationType::RemovePoint { id: points[0] };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
}
if is_point2_terminal {
let modification_type = VectorModificationType::RemovePoint { id: points[1] };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
}
}

fn dissolve_anchor(anchor: PointId, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData) -> Option<[(HandleId, PointId); 2]> {
// Delete point
let modification_type = VectorModificationType::RemovePoint { id: anchor };
Expand Down
Loading
Loading