mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-08 00:05:00 +00:00
Fix the Path tool's segment insertion line overlay having hysteresis with distance away from the cursor (#2677)
* Fix hysteresis in segment insertion * Update editor/src/messages/tool/common_functionality/shape_editor.rs * Update editor/src/messages/tool/common_functionality/shape_editor.rs * Fix insert point overlay --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
04d7adb867
commit
33a31b4f17
3 changed files with 12 additions and 16 deletions
|
@ -102,7 +102,7 @@ pub const MANIPULATOR_GROUP_MARKER_SIZE: f64 = 6.;
|
|||
pub const SELECTION_THRESHOLD: f64 = 10.;
|
||||
pub const HIDE_HANDLE_DISTANCE: f64 = 3.;
|
||||
pub const HANDLE_ROTATE_SNAP_ANGLE: f64 = 15.;
|
||||
pub const SEGMENT_INSERTION_DISTANCE: f64 = 7.5;
|
||||
pub const SEGMENT_INSERTION_DISTANCE: f64 = 8.;
|
||||
pub const SEGMENT_OVERLAY_SIZE: f64 = 10.;
|
||||
pub const HANDLE_LENGTH_FACTOR: f64 = 0.5;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::graph_modification_utils::{self, merge_layers};
|
||||
use super::graph_modification_utils::merge_layers;
|
||||
use super::snapping::{SnapCache, SnapCandidatePoint, SnapData, SnapManager, SnappedPoint};
|
||||
use super::utility_functions::calculate_segment_angle;
|
||||
use crate::consts::HANDLE_LENGTH_FACTOR;
|
||||
|
@ -12,7 +12,6 @@ use crate::messages::tool::common_functionality::utility_functions::is_visible_p
|
|||
use crate::messages::tool::tool_messages::path_tool::{PathOverlayMode, PointSelectState};
|
||||
use bezier_rs::{Bezier, BezierHandles, Subpath, TValue};
|
||||
use glam::{DAffine2, DVec2};
|
||||
use graphene_core::transform::Transform;
|
||||
use graphene_core::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType};
|
||||
use graphene_std::vector::{HandleId, SegmentId};
|
||||
|
||||
|
@ -149,7 +148,6 @@ pub struct ClosestSegment {
|
|||
colinear: [Option<HandleId>; 2],
|
||||
t: f64,
|
||||
bezier_point_to_viewport: DVec2,
|
||||
stroke_width: f64,
|
||||
}
|
||||
|
||||
impl ClosestSegment {
|
||||
|
@ -169,6 +167,12 @@ impl ClosestSegment {
|
|||
self.bezier_point_to_viewport
|
||||
}
|
||||
|
||||
pub fn closest_point(&self, document_metadata: &DocumentMetadata) -> DVec2 {
|
||||
let transform = document_metadata.transform_to_viewport(self.layer);
|
||||
let bezier_point = self.bezier.evaluate(TValue::Parametric(self.t));
|
||||
transform.transform_point2(bezier_point)
|
||||
}
|
||||
|
||||
/// Updates this [`ClosestSegment`] with the viewport-space location of the closest point on the segment to the given mouse position.
|
||||
pub fn update_closest_point(&mut self, document_metadata: &DocumentMetadata, mouse_position: DVec2) {
|
||||
let transform = document_metadata.transform_to_viewport(self.layer);
|
||||
|
@ -186,10 +190,8 @@ impl ClosestSegment {
|
|||
self.bezier_point_to_viewport.distance_squared(mouse_position)
|
||||
}
|
||||
|
||||
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;
|
||||
(stroke_width + tolerance).powi(2) < dist_sq
|
||||
pub fn too_far(&self, mouse_position: DVec2, tolerance: f64) -> bool {
|
||||
tolerance.powi(2) < self.distance_squared(mouse_position)
|
||||
}
|
||||
|
||||
pub fn handle_positions(&self, document_metadata: &DocumentMetadata) -> (Option<DVec2>, Option<DVec2>) {
|
||||
|
@ -1449,11 +1451,6 @@ impl ShapeState {
|
|||
if distance_squared < closest_distance_squared {
|
||||
closest_distance_squared = distance_squared;
|
||||
|
||||
// 0.5 is half the line (center to side) but it's convenient to allow targeting slightly more than half the line width
|
||||
const STROKE_WIDTH_PERCENT: f64 = 0.7;
|
||||
|
||||
let stroke_width = graph_modification_utils::get_stroke_width(layer, network_interface).unwrap_or(1.) as f64 * STROKE_WIDTH_PERCENT;
|
||||
|
||||
// Convert to linear if handes are on top of control points
|
||||
if let bezier_rs::BezierHandles::Cubic { handle_start, handle_end } = bezier.handles {
|
||||
if handle_start.abs_diff_eq(bezier.start(), f64::EPSILON * 100.) && handle_end.abs_diff_eq(bezier.end(), f64::EPSILON * 100.) {
|
||||
|
@ -1474,7 +1471,6 @@ impl ShapeState {
|
|||
t,
|
||||
bezier_point_to_viewport: screenspace,
|
||||
layer,
|
||||
stroke_width,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1129,7 +1129,7 @@ impl Fsm for PathToolFsmState {
|
|||
Self::Ready => {
|
||||
if let Some(closest_segment) = &tool_data.segment {
|
||||
let perp = closest_segment.calculate_perp(document);
|
||||
let point = closest_segment.closest_point_to_viewport();
|
||||
let point = closest_segment.closest_point(document.metadata());
|
||||
|
||||
// Draw an X on the segment
|
||||
if tool_data.delete_segment_pressed {
|
||||
|
@ -1400,7 +1400,7 @@ impl Fsm for PathToolFsmState {
|
|||
// If already hovering on a segment, then recalculate its closest point
|
||||
else if let Some(closest_segment) = &mut tool_data.segment {
|
||||
closest_segment.update_closest_point(document.metadata(), input.mouse.position);
|
||||
if closest_segment.too_far(input.mouse.position, SEGMENT_INSERTION_DISTANCE, document.metadata()) {
|
||||
if closest_segment.too_far(input.mouse.position, SEGMENT_INSERTION_DISTANCE) {
|
||||
tool_data.segment = None;
|
||||
}
|
||||
responses.add(OverlaysMessage::Draw)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue