Refactor collection of snap targets (#2114)

* Collect snap targets cleanup

* Make Clippy happy

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
James Lindsay
2024-11-20 22:27:49 -08:00
committed by GitHub
co-authored by Keavon Chambers
parent d7a271f675
commit 51ce51ea8c
11 changed files with 133 additions and 83 deletions
@@ -50,8 +50,8 @@ impl AlignmentSnapper {
}
}
pub fn snap_bbox_points(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint) {
self.collect_bounding_box_points(snap_data, point.source_index == 0);
pub fn snap_bbox_points(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint, config: SnapTypeConfiguration) {
self.collect_bounding_box_points(snap_data, !config.use_existing_candidates);
let unselected_geometry = if snap_data.document.snapping_state.target_enabled(SnapTarget::Alignment(AlignmentSnapTarget::Handle)) {
snap_data.node_snap_cache.map(|cache| cache.unselected.as_slice()).unwrap_or(&[])
} else {
@@ -154,23 +154,23 @@ impl AlignmentSnapper {
_ => {}
}
}
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults) {
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, config: SnapTypeConfiguration) {
let is_bbox = matches!(point.source, SnapSource::BoundingBox(_));
let is_geometry = matches!(point.source, SnapSource::Geometry(_));
let geometry_selected = snap_data.has_manipulators();
if is_bbox || (is_geometry && geometry_selected) || (is_geometry && point.alignment) {
self.snap_bbox_points(snap_data, point, snap_results, SnapConstraint::None);
self.snap_bbox_points(snap_data, point, snap_results, SnapConstraint::None, config);
}
}
pub fn constrained_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint) {
pub fn constrained_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint, config: SnapTypeConfiguration) {
let is_bbox = matches!(point.source, SnapSource::BoundingBox(_));
let is_geometry = matches!(point.source, SnapSource::Geometry(_));
let geometry_selected = snap_data.has_manipulators();
if is_bbox || (is_geometry && geometry_selected) || (is_geometry && point.alignment) {
self.snap_bbox_points(snap_data, point, snap_results, constraint);
self.snap_bbox_points(snap_data, point, snap_results, constraint, config);
}
}
}
@@ -323,22 +323,23 @@ impl DistributionSnapper {
}
}
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, bounds: Option<Rect>) {
let Some(bounds) = bounds else { return };
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, config: SnapTypeConfiguration) {
let Some(bounds) = config.bbox else { return };
if point.source != SnapSource::BoundingBox(BoundingBoxSnapSource::Center) || !snap_data.document.snapping_state.bounds.distribute {
return;
}
self.collect_bounding_box_points(snap_data, point.source_index == 0, bounds);
self.collect_bounding_box_points(snap_data, config.accept_distribution, bounds);
self.snap_bbox_points(snap_tolerance(snap_data.document), point, snap_results, SnapConstraint::None, bounds);
}
pub fn constrained_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint, bounds: Option<Rect>) {
let Some(bounds) = bounds else { return };
pub fn constrained_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint, config: SnapTypeConfiguration) {
let Some(bounds) = config.bbox else { return };
if point.source != SnapSource::BoundingBox(BoundingBoxSnapSource::Center) || !snap_data.document.snapping_state.bounds.distribute {
return;
}
self.collect_bounding_box_points(snap_data, point.source_index == 0, bounds);
self.collect_bounding_box_points(snap_data, config.accept_distribution, bounds);
self.snap_bbox_points(snap_tolerance(snap_data.document), point, snap_results, constraint, bounds);
}
}
@@ -92,8 +92,8 @@ impl LayerSnapper {
}
}
}
pub fn free_snap_paths(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults) {
self.collect_paths(snap_data, point.source_index == 0);
pub fn free_snap_paths(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, config: SnapTypeConfiguration) {
self.collect_paths(snap_data, !config.use_existing_candidates);
let document = snap_data.document;
let normals = document.snapping_state.target_enabled(SnapTarget::Geometry(GeometrySnapTarget::Normal));
@@ -131,9 +131,9 @@ impl LayerSnapper {
}
}
pub fn snap_paths_constrained(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint) {
pub fn snap_paths_constrained(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint, config: SnapTypeConfiguration) {
let document = snap_data.document;
self.collect_paths(snap_data, point.source_index == 0);
self.collect_paths(snap_data, !config.use_existing_candidates);
let tolerance = snap_tolerance(document);
let constraint_path = if let SnapConstraint::Circle { center, radius } = constraint {
@@ -182,6 +182,10 @@ impl LayerSnapper {
if !document.network_interface.is_artboard(&layer.to_node(), &[]) || snap_data.ignore.contains(&layer) {
continue;
}
if self.points_to_snap.len() >= crate::consts::MAX_LAYER_SNAP_POINTS {
warn!("Snap point overflow; skipping.");
return;
}
if document.snapping_state.target_enabled(SnapTarget::Artboard(ArtboardSnapTarget::Corner)) {
let Some(bounds) = document
@@ -201,6 +205,10 @@ impl LayerSnapper {
if snap_data.ignore_bounds(layer) {
continue;
}
if self.points_to_snap.len() >= crate::consts::MAX_LAYER_SNAP_POINTS {
warn!("Snap point overflow; skipping.");
return;
}
let Some(bounds) = document.metadata().bounding_box_with_transform(layer, DAffine2::IDENTITY) else {
continue;
};
@@ -210,7 +218,6 @@ impl LayerSnapper {
}
}
pub fn snap_anchors(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, c: SnapConstraint, constrained_point: DVec2) {
self.collect_anchors(snap_data, point.source_index == 0);
let mut best = None;
for candidate in &self.points_to_snap {
// Candidate is not on constraint
@@ -244,14 +251,16 @@ impl LayerSnapper {
snap_results.points.push(result);
}
}
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults) {
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, config: SnapTypeConfiguration) {
self.collect_anchors(snap_data, !config.use_existing_candidates);
self.snap_anchors(snap_data, point, snap_results, SnapConstraint::None, point.document_point);
self.free_snap_paths(snap_data, point, snap_results);
self.free_snap_paths(snap_data, point, snap_results, config);
}
pub fn constrained_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint) {
pub fn constrained_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint, config: SnapTypeConfiguration) {
self.collect_anchors(snap_data, !config.use_existing_candidates);
self.snap_anchors(snap_data, point, snap_results, constraint, constraint.projection(point.document_point));
self.snap_paths_constrained(snap_data, point, snap_results, constraint);
self.snap_paths_constrained(snap_data, point, snap_results, constraint, config);
}
}
@@ -313,7 +322,6 @@ pub struct SnapCandidatePoint {
pub document_point: DVec2,
pub source: SnapSource,
pub target: SnapTarget,
pub source_index: usize,
pub quad: Option<Quad>,
pub neighbors: Vec<DVec2>,
pub alignment: bool,
@@ -417,6 +425,9 @@ fn subpath_anchor_snap_points(layer: LayerNodeIdentifier, subpath: &Subpath<Poin
if snap_data.ignore_manipulator(layer, subpath.manipulator_groups()[index].id) || snap_data.ignore_manipulator(layer, subpath.manipulator_groups()[(index + 1) % subpath.len()].id) {
continue;
}
if points.len() >= crate::consts::MAX_LAYER_SNAP_POINTS {
return;
}
let in_handle = curve.handle_start().map(|handle| handle - curve.start).filter(handle_not_under(to_document));
let out_handle = curve.handle_end().map(|handle| handle - curve.end).filter(handle_not_under(to_document));
@@ -435,6 +446,10 @@ fn subpath_anchor_snap_points(layer: LayerNodeIdentifier, subpath: &Subpath<Poin
continue;
}
if points.len() >= crate::consts::MAX_LAYER_SNAP_POINTS {
return;
}
let colinear = are_manipulator_handles_colinear(group, to_document, subpath, index);
if colinear && document.snapping_state.target_enabled(SnapTarget::Geometry(GeometrySnapTarget::AnchorWithColinearHandles)) {
@@ -471,6 +486,9 @@ pub fn get_layer_snap_points(layer: LayerNodeIdentifier, snap_data: &SnapData, p
if document.network_interface.is_artboard(&layer.to_node(), &[]) {
return;
}
if points.len() >= crate::consts::MAX_LAYER_SNAP_POINTS {
return;
}
if layer.has_children(document.metadata()) {
for child in layer.descendants(document.metadata()) {