Skip to content

Commit 71ddae9

Browse files
0SlowPoke0Keavon
andauthored
Fix Path tool multi-point handle scaling behavior and double-click smooth/sharp conversion on rectangles (#2765)
* fixed double-click on anchor connected to linear segments * fix when scaling when anchor * Nit --------- Co-authored-by: Keavon Chambers <[email protected]>
1 parent 59e3483 commit 71ddae9

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

editor/src/messages/portfolio/document/utility_types/transformation.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ use crate::messages::tool::common_functionality::shape_editor::ShapeState;
99
use crate::messages::tool::utility_types::ToolType;
1010
use glam::{DAffine2, DMat2, DVec2};
1111
use graphene_std::renderer::Quad;
12-
use graphene_std::vector::VectorModificationType;
13-
use graphene_std::vector::{HandleExt, ManipulatorPointId};
14-
use graphene_std::vector::{HandleId, PointId};
12+
use graphene_std::vector::{HandleExt, HandleId, ManipulatorPointId, PointId, VectorModificationType};
1513
use std::collections::{HashMap, VecDeque};
1614
use std::f64::consts::PI;
1715

@@ -616,7 +614,7 @@ impl<'a> Selected<'a> {
616614
responses.add(GraphOperationMessage::Vector { layer, modification_type });
617615
}
618616

619-
if transform_operation.is_some_and(|transform_operation| matches!(transform_operation, TransformOperation::Scaling(_))) && initial_points.anchors.len() > 1 {
617+
if transform_operation.is_some_and(|transform_operation| matches!(transform_operation, TransformOperation::Scaling(_))) && (initial_points.anchors.len() == 2) {
620618
return;
621619
}
622620

editor/src/messages/tool/common_functionality/shape_editor.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,9 @@ impl ShapeState {
899899
let non_zero_handles = handles.iter().filter(|handle| handle.length(vector_data) > 1e-6).count();
900900
let handle_segments = handles.iter().map(|handles| handles.segment).collect::<Vec<_>>();
901901

902+
// Check if the anchor is connected to linear segments and has no handles
903+
let linear_segments = vector_data.connected_linear_segments(point_id) != 0;
904+
902905
// Grab the next and previous manipulator groups by simply looking at the next / previous index
903906
let points = handles.iter().map(|handle| vector_data.other_point(handle.segment, point_id));
904907
let anchor_positions = points
@@ -940,7 +943,7 @@ impl ShapeState {
940943
handle_direction *= -1.;
941944
}
942945

943-
if non_zero_handles != 0 {
946+
if non_zero_handles != 0 && !linear_segments {
944947
let [a, b] = handles.as_slice() else { return };
945948
let (non_zero_handle, zero_handle) = if a.length(vector_data) > 1e-6 { (a, b) } else { (b, a) };
946949
let Some(direction) = non_zero_handle
@@ -1772,10 +1775,13 @@ impl ShapeState {
17721775
.filter(|&handle| anchor.abs_diff_eq(handle, 1e-5))
17731776
.count();
17741777

1778+
// Check if the anchor is connected to linear segments.
1779+
let one_or_more_segment_linear = vector_data.connected_linear_segments(id) != 0;
1780+
17751781
// Check by comparing the handle positions to the anchor if this manipulator group is a point
17761782
for point in self.selected_points() {
17771783
let Some(point_id) = point.as_anchor() else { continue };
1778-
if positions != 0 {
1784+
if positions != 0 || one_or_more_segment_linear {
17791785
self.convert_manipulator_handles_to_colinear(&vector_data, point_id, responses, layer);
17801786
} else {
17811787
for handle in vector_data.all_connected(point_id) {

node-graph/gcore/src/vector/vector_data.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::transform::Transform;
1111
use crate::vector::click_target::{ClickTargetType, FreePoint};
1212
use crate::{AlphaBlending, Color, GraphicGroupTable};
1313
pub use attributes::*;
14-
use bezier_rs::ManipulatorGroup;
14+
use bezier_rs::{BezierHandles, ManipulatorGroup};
1515
use core::borrow::Borrow;
1616
use core::hash::Hash;
1717
use dyn_any::DynAny;
@@ -334,6 +334,13 @@ impl VectorData {
334334
index.flat_map(|index| self.segment_domain.connected_points(index).map(|index| self.point_domain.ids()[index]))
335335
}
336336

337+
/// Returns the number of linear segments connected to the given point.
338+
pub fn connected_linear_segments(&self, point_id: PointId) -> usize {
339+
self.segment_bezier_iter()
340+
.filter(|(_, bez, start, end)| ((*start == point_id || *end == point_id) && matches!(bez.handles, BezierHandles::Linear)))
341+
.count()
342+
}
343+
337344
/// Get an array slice of all segment IDs.
338345
pub fn segment_ids(&self) -> &[SegmentId] {
339346
self.segment_domain.ids()

0 commit comments

Comments
 (0)