Skip to content

Commit f6e592d

Browse files
authored
New nodes: 'Point Inside Shape' and 'Close Path' (#2673)
* add point inside shape,close path,and disabled node to layer conversion * removed the usage one_instance * code review
1 parent 3496e22 commit f6e592d

File tree

3 files changed

+64
-6
lines changed

3 files changed

+64
-6
lines changed

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,11 +1214,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
12141214
if is_stack_wire(&wire) { stack_wires.push(wire) } else { node_wires.push(wire) }
12151215
}
12161216

1217-
// Auto convert node to layer when inserting on a single stack wire
1218-
if stack_wires.len() == 1 && node_wires.is_empty() {
1219-
network_interface.set_to_node_or_layer(&selected_node_id, selection_network_path, true)
1220-
}
1221-
12221217
let overlapping_wire = if network_interface.is_layer(&selected_node_id, selection_network_path) {
12231218
if stack_wires.len() == 1 {
12241219
stack_wires.first()

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

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod attributes;
22
mod indexed;
33
mod modification;
44

5-
use super::misc::point_to_dvec2;
5+
use super::misc::{dvec2_to_point, point_to_dvec2};
66
use super::style::{PathStyle, Stroke};
77
use crate::instances::Instances;
88
use crate::{AlphaBlending, Color, GraphicGroupTable};
@@ -12,6 +12,7 @@ use core::borrow::Borrow;
1212
use dyn_any::DynAny;
1313
use glam::{DAffine2, DVec2};
1414
pub use indexed::VectorDataIndex;
15+
use kurbo::{Affine, Shape};
1516
pub use modification::*;
1617
use std::collections::HashMap;
1718

@@ -193,6 +194,23 @@ impl VectorData {
193194
vector_data
194195
}
195196

197+
pub fn close_subpaths(&mut self) {
198+
let segments_to_add: Vec<_> = self
199+
.stroke_bezier_paths()
200+
.filter(|subpath| !subpath.closed)
201+
.filter_map(|subpath| {
202+
let (first, last) = subpath.manipulator_groups().first().zip(subpath.manipulator_groups().last())?;
203+
let (start, end) = self.point_domain.resolve_id(first.id).zip(self.point_domain.resolve_id(last.id))?;
204+
Some((start, end))
205+
})
206+
.collect();
207+
208+
for (start, end) in segments_to_add {
209+
let segment_id = self.segment_domain.next_id().next_id();
210+
self.segment_domain.push(segment_id, start, end, bezier_rs::BezierHandles::Linear, StrokeId::ZERO);
211+
}
212+
}
213+
196214
/// Compute the bounding boxes of the subpaths without any transform
197215
pub fn bounding_box(&self) -> Option<[DVec2; 2]> {
198216
self.bounding_box_with_transform(DAffine2::IDENTITY)
@@ -316,6 +334,34 @@ impl VectorData {
316334
self.point_domain.resolve_id(point).map_or(0, |point| self.segment_domain.connected_count(point))
317335
}
318336

337+
pub fn check_point_inside_shape(&self, vector_data_transform: DAffine2, point: DVec2) -> bool {
338+
let bez_paths: Vec<_> = self
339+
.stroke_bezpath_iter()
340+
.map(|mut bezpath| {
341+
// TODO: apply transform to points instead of modifying the paths
342+
bezpath.apply_affine(Affine::new(vector_data_transform.to_cols_array()));
343+
bezpath.close_path();
344+
let bbox = bezpath.bounding_box();
345+
(bezpath, bbox)
346+
})
347+
.collect();
348+
349+
// Check against all paths the point is contained in to compute the correct winding number
350+
let mut number = 0;
351+
352+
for (shape, bbox) in bez_paths {
353+
if bbox.x0 > point.x || bbox.y0 > point.y || bbox.x1 < point.x || bbox.y1 < point.y {
354+
continue;
355+
}
356+
357+
let winding = shape.winding(dvec2_to_point(point));
358+
number += winding;
359+
}
360+
361+
// Non-zero fill rule
362+
number != 0
363+
}
364+
319365
/// Points that can be extended from.
320366
///
321367
/// This is usually only points with exactly one connection unless vector meshes are enabled.

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,23 @@ fn bevel(_: impl Ctx, source: VectorDataTable, #[default(10.)] distance: Length)
17151715
result
17161716
}
17171717

1718+
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
1719+
fn close_path(_: impl Ctx, source: VectorDataTable) -> VectorDataTable {
1720+
let mut new_table = VectorDataTable::empty();
1721+
1722+
for mut source_instance in source.instance_iter() {
1723+
source_instance.instance.close_subpaths();
1724+
new_table.push(source_instance);
1725+
}
1726+
1727+
new_table
1728+
}
1729+
1730+
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
1731+
fn point_inside(_: impl Ctx, source: VectorDataTable, point: DVec2) -> bool {
1732+
source.instance_iter().any(|instance| instance.instance.check_point_inside_shape(instance.transform, point))
1733+
}
1734+
17181735
#[node_macro::node(name("Merge by Distance"), category("Vector"), path(graphene_core::vector))]
17191736
fn merge_by_distance(_: impl Ctx, source: VectorDataTable, #[default(10.)] distance: Length) -> VectorDataTable {
17201737
let source_transform = source.transform();

0 commit comments

Comments
 (0)