mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 07:18:04 +08:00
Update the bounding box snapping modes to use Align with Edges for edges and alignment (#2185)
* Fix snapping to respect rotation of bounding box Fixes snapping behaviour which defaulted to X and Y axes. * Remove redundant align along edges * Code review * Update manual --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -91,7 +91,6 @@ impl SnappingState {
|
||||
match target {
|
||||
SnapTarget::BoundingBox(target) => match target {
|
||||
BoundingBoxSnapTarget::CornerPoint => self.bounding_box.corner_point,
|
||||
BoundingBoxSnapTarget::AlongEdge => self.bounding_box.along_edge,
|
||||
BoundingBoxSnapTarget::EdgeMidpoint => self.bounding_box.edge_midpoint,
|
||||
BoundingBoxSnapTarget::CenterPoint => self.bounding_box.center_point,
|
||||
},
|
||||
@@ -106,7 +105,7 @@ impl SnappingState {
|
||||
SnapTarget::Artboard(_) => self.artboards,
|
||||
SnapTarget::Grid(_) => self.grid_snapping,
|
||||
SnapTarget::Alignment(AlignmentSnapTarget::AlignWithAnchorPoint) => self.path.align_with_anchor_point,
|
||||
SnapTarget::Alignment(_) => self.bounding_box.align_with_corner_point,
|
||||
SnapTarget::Alignment(_) => self.bounding_box.align_with_edges,
|
||||
SnapTarget::DistributeEvenly(_) => self.bounding_box.distribute_evenly,
|
||||
_ => false,
|
||||
}
|
||||
@@ -119,8 +118,7 @@ pub struct BoundingBoxSnapping {
|
||||
pub center_point: bool,
|
||||
pub corner_point: bool,
|
||||
pub edge_midpoint: bool,
|
||||
pub along_edge: bool,
|
||||
pub align_with_corner_point: bool,
|
||||
pub align_with_edges: bool,
|
||||
pub distribute_evenly: bool,
|
||||
}
|
||||
|
||||
@@ -130,8 +128,7 @@ impl Default for BoundingBoxSnapping {
|
||||
center_point: true,
|
||||
corner_point: true,
|
||||
edge_midpoint: true,
|
||||
along_edge: true,
|
||||
align_with_corner_point: true,
|
||||
align_with_edges: true,
|
||||
distribute_evenly: true,
|
||||
}
|
||||
}
|
||||
@@ -378,13 +375,11 @@ impl fmt::Display for SnapSource {
|
||||
}
|
||||
|
||||
type GetSnapState = for<'a> fn(&'a mut SnappingState) -> &'a mut bool;
|
||||
pub const SNAP_FUNCTIONS_FOR_BOUNDING_BOXES: [(&str, GetSnapState, &str); 6] = [
|
||||
pub const SNAP_FUNCTIONS_FOR_BOUNDING_BOXES: [(&str, GetSnapState, &str); 5] = [
|
||||
(
|
||||
// TODO: Rename to "Beyond Edges" and update behavior to snap to an infinite extension of the bounding box edges
|
||||
// TODO: (even when the layer is locally rotated) instead of horizontally/vertically aligning with the corner points
|
||||
"Align with Corner Points",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.align_with_corner_point) as GetSnapState,
|
||||
"Snaps to horizontal/vertical alignment with the corner points of any layer's bounding box",
|
||||
"Align with Edges",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.align_with_edges) as GetSnapState,
|
||||
"Snaps to horizontal/vertical alignment with the edges of any layer's bounding box",
|
||||
),
|
||||
(
|
||||
"Corner Points",
|
||||
@@ -401,11 +396,6 @@ pub const SNAP_FUNCTIONS_FOR_BOUNDING_BOXES: [(&str, GetSnapState, &str); 6] = [
|
||||
(|snapping_state| &mut snapping_state.bounding_box.edge_midpoint) as GetSnapState,
|
||||
"Snaps to any of the four points at the middle of the edges of any layer's bounding box",
|
||||
),
|
||||
(
|
||||
"Along Edges",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.along_edge) as GetSnapState,
|
||||
"Snaps anywhere along the four edges of any layer's bounding box",
|
||||
),
|
||||
(
|
||||
"Distribute Evenly",
|
||||
(|snapping_state| &mut snapping_state.bounding_box.distribute_evenly) as GetSnapState,
|
||||
@@ -463,7 +453,6 @@ pub enum BoundingBoxSnapTarget {
|
||||
CornerPoint,
|
||||
CenterPoint,
|
||||
EdgeMidpoint,
|
||||
AlongEdge,
|
||||
}
|
||||
|
||||
impl fmt::Display for BoundingBoxSnapTarget {
|
||||
@@ -472,7 +461,6 @@ impl fmt::Display for BoundingBoxSnapTarget {
|
||||
BoundingBoxSnapTarget::CornerPoint => write!(f, "Bounding Box: Corner Point"),
|
||||
BoundingBoxSnapTarget::CenterPoint => write!(f, "Bounding Box: Center Point"),
|
||||
BoundingBoxSnapTarget::EdgeMidpoint => write!(f, "Bounding Box: Edge Midpoint"),
|
||||
BoundingBoxSnapTarget::AlongEdge => write!(f, "Bounding Box: Along Edge"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ pub use {alignment_snapper::*, distribution_snapper::*, grid_snapper::*, layer_s
|
||||
use crate::consts::{COLOR_OVERLAY_BLUE, COLOR_OVERLAY_SNAP_BACKGROUND, COLOR_OVERLAY_WHITE};
|
||||
use crate::messages::portfolio::document::overlays::utility_types::{OverlayContext, Pivot};
|
||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||
use crate::messages::portfolio::document::utility_types::misc::{BoundingBoxSnapTarget, GridSnapTarget, PathSnapTarget, SnapTarget};
|
||||
use crate::messages::portfolio::document::utility_types::misc::{GridSnapTarget, PathSnapTarget, SnapTarget};
|
||||
use crate::messages::prelude::*;
|
||||
|
||||
use bezier_rs::{Subpath, TValue};
|
||||
@@ -135,14 +135,7 @@ fn get_closest_line(lines: &[SnappedLine]) -> Option<&SnappedPoint> {
|
||||
fn get_closest_intersection(snap_to: DVec2, curves: &[SnappedCurve]) -> Option<SnappedPoint> {
|
||||
let mut best = None;
|
||||
for curve_i in curves {
|
||||
if curve_i.point.target == SnapTarget::BoundingBox(BoundingBoxSnapTarget::AlongEdge) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for curve_j in curves {
|
||||
if curve_j.point.target == SnapTarget::BoundingBox(BoundingBoxSnapTarget::AlongEdge) {
|
||||
continue;
|
||||
}
|
||||
if curve_i.start == curve_j.start && curve_i.layer == curve_j.layer {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ impl AlignmentSnapper {
|
||||
let document = snap_data.document;
|
||||
|
||||
self.bounding_box_points.clear();
|
||||
if !document.snapping_state.bounding_box.align_with_corner_point {
|
||||
if !document.snapping_state.bounding_box.align_with_edges {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,9 @@ impl AlignmentSnapper {
|
||||
Quad::intersect_rays(target_point.document_point, DVec2::X, origin, direction),
|
||||
]
|
||||
} else {
|
||||
[DVec2::new(point.document_point.x, target_position.y), DVec2::new(target_position.x, point.document_point.y)].map(Some)
|
||||
let Some(quad) = target_point.quad.map(|quad| quad.0) else { continue };
|
||||
let edges = [quad[1] - quad[0], quad[3] - quad[0]];
|
||||
edges.map(|edge| edge.try_normalize().map(|edge| (point.document_point - target_position).project_onto(edge) + target_position))
|
||||
};
|
||||
|
||||
let target_path = matches!(target_point.target, SnapTarget::Path(_));
|
||||
|
||||
@@ -86,9 +86,6 @@ impl LayerSnapper {
|
||||
}
|
||||
}
|
||||
}
|
||||
if !snap_data.ignore_bounds(layer) {
|
||||
self.add_layer_bounds(document, layer, SnapTarget::BoundingBox(BoundingBoxSnapTarget::AlongEdge));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user