From bf0ec2c9c8207a13e3319bb7d4678990d433a54f Mon Sep 17 00:00:00 2001 From: 0HyperCube <78500760+0HyperCube@users.noreply.github.com> Date: Sat, 13 Jan 2024 16:10:24 +0000 Subject: [PATCH] Snapping improvements (#1567) --- .../portfolio/document/utility_types/misc.rs | 5 +++- .../tool/common_functionality/shape_editor.rs | 23 ++++++++++++++++++- .../tool/common_functionality/snapping.rs | 4 ++-- .../snapping/layer_snapper.rs | 4 ++-- .../tool/tool_messages/select_tool.rs | 4 ++++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/editor/src/messages/portfolio/document/utility_types/misc.rs b/editor/src/messages/portfolio/document/utility_types/misc.rs index 0d355894..2187ba6c 100644 --- a/editor/src/messages/portfolio/document/utility_types/misc.rs +++ b/editor/src/messages/portfolio/document/utility_types/misc.rs @@ -77,7 +77,7 @@ impl Default for SnappingState { edges: true, corners: true, edge_midpoints: false, - centres: false, + centres: true, }, nodes: NodeSnapping { paths: true, @@ -245,6 +245,9 @@ impl SnapSource { pub fn is_some(&self) -> bool { self != &Self::None } + pub fn bounding_box(&self) -> bool { + matches!(self, Self::BoundingBox(_) | Self::Board(_)) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BoundingBoxSnapTarget { diff --git a/editor/src/messages/tool/common_functionality/shape_editor.rs b/editor/src/messages/tool/common_functionality/shape_editor.rs index e0532fbe..2e48a56a 100644 --- a/editor/src/messages/tool/common_functionality/shape_editor.rs +++ b/editor/src/messages/tool/common_functionality/shape_editor.rs @@ -98,7 +98,28 @@ impl ShapeState { SnapSource::Geometry(GeometrySnapSource::Sharp) }; let Some(position) = handle.get_position(&group) else { continue }; - let point = SnapCandidatePoint::new_source(to_document.transform_point2(position) + mouse_delta, source); + let mut point = SnapCandidatePoint::new_source(to_document.transform_point2(position) + mouse_delta, source); + + let mut push_neighbour = |group: ManipulatorGroup| { + if !state.is_selected(ManipulatorPointId::new(group.id, SelectedType::Anchor)) { + point.neighbors.push(group.anchor) + } + }; + if handle == SelectedType::Anchor { + // Previous anchor (looping if closed) + if index > 0 { + push_neighbour(subpath.manipulator_groups()[index - 1]); + } else if subpath.closed() { + push_neighbour(subpath.manipulator_groups()[subpath.len() - 1]); + } + // Next anchor (looping if closed) + if index + 1 < subpath.len() { + push_neighbour(subpath.manipulator_groups()[index + 1]); + } else if subpath.closed() { + push_neighbour(subpath.manipulator_groups()[0]); + } + } + let snapped = snap_manager.free_snap(&snap_data, &point, None, false); if best_snapped.other_snap_better(&snapped) { offset = snapped.snapped_point_document - point.document_point + mouse_delta; diff --git a/editor/src/messages/tool/common_functionality/snapping.rs b/editor/src/messages/tool/common_functionality/snapping.rs index 842eccd0..3cf1b172 100644 --- a/editor/src/messages/tool/common_functionality/snapping.rs +++ b/editor/src/messages/tool/common_functionality/snapping.rs @@ -64,9 +64,9 @@ pub fn snap_tolerance(document: &DocumentMessageHandler) -> f64 { } fn compare_points(a: &&SnappedPoint, b: &&SnappedPoint) -> Ordering { - if (a.target.bounding_box() && !b.target.bounding_box()) || (a.at_intersection && !b.at_intersection) { + if (a.target.bounding_box() && !b.target.bounding_box()) || (a.at_intersection && !b.at_intersection) || (a.source.bounding_box() && !b.source.bounding_box()) { Ordering::Greater - } else if (!a.target.bounding_box() && b.target.bounding_box()) || (!a.at_intersection && b.at_intersection) { + } else if (!a.target.bounding_box() && b.target.bounding_box()) || (!a.at_intersection && b.at_intersection) || (!a.source.bounding_box() && b.source.bounding_box()) { Ordering::Less } else { a.distance.partial_cmp(&b.distance).unwrap() diff --git a/editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs b/editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs index 3810b2a9..5a2a5d4e 100644 --- a/editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs +++ b/editor/src/messages/tool/common_functionality/snapping/layer_snapper.rs @@ -330,7 +330,7 @@ impl SnapCandidatePoint { } } #[derive(Default)] -struct BBoxSnapValues { +pub struct BBoxSnapValues { corner_source: SnapSource, corner_target: SnapTarget, edge_source: SnapSource, @@ -348,7 +348,7 @@ impl BBoxSnapValues { centre_target: SnapTarget::BoundingBox(BoundingBoxSnapTarget::Centre), }; } -fn get_bbox_points(quad: Quad, points: &mut Vec, values: BBoxSnapValues, document: &DocumentMessageHandler) { +pub fn get_bbox_points(quad: Quad, points: &mut Vec, values: BBoxSnapValues, document: &DocumentMessageHandler) { for index in 0..4 { let start = quad.0[index]; let end = quad.0[(index + 1) % 4]; diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 0cde690a..70411e6b 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -281,6 +281,10 @@ impl SelectToolData { self.snap_candidates.clear(); for &layer in &self.layers_dragging { snapping::get_layer_snap_points(layer, &SnapData::new(document, input), &mut self.snap_candidates); + if let Some(bounds) = document.metadata.bounding_box_with_transform(layer, DAffine2::IDENTITY) { + let quad = document.metadata.transform_to_document(layer) * Quad::from_box(bounds); + snapping::get_bbox_points(quad, &mut self.snap_candidates, snapping::BBoxSnapValues::BOUNDING_BOX, document); + } } }