Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2144,7 +2144,7 @@ impl DocumentMessageHandler {
network_interface.upstream_flow_back_from_nodes(vec![selected_id.to_node()], &[], FlowType::HorizontalFlow).find(|id| {
network_interface
.reference(id, &[])
.is_some_and(|reference| reference == DefinitionIdentifier::Network("Boolean Operation".into()))
.is_some_and(|reference| reference == DefinitionIdentifier::ProtoNode(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER))
})
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,12 @@ impl<'a> ModifyInputsContext<'a> {
}

pub fn insert_boolean_data(&mut self, operation: graphene_std::vector::misc::BooleanOperation, layer: LayerNodeIdentifier) {
let boolean = resolve_network_node_type("Boolean Operation").expect("Boolean node does not exist").node_template_input_override([
Some(NodeInput::value(TaggedValue::Graphic(Default::default()), true)),
Some(NodeInput::value(TaggedValue::BooleanOperation(operation), false)),
]);
let boolean = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER)
.expect("Boolean node does not exist")
.node_template_input_override([
Some(NodeInput::value(TaggedValue::Graphic(Default::default()), true)),
Some(NodeInput::value(TaggedValue::BooleanOperation(operation), false)),
]);

let boolean_id = NodeId::new();
self.network_interface.insert_node(boolean_id, boolean, &[]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::utility_types::FrontendNodeType;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::network_interface::{
DocumentNodeMetadata, DocumentNodePersistentMetadata, InputMetadata, NodeNetworkInterface, NodeNetworkMetadata, NodeNetworkPersistentMetadata, NodeTemplate, NodeTypePersistentMetadata,
NumberInputSettings, Vec2InputSettings, WidgetOverride,
Vec2InputSettings, WidgetOverride,
};
use crate::messages::portfolio::utility_types::CachedData;
use crate::messages::prelude::Message;
Expand Down Expand Up @@ -1870,169 +1870,6 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
description: Cow::Borrowed("TODO"),
properties: None,
},
DocumentNodeDefinition {
identifier: "Boolean Operation",
category: "Vector: Modifier",
node_template: NodeTemplate {
document_node: DocumentNode {
implementation: DocumentNodeImplementation::Network(NodeNetwork {
exports: vec![NodeInput::node(NodeId(1), 0)],
nodes: vec![
DocumentNode {
inputs: vec![NodeInput::import(concrete!(Table<Vector>), 0), NodeInput::import(concrete!(vector::style::Fill), 1)],
implementation: DocumentNodeImplementation::ProtoNode(path_bool_nodes::boolean_operation::IDENTIFIER),
call_argument: generic!(T),
..Default::default()
},
DocumentNode {
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::ProtoNode(memo::memo::IDENTIFIER),
call_argument: generic!(T),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::Graphic(Default::default()), true),
NodeInput::value(TaggedValue::BooleanOperation(vector::misc::BooleanOperation::Union), false),
],
..Default::default()
},
persistent_node_metadata: DocumentNodePersistentMetadata {
network_metadata: Some(NodeNetworkMetadata {
persistent_metadata: NodeNetworkPersistentMetadata {
node_metadata: [
DocumentNodeMetadata {
persistent_metadata: DocumentNodePersistentMetadata {
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
..Default::default()
},
..Default::default()
},
DocumentNodeMetadata {
persistent_metadata: DocumentNodePersistentMetadata {
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(7, 0)),
..Default::default()
},
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
},
..Default::default()
}),
input_metadata: vec![("Content", "TODO").into(), ("Operation", "TODO").into()],
output_names: vec!["Vector".to_string()],
..Default::default()
},
},
description: Cow::Borrowed("TODO"),
properties: None,
},
DocumentNodeDefinition {
identifier: "Scatter Points",
category: "Vector: Modifier",
node_template: NodeTemplate {
document_node: DocumentNode {
implementation: DocumentNodeImplementation::Network(NodeNetwork {
exports: vec![NodeInput::node(NodeId(1), 0)],
nodes: [
DocumentNode {
inputs: vec![
NodeInput::import(concrete!(Table<Vector>), 0),
NodeInput::import(concrete!(f64), 1),
NodeInput::import(concrete!(u32), 2),
],
call_argument: generic!(T),
implementation: DocumentNodeImplementation::ProtoNode(vector::poisson_disk_points::IDENTIFIER),
..Default::default()
},
DocumentNode {
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::ProtoNode(memo::memo::IDENTIFIER),
call_argument: generic!(T),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![
NodeInput::value(TaggedValue::Vector(Default::default()), true),
NodeInput::value(TaggedValue::F64(10.), false),
NodeInput::value(TaggedValue::U32(0), false),
],
..Default::default()
},
persistent_node_metadata: DocumentNodePersistentMetadata {
network_metadata: Some(NodeNetworkMetadata {
persistent_metadata: NodeNetworkPersistentMetadata {
node_metadata: [
DocumentNodeMetadata {
persistent_metadata: DocumentNodePersistentMetadata {
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
..Default::default()
},
..Default::default()
},
DocumentNodeMetadata {
persistent_metadata: DocumentNodePersistentMetadata {
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(7, 0)),
..Default::default()
},
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
},
..Default::default()
}),
input_metadata: vec![
("Content", "TODO").into(),
InputMetadata::with_name_description_override(
"Separation",
"TODO",
WidgetOverride::Number(NumberInputSettings {
min: Some(0.01),
mode: NumberInputMode::Range,
range_min: Some(1.),
range_max: Some(100.),
..Default::default()
}),
),
InputMetadata::with_name_description_override(
"Seed",
"TODO",
WidgetOverride::Number(NumberInputSettings {
min: Some(0.),
is_integer: true,
..Default::default()
}),
),
],
output_names: vec!["Vector".to_string()],
..Default::default()
},
},
description: Cow::Borrowed("TODO"),
properties: None,
},
];

document_node_derive::post_process_nodes(custom)
Expand Down
43 changes: 37 additions & 6 deletions editor/src/messages/portfolio/document_migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
"graphene_core::transform::FreezeRealTimeNode",
"graphene_core::transform_nodes::BoundlessFootprintNode",
"graphene_core::transform_nodes::FreezeRealTimeNode",
// `subpath_segment_lengths` was inlined into the `sample_polyline` proto; old "Sample Polyline" subnetworks pass through unchanged.
"graphene_core::vector::SubpathSegmentLengthsNode",
"core_types::vector::SubpathSegmentLengthsNode",
],
Expand Down Expand Up @@ -910,8 +909,8 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
aliases: &["graphene_core::vector::PointsToPolylineNode"],
},
NodeReplacement {
node: graphene_std::vector::poisson_disk_points::IDENTIFIER,
aliases: &["graphene_core::vector::PoissonDiskPointsNode"],
node: graphene_std::vector::scatter_points::IDENTIFIER,
aliases: &["graphene_core::vector::PoissonDiskPointsNode", "core_types::vector::PoissonDiskPointsNode"],
Comment thread
Keavon marked this conversation as resolved.
},
NodeReplacement {
node: graphene_std::vector::position_on_path::IDENTIFIER,
Expand Down Expand Up @@ -2036,10 +2035,10 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
/// definition by its old reference name, swaps it to a still-supported implementation, and preserves the user's inputs.
/// After this runs, the node's reference resolves cleanly so the rest of `migrate_node` proceeds normally.
fn migrate_removed_catalog_definitions(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], document: &mut DocumentMessageHandler) -> Option<()> {
// Collapse the legacy "Sample Polyline" wrapper network into the standalone `sample_polyline` proto.
// The proto now computes per-bezpath segment lengths inline, so the wrapper's separate `subpath_segment_lengths`
// Collapse the legacy "Sample Polyline" wrapper network into the standalone `sample_polyline` proto node.
// The proto node now computes per-bezpath segment lengths inline, so the wrapper's separate `subpath_segment_lengths`
// and `Memo` nodes are no longer needed. The 7 user-facing inputs are positionally identical between the
// old wrapper and the new proto.
// old wrapper and the new proto node.
if let Some(DefinitionIdentifier::Network(name)) = document.network_interface.reference(node_id, network_path)
&& name == "Sample Polyline"
&& node.inputs.len() == 7
Expand All @@ -2052,6 +2051,38 @@ fn migrate_removed_catalog_definitions(node_id: &NodeId, node: &DocumentNode, ne
}
}

// Collapse the legacy "Scatter Points" wrapper network into the standalone `scatter_points` proto node.
// The wrapper's trailing `Memo` node is now produced automatically by the `memoize` attribute on the
// proto node, so the wrapper itself is redundant. The 3 user-facing inputs are positionally identical
// between the old wrapper and the new proto node.
if let Some(DefinitionIdentifier::Network(name)) = document.network_interface.reference(node_id, network_path)
&& name == "Scatter Points"
&& node.inputs.len() == 3
{
let mut node_template = resolve_proto_node_type(graphene_std::vector::scatter_points::IDENTIFIER)?.default_node_template();
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut node_template)?;
for (index, input) in old_inputs.iter().take(3).enumerate() {
document.network_interface.set_input(&InputConnector::node(*node_id, index), input.clone(), network_path);
}
}

// Collapse the legacy "Boolean Operation" wrapper network into the standalone `boolean_operation` proto node.
// The wrapper's trailing `Memo` node is now produced automatically by the `memoize` attribute on the
// proto node, so the wrapper itself is redundant. The 2 user-facing inputs are positionally identical
// between the old wrapper and the new proto node.
if let Some(DefinitionIdentifier::Network(name)) = document.network_interface.reference(node_id, network_path)
&& name == "Boolean Operation"
&& node.inputs.len() == 2
{
let mut node_template = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER)?.default_node_template();
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut node_template)?;
for (index, input) in old_inputs.iter().take(2).enumerate() {
document.network_interface.set_input(&InputConnector::node(*node_id, index), input.clone(), network_path);
}
}

Some(())
}

Expand Down
2 changes: 1 addition & 1 deletion node-graph/nodes/path-bool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub use vector_types::vector::misc::BooleanOperation;
// TODO: with multiple rows while still assuming a single row for the boolean operations.

/// 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("Vector: Modifier"), memoize)]
async fn boolean_operation<I: graphic_types::IntoGraphicTable + 'n + Send + Clone>(
_: impl Ctx,
/// The table of vector paths to perform the boolean operation on. Nested tables are automatically flattened.
Expand Down
11 changes: 6 additions & 5 deletions node-graph/nodes/vector/src/vector_nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1780,14 +1780,15 @@ async fn tangent_on_path(
if radians { angle } else { angle.to_degrees() }
}

#[node_macro::node(category(""), path(core_types::vector))]
async fn poisson_disk_points(
#[node_macro::node(category("Vector: Modifier"), path(core_types::vector), memoize)]
async fn scatter_points(
_: impl Ctx,
content: Table<Vector>,
#[unit(" px")]
#[default(10.)]
#[hard_min(0.01)]
separation_disk_diameter: f64,
#[range((1., 100.))]
separation: f64,
seed: SeedValue,
) -> Table<Vector> {
let mut rng = rand::rngs::StdRng::seed_from_u64(seed.into());
Expand All @@ -1813,7 +1814,7 @@ async fn poisson_disk_points(
continue;
}

for point in bezpath_algorithms::poisson_disk_points(i, &path_with_bounding_boxes, separation_disk_diameter, || rng.random::<f64>()) {
for point in bezpath_algorithms::poisson_disk_points(i, &path_with_bounding_boxes, separation, || rng.random::<f64>()) {
result.point_domain.push(PointId::generate(), point);
}
}
Expand Down Expand Up @@ -3120,7 +3121,7 @@ mod test {
}
#[tokio::test]
async fn poisson() {
let poisson_points = super::poisson_disk_points(
let poisson_points = super::scatter_points(
Footprint::default(),
vector_node_from_bezpath(Ellipse::from_rect(Rect::new(-50., -50., 50., 50.)).to_path(DEFAULT_ACCURACY)),
10. * std::f64::consts::SQRT_2,
Expand Down
Loading