Extract gpath_bool from mod gstd::ops path_bool-related nodes (#2762)

* cargo shear

* Extract `gpath_bool` from `mod gstd::ops` path_bool-related nodes
This commit is contained in:
Firestar99 2025-06-27 15:12:08 +02:00 committed by GitHub
parent 9cf8d2cd05
commit ffc6c5532b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 128 additions and 107 deletions

30
Cargo.lock generated
View file

@ -2132,6 +2132,7 @@ dependencies = [
"graph-craft", "graph-craft",
"graphene-application-io", "graphene-application-io",
"graphene-core", "graphene-core",
"graphene-path-bool",
"iai-callgrind", "iai-callgrind",
"js-sys", "js-sys",
"log", "log",
@ -2214,12 +2215,26 @@ dependencies = [
"wgpu", "wgpu",
] ]
[[package]]
name = "graphene-path-bool"
version = "0.1.0"
dependencies = [
"bezier-rs",
"dyn-any",
"glam",
"graphene-core",
"log",
"node-macro",
"path-bool",
"serde",
"specta",
]
[[package]] [[package]]
name = "graphene-std" name = "graphene-std"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bezier-rs",
"bytemuck", "bytemuck",
"dyn-any", "dyn-any",
"fastnoise-lite", "fastnoise-lite",
@ -2228,16 +2243,15 @@ dependencies = [
"graph-craft", "graph-craft",
"graphene-application-io", "graphene-application-io",
"graphene-core", "graphene-core",
"graphene-path-bool",
"image", "image",
"log", "log",
"ndarray", "ndarray",
"node-macro", "node-macro",
"path-bool",
"rand 0.9.0", "rand 0.9.0",
"rand_chacha 0.9.0", "rand_chacha 0.9.0",
"reqwest", "reqwest",
"tokio", "tokio",
"usvg",
"vello", "vello",
"wasm-bindgen", "wasm-bindgen",
"wasm-bindgen-futures", "wasm-bindgen-futures",
@ -2313,7 +2327,6 @@ dependencies = [
name = "graphite-wasm" name = "graphite-wasm"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"glam",
"graph-craft", "graph-craft",
"graphene-std", "graphene-std",
"graphite-editor", "graphite-editor",
@ -2948,6 +2961,7 @@ dependencies = [
"glam", "glam",
"graph-craft", "graph-craft",
"graphene-core", "graphene-core",
"graphene-path-bool",
"graphene-std", "graphene-std",
"log", "log",
"once_cell", "once_cell",
@ -4481,17 +4495,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
name = "preprocessor" name = "preprocessor"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"base64 0.22.1",
"dyn-any",
"futures",
"glam",
"graph-craft", "graph-craft",
"graphene-std", "graphene-std",
"interpreted-executor", "interpreted-executor",
"log",
"serde",
"serde_json",
"tokio",
] ]
[[package]] [[package]]

View file

@ -7,6 +7,7 @@ members = [
"node-graph/gapplication-io", "node-graph/gapplication-io",
"node-graph/gcore", "node-graph/gcore",
"node-graph/gstd", "node-graph/gstd",
"node-graph/gpath-bool",
"node-graph/graph-craft", "node-graph/graph-craft",
"node-graph/graphene-cli", "node-graph/graphene-cli",
"node-graph/interpreted-executor", "node-graph/interpreted-executor",
@ -23,6 +24,7 @@ default-members = [
"frontend/wasm", "frontend/wasm",
"node-graph/gcore", "node-graph/gcore",
"node-graph/gstd", "node-graph/gstd",
"node-graph/gpath-bool",
"node-graph/graph-craft", "node-graph/graph-craft",
"node-graph/graphene-cli", "node-graph/graphene-cli",
"node-graph/interpreted-executor", "node-graph/interpreted-executor",
@ -39,6 +41,7 @@ math-parser = { path = "libraries/math-parser" }
path-bool = { path = "libraries/path-bool" } path-bool = { path = "libraries/path-bool" }
graphene-application-io = { path = "node-graph/gapplication-io" } graphene-application-io = { path = "node-graph/gapplication-io" }
graphene-core = { path = "node-graph/gcore" } graphene-core = { path = "node-graph/gcore" }
graphene-path-bool = { path = "node-graph/gpath-bool" }
graph-craft = { path = "node-graph/graph-craft" } graph-craft = { path = "node-graph/graph-craft" }
graphene-std = { path = "node-graph/gstd" } graphene-std = { path = "node-graph/gstd" }
interpreted-executor = { path = "node-graph/interpreted-executor" } interpreted-executor = { path = "node-graph/interpreted-executor" }

View file

@ -30,11 +30,12 @@ use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput, NodeNetwork, OldNodeNetwork}; use graph_craft::document::{NodeId, NodeInput, NodeNetwork, OldNodeNetwork};
use graphene_std::math::quad::Quad; use graphene_std::math::quad::Quad;
use graphene_std::path_bool::{boolean_intersect, path_bool_lib};
use graphene_std::raster::BlendMode; use graphene_std::raster::BlendMode;
use graphene_std::raster_types::{Raster, RasterDataTable}; use graphene_std::raster_types::{Raster, RasterDataTable};
use graphene_std::vector::PointId;
use graphene_std::vector::click_target::{ClickTarget, ClickTargetType}; use graphene_std::vector::click_target::{ClickTarget, ClickTargetType};
use graphene_std::vector::style::ViewMode; use graphene_std::vector::style::ViewMode;
use graphene_std::vector::{PointId, path_bool_lib};
use std::time::Duration; use std::time::Duration;
pub struct DocumentMessageData<'a> { pub struct DocumentMessageData<'a> {
@ -2962,7 +2963,7 @@ impl<'a> ClickXRayIter<'a> {
// We do this on this using the target area to reduce computation (as the target area is usually very simple). // We do this on this using the target area to reduce computation (as the target area is usually very simple).
if clip && intersects { if clip && intersects {
let clip_path = click_targets_to_path_lib_segments(click_targets.iter().flat_map(|x| x.iter()), transform); let clip_path = click_targets_to_path_lib_segments(click_targets.iter().flat_map(|x| x.iter()), transform);
let subtracted = graphene_std::vector::boolean_intersect(path, clip_path).into_iter().flatten().collect::<Vec<_>>(); let subtracted = boolean_intersect(path, clip_path).into_iter().flatten().collect::<Vec<_>>();
if subtracted.is_empty() { if subtracted.is_empty() {
use_children = false; use_children = false;
} else { } else {

View file

@ -79,7 +79,7 @@ pub enum GraphOperationMessage {
}, },
NewBooleanOperationLayer { NewBooleanOperationLayer {
id: NodeId, id: NodeId,
operation: graphene_std::vector::misc::BooleanOperation, operation: graphene_std::path_bool::BooleanOperation,
parent: LayerNodeIdentifier, parent: LayerNodeIdentifier,
insert_index: usize, insert_index: usize,
}, },

View file

@ -10,8 +10,8 @@ use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{NodeId, NodeInput};
use graphene_std::Color; use graphene_std::Color;
use graphene_std::renderer::Quad; use graphene_std::renderer::Quad;
use graphene_std::renderer::convert_usvg_path::convert_usvg_path;
use graphene_std::text::{Font, TypesettingConfig}; use graphene_std::text::{Font, TypesettingConfig};
use graphene_std::vector::convert_usvg_path;
use graphene_std::vector::style::{Fill, Gradient, GradientStops, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin}; use graphene_std::vector::style::{Fill, Gradient, GradientStops, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -134,7 +134,7 @@ impl<'a> ModifyInputsContext<'a> {
LayerNodeIdentifier::new(new_id, self.network_interface, &[]) LayerNodeIdentifier::new(new_id, self.network_interface, &[])
} }
pub fn insert_boolean_data(&mut self, operation: graphene_std::vector::misc::BooleanOperation, layer: LayerNodeIdentifier) { pub fn insert_boolean_data(&mut self, operation: graphene_std::path_bool::BooleanOperation, layer: LayerNodeIdentifier) {
let boolean = resolve_document_node_type("Boolean Operation").expect("Boolean node does not exist").node_template_input_override([ let boolean = resolve_document_node_type("Boolean Operation").expect("Boolean node does not exist").node_template_input_override([
Some(NodeInput::value(TaggedValue::GraphicGroup(graphene_std::GraphicGroupTable::default()), true)), Some(NodeInput::value(TaggedValue::GraphicGroup(graphene_std::GraphicGroupTable::default()), true)),
Some(NodeInput::value(TaggedValue::BooleanOperation(operation), false)), Some(NodeInput::value(TaggedValue::BooleanOperation(operation), false)),

View file

@ -1734,7 +1734,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
nodes: vec![ nodes: vec![
DocumentNode { DocumentNode {
inputs: vec![NodeInput::network(concrete!(VectorDataTable), 0), NodeInput::network(concrete!(vector::style::Fill), 1)], inputs: vec![NodeInput::network(concrete!(VectorDataTable), 0), NodeInput::network(concrete!(vector::style::Fill), 1)],
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::vector::BooleanOperationNode")), implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_path_bool::BooleanOperationNode")),
manual_composition: Some(generic!(T)), manual_composition: Some(generic!(T)),
..Default::default() ..Default::default()
}, },
@ -1765,7 +1765,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}), }),
inputs: vec![ inputs: vec![
NodeInput::value(TaggedValue::GraphicGroup(GraphicGroupTable::default()), true), NodeInput::value(TaggedValue::GraphicGroup(GraphicGroupTable::default()), true),
NodeInput::value(TaggedValue::BooleanOperation(vector::misc::BooleanOperation::Union), false), NodeInput::value(TaggedValue::BooleanOperation(path_bool::BooleanOperation::Union), false),
], ],
..Default::default() ..Default::default()
}, },

View file

@ -13,6 +13,7 @@ use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput}; use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
use graphene_std::animation::RealTimeMode; use graphene_std::animation::RealTimeMode;
use graphene_std::ops::XY; use graphene_std::ops::XY;
use graphene_std::path_bool::BooleanOperation;
use graphene_std::raster::curve::Curve; use graphene_std::raster::curve::Curve;
use graphene_std::raster::{ use graphene_std::raster::{
BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, LuminanceCalculation, NoiseType, RedGreenBlue, RedGreenBlueAlpha, RelativeAbsolute, BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, LuminanceCalculation, NoiseType, RedGreenBlue, RedGreenBlueAlpha, RelativeAbsolute,
@ -22,8 +23,8 @@ use graphene_std::raster_types::{CPU, GPU, RasterDataTable};
use graphene_std::text::Font; use graphene_std::text::Font;
use graphene_std::transform::{Footprint, ReferencePoint}; use graphene_std::transform::{Footprint, ReferencePoint};
use graphene_std::vector::VectorDataTable; use graphene_std::vector::VectorDataTable;
use graphene_std::vector::misc::GridType;
use graphene_std::vector::misc::{ArcType, MergeByDistanceAlgorithm}; use graphene_std::vector::misc::{ArcType, MergeByDistanceAlgorithm};
use graphene_std::vector::misc::{BooleanOperation, GridType};
use graphene_std::vector::misc::{CentroidType, PointSpacingType}; use graphene_std::vector::misc::{CentroidType, PointSpacingType};
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops}; use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops};
use graphene_std::vector::style::{GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin}; use graphene_std::vector::style::{GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};

View file

@ -693,5 +693,5 @@ impl PTZ {
#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum GroupFolderType { pub enum GroupFolderType {
Layer, Layer,
BooleanOperation(graphene_std::vector::misc::BooleanOperation), BooleanOperation(graphene_std::path_bool::BooleanOperation),
} }

View file

@ -70,6 +70,7 @@ const REPLACEMENTS: &[(&str, &str)] = &[
("graphene_core::transform::CullNode", "graphene_core::ops::IdentityNode"), ("graphene_core::transform::CullNode", "graphene_core::ops::IdentityNode"),
("graphene_std::raster::MaskImageNode", "graphene_std::raster::MaskNode"), ("graphene_std::raster::MaskImageNode", "graphene_std::raster::MaskNode"),
("graphene_core::vector::FlattenVectorElementsNode", "graphene_core::vector::FlattenPathNode"), ("graphene_core::vector::FlattenVectorElementsNode", "graphene_core::vector::FlattenPathNode"),
("graphene_std::vector::BooleanOperationNode", "graphene_path_bool::BooleanOperationNode"),
]; ];
pub fn document_migration_string_preprocessing(document_serialized_content: String) -> String { pub fn document_migration_string_preprocessing(document_serialized_content: String) -> String {

View file

@ -4,7 +4,7 @@ use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType}; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graphene_std::vector::misc::BooleanOperation; use graphene_std::path_bool::BooleanOperation;
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct MenuBarMessageHandler { pub struct MenuBarMessageHandler {

View file

@ -22,10 +22,10 @@ use crate::messages::tool::common_functionality::utility_functions::{resize_boun
use bezier_rs::Subpath; use bezier_rs::Subpath;
use glam::DMat2; use glam::DMat2;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_std::path_bool::BooleanOperation;
use graphene_std::renderer::Quad; use graphene_std::renderer::Quad;
use graphene_std::renderer::Rect; use graphene_std::renderer::Rect;
use graphene_std::transform::ReferencePoint; use graphene_std::transform::ReferencePoint;
use graphene_std::vector::misc::BooleanOperation;
use std::fmt; use std::fmt;
#[derive(Default)] #[derive(Default)]

View file

@ -35,7 +35,6 @@ wasm-bindgen = { workspace = true }
serde-wasm-bindgen = { workspace = true } serde-wasm-bindgen = { workspace = true }
js-sys = { workspace = true } js-sys = { workspace = true }
wasm-bindgen-futures = { workspace = true } wasm-bindgen-futures = { workspace = true }
glam = { workspace = true }
math-parser = { workspace = true } math-parser = { workspace = true }
wgpu = { workspace = true } wgpu = { workspace = true }
web-sys = { workspace = true } web-sys = { workspace = true }

View file

@ -1,3 +1,5 @@
pub mod convert_usvg_path;
use crate::instances::Instance; use crate::instances::Instance;
pub use crate::math::quad::Quad; pub use crate::math::quad::Quad;
pub use crate::math::rect::Rect; pub use crate::math::rect::Rect;

View file

@ -0,0 +1,47 @@
use crate::vector::PointId;
use bezier_rs::{ManipulatorGroup, Subpath};
use glam::DVec2;
pub fn convert_usvg_path(path: &usvg::Path) -> Vec<Subpath<PointId>> {
let mut subpaths = Vec::new();
let mut groups = Vec::new();
let mut points = path.data().points().iter();
let to_vec = |p: &usvg::tiny_skia_path::Point| DVec2::new(p.x as f64, p.y as f64);
for verb in path.data().verbs() {
match verb {
usvg::tiny_skia_path::PathVerb::Move => {
subpaths.push(Subpath::new(std::mem::take(&mut groups), false));
let Some(start) = points.next().map(to_vec) else { continue };
groups.push(ManipulatorGroup::new(start, Some(start), Some(start)));
}
usvg::tiny_skia_path::PathVerb::Line => {
let Some(end) = points.next().map(to_vec) else { continue };
groups.push(ManipulatorGroup::new(end, Some(end), Some(end)));
}
usvg::tiny_skia_path::PathVerb::Quad => {
let Some(handle) = points.next().map(to_vec) else { continue };
let Some(end) = points.next().map(to_vec) else { continue };
if let Some(last) = groups.last_mut() {
last.out_handle = Some(last.anchor + (2. / 3.) * (handle - last.anchor));
}
groups.push(ManipulatorGroup::new(end, Some(end + (2. / 3.) * (handle - end)), Some(end)));
}
usvg::tiny_skia_path::PathVerb::Cubic => {
let Some(first_handle) = points.next().map(to_vec) else { continue };
let Some(second_handle) = points.next().map(to_vec) else { continue };
let Some(end) = points.next().map(to_vec) else { continue };
if let Some(last) = groups.last_mut() {
last.out_handle = Some(first_handle);
}
groups.push(ManipulatorGroup::new(end, Some(second_handle), Some(end)));
}
usvg::tiny_skia_path::PathVerb::Close => {
subpaths.push(Subpath::new(std::mem::take(&mut groups), true));
}
}
}
subpaths.push(Subpath::new(groups, false));
subpaths
}

View file

@ -13,22 +13,6 @@ pub enum CentroidType {
Length, Length,
} }
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
#[widget(Radio)]
pub enum BooleanOperation {
#[default]
#[icon("BooleanUnion")]
Union,
#[icon("BooleanSubtractFront")]
SubtractFront,
#[icon("BooleanSubtractBack")]
SubtractBack,
#[icon("BooleanIntersect")]
Intersect,
#[icon("BooleanDifference")]
Difference,
}
pub trait AsU64 { pub trait AsU64 {
fn as_u64(&self) -> u64; fn as_u64(&self) -> u64;
} }

View file

@ -0,0 +1,19 @@
[package]
name = "graphene-path-bool"
version = "0.1.0"
edition = "2024"
description = "graphene path bool nodes"
authors = ["Graphite Authors <contact@graphite.rs>"]
license = "MIT OR Apache-2.0"
[dependencies]
# Local dependencies
dyn-any = { workspace = true }
bezier-rs = { workspace = true }
graphene-core = { workspace = true }
node-macro = { workspace = true }
glam = { workspace = true }
specta = { workspace = true }
log = { workspace = true }
path-bool = { workspace = true }
serde = { workspace = true }

View file

@ -1,10 +1,10 @@
use bezier_rs::{ManipulatorGroup, Subpath}; use bezier_rs::{ManipulatorGroup, Subpath};
use dyn_any::DynAny;
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use graphene_core::instances::{Instance, InstanceRef}; use graphene_core::instances::{Instance, InstanceRef};
use graphene_core::vector::algorithms::merge_by_distance::MergeByDistanceExt; use graphene_core::vector::algorithms::merge_by_distance::MergeByDistanceExt;
use graphene_core::vector::misc::BooleanOperation;
use graphene_core::vector::style::Fill; use graphene_core::vector::style::Fill;
pub use graphene_core::vector::*; use graphene_core::vector::{PointId, VectorData, VectorDataTable};
use graphene_core::{Color, Ctx, GraphicElement, GraphicGroupTable}; use graphene_core::{Color, Ctx, GraphicElement, GraphicGroupTable};
pub use path_bool as path_bool_lib; pub use path_bool as path_bool_lib;
use path_bool::{FillRule, PathBooleanOperation}; use path_bool::{FillRule, PathBooleanOperation};
@ -14,6 +14,22 @@ use std::ops::Mul;
// TODO: since before we used a Vec of single-row tables and now we use a single table // TODO: since before we used a Vec of single-row tables and now we use a single table
// TODO: with multiple rows while still assuming a single row for the boolean operations. // TODO: with multiple rows while still assuming a single row for the boolean operations.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
#[widget(Radio)]
pub enum BooleanOperation {
#[default]
#[icon("BooleanUnion")]
Union,
#[icon("BooleanSubtractFront")]
SubtractFront,
#[icon("BooleanSubtractBack")]
SubtractBack,
#[icon("BooleanIntersect")]
Intersect,
#[icon("BooleanDifference")]
Difference,
}
/// Combines the geometric forms of one or more closed paths into a new vector path that results from cutting or joining the paths by the chosen method. /// Combines the geometric forms of one or more closed paths into a new vector path that results from cutting or joining the paths by the chosen method.
#[node_macro::node(category(""))] #[node_macro::node(category(""))]
async fn boolean_operation<I: Into<GraphicGroupTable> + 'n + Send + Clone>( async fn boolean_operation<I: Into<GraphicGroupTable> + 'n + Send + Clone>(
@ -356,50 +372,6 @@ fn from_path(path_data: &[Path]) -> VectorData {
VectorData::from_subpaths(all_subpaths, false) VectorData::from_subpaths(all_subpaths, false)
} }
pub fn convert_usvg_path(path: &usvg::Path) -> Vec<Subpath<PointId>> {
let mut subpaths = Vec::new();
let mut groups = Vec::new();
let mut points = path.data().points().iter();
let to_vec = |p: &usvg::tiny_skia_path::Point| DVec2::new(p.x as f64, p.y as f64);
for verb in path.data().verbs() {
match verb {
usvg::tiny_skia_path::PathVerb::Move => {
subpaths.push(Subpath::new(std::mem::take(&mut groups), false));
let Some(start) = points.next().map(to_vec) else { continue };
groups.push(ManipulatorGroup::new(start, Some(start), Some(start)));
}
usvg::tiny_skia_path::PathVerb::Line => {
let Some(end) = points.next().map(to_vec) else { continue };
groups.push(ManipulatorGroup::new(end, Some(end), Some(end)));
}
usvg::tiny_skia_path::PathVerb::Quad => {
let Some(handle) = points.next().map(to_vec) else { continue };
let Some(end) = points.next().map(to_vec) else { continue };
if let Some(last) = groups.last_mut() {
last.out_handle = Some(last.anchor + (2. / 3.) * (handle - last.anchor));
}
groups.push(ManipulatorGroup::new(end, Some(end + (2. / 3.) * (handle - end)), Some(end)));
}
usvg::tiny_skia_path::PathVerb::Cubic => {
let Some(first_handle) = points.next().map(to_vec) else { continue };
let Some(second_handle) = points.next().map(to_vec) else { continue };
let Some(end) = points.next().map(to_vec) else { continue };
if let Some(last) = groups.last_mut() {
last.out_handle = Some(first_handle);
}
groups.push(ManipulatorGroup::new(end, Some(second_handle), Some(end)));
}
usvg::tiny_skia_path::PathVerb::Close => {
subpaths.push(Subpath::new(std::mem::take(&mut groups), true));
}
}
}
subpaths.push(Subpath::new(groups, false));
subpaths
}
type Path = Vec<path_bool::PathSegment>; type Path = Vec<path_bool::PathSegment>;
fn boolean_union(a: Path, b: Path) -> Vec<Path> { fn boolean_union(a: Path, b: Path) -> Vec<Path> {

View file

@ -16,6 +16,7 @@ loading = ["serde_json"]
# Local dependencies # Local dependencies
dyn-any = { workspace = true } dyn-any = { workspace = true }
graphene-core = { workspace = true } graphene-core = { workspace = true }
graphene-path-bool = { workspace = true }
graphene-application-io = { workspace = true } graphene-application-io = { workspace = true }
# Workspace dependencies # Workspace dependencies

View file

@ -247,7 +247,7 @@ tagged_value! {
GradientType(graphene_core::vector::style::GradientType), GradientType(graphene_core::vector::style::GradientType),
ReferencePoint(graphene_core::transform::ReferencePoint), ReferencePoint(graphene_core::transform::ReferencePoint),
CentroidType(graphene_core::vector::misc::CentroidType), CentroidType(graphene_core::vector::misc::CentroidType),
BooleanOperation(graphene_core::vector::misc::BooleanOperation), BooleanOperation(graphene_path_bool::BooleanOperation),
} }
impl TaggedValue { impl TaggedValue {

View file

@ -28,18 +28,16 @@ dyn-any = { workspace = true }
graph-craft = { workspace = true } graph-craft = { workspace = true }
wgpu-executor = { workspace = true } wgpu-executor = { workspace = true }
graphene-core = { workspace = true } graphene-core = { workspace = true }
graphene-path-bool = { workspace = true }
graphene-application-io = { workspace = true } graphene-application-io = { workspace = true }
# Workspace dependencies # Workspace dependencies
fastnoise-lite = { workspace = true } fastnoise-lite = { workspace = true }
log = { workspace = true } log = { workspace = true }
bezier-rs = { workspace = true }
path-bool = { workspace = true }
glam = { workspace = true } glam = { workspace = true }
node-macro = { workspace = true } node-macro = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
usvg = { workspace = true }
rand_chacha = { workspace = true } rand_chacha = { workspace = true }
rand = { workspace = true } rand = { workspace = true }
bytemuck = { workspace = true } bytemuck = { workspace = true }

View file

@ -6,9 +6,10 @@ pub mod http;
pub mod image_color_palette; pub mod image_color_palette;
pub mod raster; pub mod raster;
pub mod text; pub mod text;
pub mod vector;
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
pub mod wasm_application_io; pub mod wasm_application_io;
pub use graphene_application_io as application_io; pub use graphene_application_io as application_io;
pub use graphene_core::vector;
pub use graphene_core::*; pub use graphene_core::*;
pub use graphene_path_bool as path_bool;

View file

@ -14,6 +14,7 @@ graphene-std = { workspace = true }
graph-craft = { workspace = true } graph-craft = { workspace = true }
wgpu-executor = { workspace = true } wgpu-executor = { workspace = true }
graphene-core = { workspace = true } graphene-core = { workspace = true }
graphene-path-bool = { workspace = true }
dyn-any = { workspace = true } dyn-any = { workspace = true }
# Workspace dependencies # Workspace dependencies

View file

@ -60,7 +60,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<f64>]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Vec<f64>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => BlendMode]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => BlendMode]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::transform::ReferencePoint]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::transform::ReferencePoint]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::misc::BooleanOperation]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_path_bool::BooleanOperation]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Option<Color>]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Option<Color>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Fill]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::Fill]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeCap]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_core::vector::style::StrokeCap]),

View file

@ -7,23 +7,8 @@ license = "MIT OR Apache-2.0"
[features] [features]
[dependencies] [dependencies]
# Local dependencies
dyn-any = { path = "../../libraries/dyn-any", features = [
"log-bad-types",
"rc",
"glam",
] }
# Workspace dependencies # Workspace dependencies
graphene-std = { workspace = true, features = ["gpu"] } graphene-std = { workspace = true, features = ["gpu"] }
graph-craft = { workspace = true } graph-craft = { workspace = true }
interpreted-executor = { workspace = true } interpreted-executor = { workspace = true }
log = { workspace = true }
futures = { workspace = true }
glam = { workspace = true }
base64 = { workspace = true }
# Optional workspace dependencies
serde = { workspace = true, optional = true }
tokio = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }