From d8b5a687df5a9c130319a43b00f9f886ec92a194 Mon Sep 17 00:00:00 2001 From: indierusty Date: Tue, 5 Aug 2025 09:19:39 +0530 Subject: [PATCH 1/5] impl function to check bezpath insideness --- .../vector/algorithms/bezpath_algorithms.rs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs b/node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs index 1a7ac6c587..f6dd1b31d9 100644 --- a/node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs +++ b/node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs @@ -466,3 +466,70 @@ pub fn round_line_join(bezpath1: &BezPath, bezpath2: &BezPath, center: DVec2) -> compute_circular_subpath_details(left, arc_point, right, center, Some(angle)) } + +/// Returns `true` if the `bezpath1` is completely inside the `bezpath2`. +pub fn bezpath_is_inside_bezpath(bezpath1: &BezPath, bezpath2: &BezPath, accuracy: Option, minimum_separation: Option) -> bool { + // Eliminate any possibility of one being inside the other, if either of them is empty + if bezpath1.is_empty() || bezpath2.is_empty() { + return false; + } + + let inner_bbox = bezpath1.bounding_box(); + let outer_bbox = bezpath2.bounding_box(); + + // Eliminate bezpath1 if its bounding box is not completely inside the bezpath2's bounding box. + // Reasoning: + // If the inner bezpath bounding box is larger than the outer bezpath bounding box in any direction + // then the inner bezpath is intersecting with or outside the outer bezpath. + if !outer_bbox.contains_rect(inner_bbox) { + return false; + } + + // Eliminate bezpath1 if any of its anchor points are outside the bezpath2. + if !bezpath1.elements().iter().filter_map(|el| el.end_point()).all(|point| bezpath2.contains(point)) { + return false; + } + + // Eliminate this subpath if it intersects with the other subpath. + if !bezpath_intersections(bezpath1, bezpath2, accuracy, minimum_separation).is_empty() { + return false; + } + + // At this point: + // (1) This subpath's bounding box is inside the other subpath's bounding box, + // (2) Its anchors are inside the other subpath, and + // (3) It is not intersecting with the other subpath. + // Hence, this subpath is completely inside the given other subpath. + true +} + +#[cfg(test)] +mod tests { + // TODO: add more intersection tests + + use super::bezpath_is_inside_bezpath; + use kurbo::{BezPath, DEFAULT_ACCURACY, Line, Point, Rect, Shape}; + + #[test] + fn is_inside_subpath() { + let boundary_polygon = Rect::new(100., 100., 500., 500.).to_path(DEFAULT_ACCURACY); + + let mut curve_intersection = BezPath::new(); + curve_intersection.move_to(Point::new(189., 289.)); + curve_intersection.quad_to(Point::new(9., 286.), Point::new(45., 410.)); + assert!(!bezpath_is_inside_bezpath(&curve_intersection, &boundary_polygon, None, None)); + + let mut curve_outside = BezPath::new(); + curve_outside.move_to(Point::new(115., 37.)); + curve_outside.quad_to(Point::new(51.4, 91.8), Point::new(76.5, 242.)); + assert!(!bezpath_is_inside_bezpath(&curve_outside, &boundary_polygon, None, None)); + + let mut curve_inside = BezPath::new(); + curve_inside.move_to(Point::new(210.1, 133.5)); + curve_inside.curve_to(Point::new(150.2, 436.9), Point::new(436., 285.), Point::new(247.6, 240.7)); + assert!(bezpath_is_inside_bezpath(&curve_inside, &boundary_polygon, None, None)); + + let line_inside = Line::new(Point::new(101., 101.5), Point::new(150.2, 499.)).to_path(DEFAULT_ACCURACY); + assert!(bezpath_is_inside_bezpath(&line_inside, &boundary_polygon, None, None)); + } +} From 71d8307b24370b8d7b107a3c7fede322392da7d1 Mon Sep 17 00:00:00 2001 From: indierusty Date: Tue, 5 Aug 2025 09:48:22 +0530 Subject: [PATCH 2/5] refactor network interface wires to use kurbo --- .../node_graph/node_graph_message_handler.rs | 31 ++++------- .../utility_types/network_interface.rs | 11 ++-- .../portfolio/document/utility_types/wires.rs | 55 +++++++------------ 3 files changed, 35 insertions(+), 62 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index e02856bcac..2d0839182f 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -25,9 +25,10 @@ use glam::{DAffine2, DVec2, IVec2}; use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput}; use graph_craft::proto::GraphErrors; use graphene_std::math::math_ext::QuadExt; +use graphene_std::vector::algorithms::bezpath_algorithms::bezpath_is_inside_bezpath; use graphene_std::vector::misc::subpath_to_kurbo_bezpath; use graphene_std::*; -use kurbo::{Line, Point}; +use kurbo::{DEFAULT_ACCURACY, Line, Point, Shape}; use renderer::Quad; use std::cmp::Ordering; @@ -958,8 +959,7 @@ impl<'a> MessageHandler> for NodeG to_connector_is_layer, GraphWireStyle::Direct, ); - let mut path_string = String::new(); - let _ = vector_wire.subpath_to_svg(&mut path_string, DAffine2::IDENTITY); + let path_string = vector_wire.to_svg(); let wire_path = WirePath { path_string, data_type: self.wire_in_progress_type, @@ -1196,7 +1196,7 @@ impl<'a> MessageHandler> for NodeG .filter(|input| input.1.as_value().is_some()) .map(|input| input.0); if let Some(selected_node_input_connect_index) = selected_node_input_connect_index { - let Some(bounding_box) = network_interface.node_bounding_box(&selected_node_id, selection_network_path) else { + let Some(node_bbox) = network_interface.node_bounding_box(&selected_node_id, selection_network_path) else { log::error!("Could not get bounding box for node: {selected_node_id}"); return; }; @@ -1220,25 +1220,14 @@ impl<'a> MessageHandler> for NodeG log::debug!("preferences.graph_wire_style: {:?}", preferences.graph_wire_style); let (wire, is_stack) = network_interface.vector_wire_from_input(&input, preferences.graph_wire_style, selection_network_path)?; - let bbox_rect = kurbo::Rect::new(bounding_box[0].x, bounding_box[0].y, bounding_box[1].x, bounding_box[1].y); - - let p1 = DVec2::new(bbox_rect.x0, bbox_rect.y0); - let p2 = DVec2::new(bbox_rect.x1, bbox_rect.y0); - let p3 = DVec2::new(bbox_rect.x1, bbox_rect.y1); - let p4 = DVec2::new(bbox_rect.x0, bbox_rect.y1); - let ps = [p1, p2, p3, p4]; - - let inside = wire.is_inside_subpath(&Subpath::from_anchors_linear(ps, true), None, None); - - let wire = subpath_to_kurbo_bezpath(wire); + let node_bbox = kurbo::Rect::new(node_bbox[0].x, node_bbox[0].y, node_bbox[1].x, node_bbox[1].y); + let inside = bezpath_is_inside_bezpath(&wire, &node_bbox.to_path(DEFAULT_ACCURACY), None, None); let intersect = wire.segments().any(|segment| { - let rect = kurbo::Rect::new(bounding_box[0].x, bounding_box[0].y, bounding_box[1].x, bounding_box[1].y); - - let top_line = Line::new(Point::new(rect.x0, rect.y0), Point::new(rect.x1, rect.y0)); - let bottom_line = Line::new(Point::new(rect.x0, rect.y1), Point::new(rect.x1, rect.y1)); - let left_line = Line::new(Point::new(rect.x0, rect.y0), Point::new(rect.x0, rect.y1)); - let right_line = Line::new(Point::new(rect.x1, rect.y0), Point::new(rect.x1, rect.y1)); + let top_line = Line::new(Point::new(node_bbox.x0, node_bbox.y0), Point::new(node_bbox.x1, node_bbox.y0)); + let bottom_line = Line::new(Point::new(node_bbox.x0, node_bbox.y1), Point::new(node_bbox.x1, node_bbox.y1)); + let left_line = Line::new(Point::new(node_bbox.x0, node_bbox.y0), Point::new(node_bbox.x0, node_bbox.y1)); + let right_line = Line::new(Point::new(node_bbox.x1, node_bbox.y0), Point::new(node_bbox.x1, node_bbox.y1)); !segment.intersect_line(top_line).is_empty() || !segment.intersect_line(bottom_line).is_empty() diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface.rs b/editor/src/messages/portfolio/document/utility_types/network_interface.rs index 5d46f10401..5a9f9b49b9 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface.rs @@ -21,6 +21,7 @@ use graphene_std::vector::click_target::{ClickTarget, ClickTargetType}; use graphene_std::vector::{PointId, Vector, VectorModificationType}; use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypes; use interpreted_executor::node_registry::NODE_REGISTRY; +use kurbo::BezPath; use serde_json::{Value, json}; use std::collections::{HashMap, HashSet, VecDeque}; use std::hash::{DefaultHasher, Hash, Hasher}; @@ -2713,8 +2714,7 @@ impl NodeNetworkInterface { let thick = vertical_end && vertical_start; let vector_wire = build_vector_wire(output_position, input_position, vertical_start, vertical_end, graph_wire_style); - let mut path_string = String::new(); - let _ = vector_wire.subpath_to_svg(&mut path_string, DAffine2::IDENTITY); + let path_string = vector_wire.to_svg(); let data_type = FrontendGraphDataType::from_type(&self.input_type(&input, network_path).0); let wire_path_update = Some(WirePath { path_string, @@ -2731,14 +2731,14 @@ impl NodeNetworkInterface { } /// Returns the vector subpath and a boolean of whether the wire should be thick. - pub fn vector_wire_from_input(&mut self, input: &InputConnector, wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<(Subpath, bool)> { + pub fn vector_wire_from_input(&mut self, input: &InputConnector, wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<(BezPath, bool)> { let Some(input_position) = self.get_input_center(input, network_path) else { log::error!("Could not get dom rect for wire end: {:?}", input); return None; }; // An upstream output could not be found, so the wire does not exist, but it should still be loaded as as empty vector let Some(upstream_output) = self.upstream_output_connector(input, network_path) else { - return Some((Subpath::from_anchors(std::iter::empty(), false), false)); + return Some((BezPath::new(), false)); }; let Some(output_position) = self.get_output_center(&upstream_output, network_path) else { log::error!("Could not get dom rect for wire start: {:?}", upstream_output); @@ -2752,8 +2752,7 @@ impl NodeNetworkInterface { pub fn wire_path_from_input(&mut self, input: &InputConnector, graph_wire_style: GraphWireStyle, dashed: bool, network_path: &[NodeId]) -> Option { let (vector_wire, thick) = self.vector_wire_from_input(input, graph_wire_style, network_path)?; - let mut path_string = String::new(); - let _ = vector_wire.subpath_to_svg(&mut path_string, DAffine2::IDENTITY); + let path_string = vector_wire.to_svg(); let data_type = FrontendGraphDataType::from_type(&self.input_type(input, network_path).0); Some(WirePath { path_string, diff --git a/editor/src/messages/portfolio/document/utility_types/wires.rs b/editor/src/messages/portfolio/document/utility_types/wires.rs index 9f85c82670..e3f1d82874 100644 --- a/editor/src/messages/portfolio/document/utility_types/wires.rs +++ b/editor/src/messages/portfolio/document/utility_types/wires.rs @@ -1,8 +1,9 @@ use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType; use bezier_rs::{ManipulatorGroup, Subpath}; use glam::{DVec2, IVec2}; -use graphene_std::uuid::NodeId; use graphene_std::vector::PointId; +use graphene_std::{uuid::NodeId, vector::misc::dvec2_to_point}; +use kurbo::{BezPath, Point}; #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] pub struct WirePath { @@ -53,7 +54,7 @@ impl GraphWireStyle { } } -pub fn build_vector_wire(output_position: DVec2, input_position: DVec2, vertical_out: bool, vertical_in: bool, graph_wire_style: GraphWireStyle) -> Subpath { +pub fn build_vector_wire(output_position: DVec2, input_position: DVec2, vertical_out: bool, vertical_in: bool, graph_wire_style: GraphWireStyle) -> BezPath { let grid_spacing = 24.; match graph_wire_style { GraphWireStyle::Direct => { @@ -85,40 +86,24 @@ pub fn build_vector_wire(output_position: DVec2, input_position: DVec2, vertical let delta01 = DVec2::new((locations[1].x - locations[0].x) * smoothing, (locations[1].y - locations[0].y) * smoothing); let delta23 = DVec2::new((locations[3].x - locations[2].x) * smoothing, (locations[3].y - locations[2].y) * smoothing); - Subpath::new( - vec![ - ManipulatorGroup { - anchor: locations[0], - in_handle: None, - out_handle: None, - id: PointId::generate(), - }, - ManipulatorGroup { - anchor: locations[1], - in_handle: None, - out_handle: Some(locations[1] + delta01), - id: PointId::generate(), - }, - ManipulatorGroup { - anchor: locations[2], - in_handle: Some(locations[2] - delta23), - out_handle: None, - id: PointId::generate(), - }, - ManipulatorGroup { - anchor: locations[3], - in_handle: None, - out_handle: None, - id: PointId::generate(), - }, - ], - false, - ) - } - GraphWireStyle::GridAligned => { - let locations = straight_wire_paths(output_position, input_position, vertical_out, vertical_in); - straight_wire_subpath(locations) + let mut wire = BezPath::new(); + wire.move_to(dvec2_to_point(locations[0])); + wire.line_to(dvec2_to_point(locations[1])); + wire.curve_to(dvec2_to_point(locations[1] + delta01), dvec2_to_point(locations[2] - delta23), dvec2_to_point(locations[2])); + wire.line_to(dvec2_to_point(locations[3])); + wire } + GraphWireStyle::GridAligned => straight_wire_paths(output_position, input_position, vertical_out, vertical_in) + .iter() + .fold(BezPath::new(), |mut bezpath, point| { + let point = Point::new(point.x as f64, point.y as f64); + if bezpath.elements().is_empty() { + bezpath.move_to(point); + } else { + bezpath.line_to(point); + } + bezpath + }), } } From 251691b435f447a26d4be19469a3cb5d23a49a03 Mon Sep 17 00:00:00 2001 From: indierusty Date: Tue, 5 Aug 2025 09:57:51 +0530 Subject: [PATCH 3/5] refactor --- .../node_graph/node_graph_message_handler.rs | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 2d0839182f..11f9698f75 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -1220,20 +1220,12 @@ impl<'a> MessageHandler> for NodeG log::debug!("preferences.graph_wire_style: {:?}", preferences.graph_wire_style); let (wire, is_stack) = network_interface.vector_wire_from_input(&input, preferences.graph_wire_style, selection_network_path)?; - let node_bbox = kurbo::Rect::new(node_bbox[0].x, node_bbox[0].y, node_bbox[1].x, node_bbox[1].y); - let inside = bezpath_is_inside_bezpath(&wire, &node_bbox.to_path(DEFAULT_ACCURACY), None, None); - - let intersect = wire.segments().any(|segment| { - let top_line = Line::new(Point::new(node_bbox.x0, node_bbox.y0), Point::new(node_bbox.x1, node_bbox.y0)); - let bottom_line = Line::new(Point::new(node_bbox.x0, node_bbox.y1), Point::new(node_bbox.x1, node_bbox.y1)); - let left_line = Line::new(Point::new(node_bbox.x0, node_bbox.y0), Point::new(node_bbox.x0, node_bbox.y1)); - let right_line = Line::new(Point::new(node_bbox.x1, node_bbox.y0), Point::new(node_bbox.x1, node_bbox.y1)); - - !segment.intersect_line(top_line).is_empty() - || !segment.intersect_line(bottom_line).is_empty() - || !segment.intersect_line(left_line).is_empty() - || !segment.intersect_line(right_line).is_empty() - }); + let node_bbox = kurbo::Rect::new(node_bbox[0].x, node_bbox[0].y, node_bbox[1].x, node_bbox[1].y).to_path(DEFAULT_ACCURACY); + let inside = bezpath_is_inside_bezpath(&wire, &node_bbox, None, None); + + let intersect = wire + .segments() + .any(|segment| node_bbox.segments().filter_map(|segment| segment.as_line()).any(|line| !segment.intersect_line(line).is_empty())); (intersect || inside).then_some((input, is_stack)) }) From fd8cbc2fe8d1142afc8c1e2fac084889a6c92c49 Mon Sep 17 00:00:00 2001 From: indierusty Date: Tue, 5 Aug 2025 10:41:19 +0530 Subject: [PATCH 4/5] refactor --- .../node_graph/node_graph_message_handler.rs | 4 +- .../portfolio/document/utility_types/wires.rs | 81 +++++-------------- node-graph/gcore/src/vector/misc.rs | 8 +- 3 files changed, 21 insertions(+), 72 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 11f9698f75..234f04c360 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -20,15 +20,13 @@ use crate::messages::tool::common_functionality::graph_modification_utils::{self use crate::messages::tool::common_functionality::utility_functions::make_path_editable_is_allowed; use crate::messages::tool::tool_messages::tool_prelude::{Key, MouseMotion}; use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; -use bezier_rs::Subpath; use glam::{DAffine2, DVec2, IVec2}; use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput}; use graph_craft::proto::GraphErrors; use graphene_std::math::math_ext::QuadExt; use graphene_std::vector::algorithms::bezpath_algorithms::bezpath_is_inside_bezpath; -use graphene_std::vector::misc::subpath_to_kurbo_bezpath; use graphene_std::*; -use kurbo::{DEFAULT_ACCURACY, Line, Point, Shape}; +use kurbo::{DEFAULT_ACCURACY, Shape}; use renderer::Quad; use std::cmp::Ordering; diff --git a/editor/src/messages/portfolio/document/utility_types/wires.rs b/editor/src/messages/portfolio/document/utility_types/wires.rs index e3f1d82874..858973f67f 100644 --- a/editor/src/messages/portfolio/document/utility_types/wires.rs +++ b/editor/src/messages/portfolio/document/utility_types/wires.rs @@ -1,9 +1,7 @@ use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType; -use bezier_rs::{ManipulatorGroup, Subpath}; use glam::{DVec2, IVec2}; -use graphene_std::vector::PointId; use graphene_std::{uuid::NodeId, vector::misc::dvec2_to_point}; -use kurbo::{BezPath, Point}; +use kurbo::{BezPath, DEFAULT_ACCURACY, Line, Point, Shape}; #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] pub struct WirePath { @@ -93,21 +91,14 @@ pub fn build_vector_wire(output_position: DVec2, input_position: DVec2, vertical wire.line_to(dvec2_to_point(locations[3])); wire } - GraphWireStyle::GridAligned => straight_wire_paths(output_position, input_position, vertical_out, vertical_in) - .iter() - .fold(BezPath::new(), |mut bezpath, point| { - let point = Point::new(point.x as f64, point.y as f64); - if bezpath.elements().is_empty() { - bezpath.move_to(point); - } else { - bezpath.line_to(point); - } - bezpath - }), + GraphWireStyle::GridAligned => { + let locations = straight_wire_path(output_position, input_position, vertical_out, vertical_in); + straight_wire_to_bezpath(locations) + } } } -fn straight_wire_paths(output_position: DVec2, input_position: DVec2, vertical_out: bool, vertical_in: bool) -> Vec { +fn straight_wire_path(output_position: DVec2, input_position: DVec2, vertical_out: bool, vertical_in: bool) -> Vec { let grid_spacing = 24; let line_width = 2; @@ -431,40 +422,24 @@ fn straight_wire_paths(output_position: DVec2, input_position: DVec2, vertical_o vec![IVec2::new(x1, y1), IVec2::new(x20, y1), IVec2::new(x20, y3), IVec2::new(x4, y3)] } -fn straight_wire_subpath(locations: Vec) -> Subpath { +fn straight_wire_to_bezpath(locations: Vec) -> BezPath { if locations.is_empty() { - return Subpath::new(Vec::new(), false); + return BezPath::new(); } + let to_point = |location: IVec2| Point::new(location.x as f64, location.y as f64); + if locations.len() == 2 { - return Subpath::new( - vec![ - ManipulatorGroup { - anchor: locations[0].into(), - in_handle: None, - out_handle: None, - id: PointId::generate(), - }, - ManipulatorGroup { - anchor: locations[1].into(), - in_handle: None, - out_handle: None, - id: PointId::generate(), - }, - ], - false, - ); + let p1 = to_point(locations[0]); + let p2 = to_point(locations[1]); + Line::new(p1, p2).to_path(DEFAULT_ACCURACY); } let corner_radius = 10; // Create path with rounded corners - let mut path = vec![ManipulatorGroup { - anchor: locations[0].into(), - in_handle: None, - out_handle: None, - id: PointId::generate(), - }]; + let mut path = BezPath::new(); + path.move_to(to_point(locations[0])); for i in 1..(locations.len() - 1) { let prev = locations[i - 1]; @@ -548,27 +523,9 @@ fn straight_wire_subpath(locations: Vec) -> Subpath { }, ); - path.extend(vec![ - ManipulatorGroup { - anchor: corner_start.into(), - in_handle: None, - out_handle: Some(corner_start_mid.into()), - id: PointId::generate(), - }, - ManipulatorGroup { - anchor: corner_end.into(), - in_handle: Some(corner_end_mid.into()), - out_handle: None, - id: PointId::generate(), - }, - ]) + path.line_to(to_point(corner_start)); + path.curve_to(to_point(corner_start_mid), to_point(corner_end_mid), to_point(corner_end)); } - - path.push(ManipulatorGroup { - anchor: (*locations.last().unwrap()).into(), - in_handle: None, - out_handle: None, - id: PointId::generate(), - }); - Subpath::new(path, false) + path.move_to(to_point(*locations.last().unwrap())); + path } diff --git a/node-graph/gcore/src/vector/misc.rs b/node-graph/gcore/src/vector/misc.rs index b87e21a947..a4ff0664cc 100644 --- a/node-graph/gcore/src/vector/misc.rs +++ b/node-graph/gcore/src/vector/misc.rs @@ -1,7 +1,7 @@ use super::PointId; use super::algorithms::offset_subpath::MAX_ABSOLUTE_DIFFERENCE; use crate::vector::{SegmentId, Vector}; -use bezier_rs::{BezierHandles, ManipulatorGroup, Subpath}; +use bezier_rs::{BezierHandles, ManipulatorGroup}; use dyn_any::DynAny; use glam::DVec2; use kurbo::{BezPath, CubicBez, Line, ParamCurve, PathSeg, Point, QuadBez}; @@ -136,12 +136,6 @@ pub fn handles_to_segment(start: DVec2, handles: BezierHandles, end: DVec2) -> P } } -pub fn subpath_to_kurbo_bezpath(subpath: Subpath) -> BezPath { - let manipulator_groups = subpath.manipulator_groups(); - let closed = subpath.closed(); - bezpath_from_manipulator_groups(manipulator_groups, closed) -} - pub fn bezpath_from_manipulator_groups(manipulator_groups: &[ManipulatorGroup], closed: bool) -> BezPath { let mut bezpath = kurbo::BezPath::new(); let mut out_handle; From 8b4cb293136ad63ef234fbea726a75bfc4b5f289 Mon Sep 17 00:00:00 2001 From: indierusty Date: Wed, 6 Aug 2025 14:24:11 +0530 Subject: [PATCH 5/5] fix adding MoveTo instead of LineTo to the grid aligned wire bezpath --- editor/src/messages/portfolio/document/utility_types/wires.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/messages/portfolio/document/utility_types/wires.rs b/editor/src/messages/portfolio/document/utility_types/wires.rs index 858973f67f..ad6ab32843 100644 --- a/editor/src/messages/portfolio/document/utility_types/wires.rs +++ b/editor/src/messages/portfolio/document/utility_types/wires.rs @@ -526,6 +526,6 @@ fn straight_wire_to_bezpath(locations: Vec) -> BezPath { path.line_to(to_point(corner_start)); path.curve_to(to_point(corner_start_mid), to_point(corner_end_mid), to_point(corner_end)); } - path.move_to(to_point(*locations.last().unwrap())); + path.line_to(to_point(*locations.last().unwrap())); path }