Hide the Cull node by integrating it into all generator nodes (#1538)

* Hide the Cull node by integrating it into all generator nodes

* Remove internal Cull node from Mandelbrot
This commit is contained in:
Keavon Chambers 2023-12-30 12:28:06 -08:00 committed by GitHub
parent 0e49388312
commit 1cc23320a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 445 additions and 65 deletions

View File

@ -1353,7 +1353,7 @@ impl DocumentMessageHandler {
.max(100.) .max(100.)
.range_min(Some(0.)) .range_min(Some(0.))
.range_max(Some(100.)) .range_max(Some(100.))
.mode(NumberInputMode::Range) .mode_range()
.on_update(|number_input: &NumberInput| { .on_update(|number_input: &NumberInput| {
if let Some(value) = number_input.value { if let Some(value) = number_input.value {
DocumentMessage::SetOpacityForSelectedLayers { opacity: value / 100. }.into() DocumentMessage::SetOpacityForSelectedLayers { opacity: value / 100. }.into()

View File

@ -190,7 +190,6 @@ impl<'a> ModifyInputsContext<'a> {
let node_type = resolve_document_node_type("Shape").expect("Shape node does not exist"); let node_type = resolve_document_node_type("Shape").expect("Shape node does not exist");
node_type.to_document_node_default_inputs([Some(NodeInput::value(TaggedValue::Subpaths(subpaths), false))], Default::default()) node_type.to_document_node_default_inputs([Some(NodeInput::value(TaggedValue::Subpaths(subpaths), false))], Default::default())
}; };
let cull = resolve_document_node_type("Cull").expect("Cull node does not exist").default_document_node();
let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_document_node(); let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_document_node();
let fill = resolve_document_node_type("Fill").expect("Fill node does not exist").default_document_node(); let fill = resolve_document_node_type("Fill").expect("Fill node does not exist").default_document_node();
let stroke = resolve_document_node_type("Stroke").expect("Stroke node does not exist").default_document_node(); let stroke = resolve_document_node_type("Stroke").expect("Stroke node does not exist").default_document_node();
@ -201,10 +200,8 @@ impl<'a> ModifyInputsContext<'a> {
self.insert_node_before(fill_id, stroke_id, 0, fill, IVec2::new(-8, 0)); self.insert_node_before(fill_id, stroke_id, 0, fill, IVec2::new(-8, 0));
let transform_id = NodeId(generate_uuid()); let transform_id = NodeId(generate_uuid());
self.insert_node_before(transform_id, fill_id, 0, transform, IVec2::new(-8, 0)); self.insert_node_before(transform_id, fill_id, 0, transform, IVec2::new(-8, 0));
let cull_id = NodeId(generate_uuid());
self.insert_node_before(cull_id, transform_id, 0, cull, IVec2::new(-8, 0));
let shape_id = NodeId(generate_uuid()); let shape_id = NodeId(generate_uuid());
self.insert_node_before(shape_id, cull_id, 0, shape, IVec2::new(-8, 0)); self.insert_node_before(shape_id, transform_id, 0, shape, IVec2::new(-8, 0));
self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true });
} }
@ -218,7 +215,6 @@ impl<'a> ModifyInputsContext<'a> {
], ],
Default::default(), Default::default(),
); );
let cull = resolve_document_node_type("Cull").expect("Cull node does not exist").default_document_node();
let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_document_node(); let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_document_node();
let fill = resolve_document_node_type("Fill").expect("Fill node does not exist").default_document_node(); let fill = resolve_document_node_type("Fill").expect("Fill node does not exist").default_document_node();
let stroke = resolve_document_node_type("Stroke").expect("Stroke node does not exist").default_document_node(); let stroke = resolve_document_node_type("Stroke").expect("Stroke node does not exist").default_document_node();
@ -229,10 +225,8 @@ impl<'a> ModifyInputsContext<'a> {
self.insert_node_before(fill_id, stroke_id, 0, fill, IVec2::new(-8, 0)); self.insert_node_before(fill_id, stroke_id, 0, fill, IVec2::new(-8, 0));
let transform_id = NodeId(generate_uuid()); let transform_id = NodeId(generate_uuid());
self.insert_node_before(transform_id, fill_id, 0, transform, IVec2::new(-8, 0)); self.insert_node_before(transform_id, fill_id, 0, transform, IVec2::new(-8, 0));
let cull_id = NodeId(generate_uuid());
self.insert_node_before(cull_id, transform_id, 0, cull, IVec2::new(-8, 0));
let text_id = NodeId(generate_uuid()); let text_id = NodeId(generate_uuid());
self.insert_node_before(text_id, cull_id, 0, text, IVec2::new(-8, 0)); self.insert_node_before(text_id, transform_id, 0, text, IVec2::new(-8, 0));
self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true });
} }
@ -241,15 +235,14 @@ impl<'a> ModifyInputsContext<'a> {
let node_type = resolve_document_node_type("Image").expect("Image node does not exist"); let node_type = resolve_document_node_type("Image").expect("Image node does not exist");
node_type.to_document_node_default_inputs([Some(NodeInput::value(TaggedValue::ImageFrame(image_frame), false))], Default::default()) node_type.to_document_node_default_inputs([Some(NodeInput::value(TaggedValue::ImageFrame(image_frame), false))], Default::default())
}; };
let sample = resolve_document_node_type("Sample").expect("Sample node does not exist").default_document_node();
let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_document_node(); let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_document_node();
let transform_id = NodeId(generate_uuid()); let transform_id = NodeId(generate_uuid());
self.insert_node_before(transform_id, layer, 0, transform, IVec2::new(-8, 0)); self.insert_node_before(transform_id, layer, 0, transform, IVec2::new(-8, 0));
let sample_id = NodeId(generate_uuid());
self.insert_node_before(sample_id, transform_id, 0, sample, IVec2::new(-8, 0));
let image_id = NodeId(generate_uuid()); let image_id = NodeId(generate_uuid());
self.insert_node_before(image_id, sample_id, 0, image, IVec2::new(-8, 0)); self.insert_node_before(image_id, transform_id, 0, image, IVec2::new(-8, 0));
self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true });
} }

View File

@ -264,6 +264,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
manual_composition: Some(concrete!(Footprint)), manual_composition: Some(concrete!(Footprint)),
..Default::default() ..Default::default()
}, },
// TODO: Does this need an internal Cull node to be added to its implementation?
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Input Frame", name: "Input Frame",
category: "Ignore", category: "Ignore",
@ -285,7 +286,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
category: "Structural", category: "Structural",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)], inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Load Resource".to_string(), name: "Load Resource".to_string(),
@ -299,6 +300,13 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::DecodeImageNode")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::DecodeImageNode")),
..Default::default() ..Default::default()
}, },
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(1), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
@ -562,7 +570,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Image Frame", name: "Image Frame",
category: "General", category: "General",
implementation: NodeImplementation::proto("graphene_std::raster::ImageFrameNode<_, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Image Frame".to_string(),
inputs: vec![NodeInput::Network(concrete!(graphene_core::raster::Image<Color>)), NodeInput::Network(concrete!(DAffine2))],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::ImageFrameNode<_, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::value("Image", TaggedValue::Image(Image::empty()), true), DocumentInputType::value("Image", TaggedValue::Image(Image::empty()), true),
DocumentInputType::value("Transform", TaggedValue::DAffine2(DAffine2::IDENTITY), true), DocumentInputType::value("Transform", TaggedValue::DAffine2(DAffine2::IDENTITY), true),
@ -574,7 +605,64 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Noise Pattern", name: "Noise Pattern",
category: "General", category: "General",
implementation: NodeImplementation::proto("graphene_std::raster::NoisePatternNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
NodeId(0),
],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Noise Pattern".to_string(),
inputs: vec![
NodeInput::Network(concrete!(())),
NodeInput::Network(concrete!(UVec2)),
NodeInput::Network(concrete!(u32)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(graphene_core::raster::NoiseType)),
NodeInput::Network(concrete!(graphene_core::raster::FractalType)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(graphene_core::raster::FractalType)),
NodeInput::Network(concrete!(u32)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(graphene_core::raster::CellularDistanceFunction)),
NodeInput::Network(concrete!(graphene_core::raster::CellularReturnType)),
NodeInput::Network(concrete!(f32)),
],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::raster::NoisePatternNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::value("None", TaggedValue::None, false), DocumentInputType::value("None", TaggedValue::None, false),
// All // All
@ -601,6 +689,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
properties: node_properties::noise_pattern_properties, properties: node_properties::noise_pattern_properties,
..Default::default() ..Default::default()
}, },
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Mask", name: "Mask",
category: "Image Adjustments", category: "Image Adjustments",
@ -613,6 +702,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
properties: node_properties::mask_properties, properties: node_properties::mask_properties,
..Default::default() ..Default::default()
}, },
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Insert Channel", name: "Insert Channel",
category: "Image Adjustments", category: "Image Adjustments",
@ -626,6 +716,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
properties: node_properties::insert_channel_properties, properties: node_properties::insert_channel_properties,
..Default::default() ..Default::default()
}, },
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Combine Channels", name: "Combine Channels",
category: "Image Adjustments", category: "Image Adjustments",
@ -643,6 +734,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}], }],
..Default::default() ..Default::default()
}, },
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Blend", name: "Blend",
category: "Image Adjustments", category: "Image Adjustments",
@ -871,7 +963,35 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Brush", name: "Brush",
category: "Brush", category: "Brush",
implementation: NodeImplementation::proto("graphene_std::brush::BrushNode<_, _, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Brush".to_string(),
inputs: vec![
NodeInput::Network(concrete!(graphene_core::raster::ImageFrame<Color>)),
NodeInput::Network(concrete!(graphene_core::raster::ImageFrame<Color>)),
NodeInput::Network(concrete!(Vec<graphene_core::vector::brush_stroke::BrushStroke>)),
NodeInput::Network(concrete!(BrushCache)),
],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::brush::BrushNode<_, _, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::value("Background", TaggedValue::ImageFrame(ImageFrame::empty()), true), DocumentInputType::value("Background", TaggedValue::ImageFrame(ImageFrame::empty()), true),
DocumentInputType::value("Bounds", TaggedValue::ImageFrame(ImageFrame::empty()), true), DocumentInputType::value("Bounds", TaggedValue::ImageFrame(ImageFrame::empty()), true),
@ -907,7 +1027,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Image", name: "Image",
category: "Ignore", category: "Ignore",
implementation: NodeImplementation::proto("graphene_core::ops::IdentityNode"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Identity".to_string(),
inputs: vec![NodeInput::Network(concrete!(ImageFrame<Color>))],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false)], inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false)],
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)], outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
properties: |_document_node, _node_id, _context| node_properties::string_properties("A bitmap image embedded in this node"), properties: |_document_node, _node_id, _context| node_properties::string_properties("A bitmap image embedded in this node"),
@ -2013,7 +2156,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Circle", name: "Circle",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::vector::generator_nodes::CircleGenerator<_>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Circle Generator".to_string(),
inputs: vec![NodeInput::Network(concrete!(())), NodeInput::Network(concrete!(f32))],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::CircleGenerator<_>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![DocumentInputType::none(), DocumentInputType::value("Radius", TaggedValue::F32(50.), false)], inputs: vec![DocumentInputType::none(), DocumentInputType::value("Radius", TaggedValue::F32(50.), false)],
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)], outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
properties: node_properties::circle_properties, properties: node_properties::circle_properties,
@ -2022,7 +2188,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Ellipse", name: "Ellipse",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::vector::generator_nodes::EllipseGenerator<_, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Ellipse Generator".to_string(),
inputs: vec![NodeInput::Network(concrete!(())), NodeInput::Network(concrete!(f32)), NodeInput::Network(concrete!(f32))],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::EllipseGenerator<_, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::none(), DocumentInputType::none(),
DocumentInputType::value("Radius X", TaggedValue::F32(50.), false), DocumentInputType::value("Radius X", TaggedValue::F32(50.), false),
@ -2035,7 +2224,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Rectangle", name: "Rectangle",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::vector::generator_nodes::RectangleGenerator<_, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Rectangle Generator".to_string(),
inputs: vec![NodeInput::Network(concrete!(())), NodeInput::Network(concrete!(f32)), NodeInput::Network(concrete!(f32))],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::RectangleGenerator<_, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::none(), DocumentInputType::none(),
DocumentInputType::value("Size X", TaggedValue::F32(100.), false), DocumentInputType::value("Size X", TaggedValue::F32(100.), false),
@ -2048,7 +2260,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Regular Polygon", name: "Regular Polygon",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::vector::generator_nodes::RegularPolygonGenerator<_, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Regular Polygon Generator".to_string(),
inputs: vec![NodeInput::Network(concrete!(())), NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(f32))],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::RegularPolygonGenerator<_, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::none(), DocumentInputType::none(),
DocumentInputType::value("Sides", TaggedValue::U32(6), false), DocumentInputType::value("Sides", TaggedValue::U32(6), false),
@ -2061,7 +2296,35 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Star", name: "Star",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::vector::generator_nodes::StarGenerator<_, _, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Star Generator".to_string(),
inputs: vec![
NodeInput::Network(concrete!(())),
NodeInput::Network(concrete!(u32)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(f32)),
],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::StarGenerator<_, _, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::none(), DocumentInputType::none(),
DocumentInputType::value("Sides", TaggedValue::U32(5), false), DocumentInputType::value("Sides", TaggedValue::U32(5), false),
@ -2075,7 +2338,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Line", name: "Line",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::vector::generator_nodes::LineGenerator<_, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Line Generator".to_string(),
inputs: vec![NodeInput::Network(concrete!(())), NodeInput::Network(concrete!(DVec2)), NodeInput::Network(concrete!(DVec2))],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::LineGenerator<_, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::none(), DocumentInputType::none(),
DocumentInputType::value("Start", TaggedValue::DVec2(DVec2::new(0., -50.)), false), DocumentInputType::value("Start", TaggedValue::DVec2(DVec2::new(0., -50.)), false),
@ -2088,7 +2374,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Spline", name: "Spline",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::vector::generator_nodes::SplineGenerator<_>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Spline Generator".to_string(),
inputs: vec![NodeInput::Network(concrete!(())), NodeInput::Network(concrete!(Vec<DVec2>))],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::SplineGenerator<_>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::none(), DocumentInputType::none(),
DocumentInputType::value("Points", TaggedValue::VecDVec2(vec![DVec2::new(0., -50.), DVec2::new(25., 0.), DVec2::new(0., 50.)]), false), DocumentInputType::value("Points", TaggedValue::VecDVec2(vec![DVec2::new(0., -50.), DVec2::new(25., 0.), DVec2::new(0., 50.)]), false),
@ -2100,10 +2409,35 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Shape", name: "Shape",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::vector::generator_nodes::PathGenerator<_>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Path Generator".to_string(),
inputs: vec![
NodeInput::Network(concrete!(Vec<bezier_rs::Subpath<graphene_core::uuid::ManipulatorGroupId>>)),
NodeInput::Network(concrete!(Vec<graphene_core::uuid::ManipulatorGroupId>)),
],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::vector::generator_nodes::PathGenerator<_>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::value("Path Data", TaggedValue::Subpaths(vec![]), false), DocumentInputType::value("Path Data", TaggedValue::Subpaths(vec![]), false),
// TODO: Keavon asks: what is this for? Is it dead code? It seems to only be set, never read.
DocumentInputType::value("Mirror", TaggedValue::ManipulatorGroupIds(vec![]), false), DocumentInputType::value("Mirror", TaggedValue::ManipulatorGroupIds(vec![]), false),
], ],
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)], outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
@ -2139,10 +2473,38 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Text", name: "Text",
category: "Vector", category: "Vector",
implementation: NodeImplementation::proto("graphene_core::text::TextGeneratorNode<_, _, _>"), implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Text Generator".to_string(),
inputs: vec![
NodeInput::Network(concrete!(application_io::EditorApi<graphene_std::wasm_application_io::WasmApplicationIo>)),
NodeInput::Network(concrete!(String)),
NodeInput::Network(concrete!(graphene_core::text::Font)),
NodeInput::Network(concrete!(f64)),
],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::text::TextGeneratorNode<_, _, _>")),
..Default::default()
},
DocumentNode {
name: "Cull".to_string(),
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::transform::CullNode<_>")),
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
]
.into_iter()
.enumerate()
.map(|(id, node)| (NodeId(id as u64), node))
.collect(),
..Default::default()
}),
inputs: vec![ inputs: vec![
DocumentInputType::none(), DocumentInputType::none(),
DocumentInputType::value("Text", TaggedValue::String("hello world".to_string()), false), DocumentInputType::value("Text", TaggedValue::String("Lorem ipsum".to_string()), false),
DocumentInputType::value("Font", TaggedValue::Font(Font::new(DEFAULT_FONT_FAMILY.into(), DEFAULT_FONT_STYLE.into())), false), DocumentInputType::value("Font", TaggedValue::Font(Font::new(DEFAULT_FONT_FAMILY.into(), DEFAULT_FONT_STYLE.into())), false),
DocumentInputType::value("Size", TaggedValue::F64(24.), false), DocumentInputType::value("Size", TaggedValue::F64(24.), false),
], ],
@ -2312,6 +2674,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
properties: node_properties::node_no_properties, properties: node_properties::node_no_properties,
..Default::default() ..Default::default()
}, },
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition { DocumentNodeDefinition {
name: "Image Segmentation", name: "Image Segmentation",
category: "Image Adjustments", category: "Image Adjustments",

View File

@ -782,11 +782,11 @@ fn curves_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, na
} }
pub fn levels_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { pub fn levels_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let input_shadows = number_widget(document_node, node_id, 1, "Shadows", NumberInput::default().min(0.).max(100.).unit("%"), true); let input_shadows = number_widget(document_node, node_id, 1, "Shadows", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
let input_midtones = number_widget(document_node, node_id, 2, "Midtones", NumberInput::default().min(0.).max(100.).unit("%"), true); let input_midtones = number_widget(document_node, node_id, 2, "Midtones", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
let input_highlights = number_widget(document_node, node_id, 3, "Highlights", NumberInput::default().min(0.).max(100.).unit("%"), true); let input_highlights = number_widget(document_node, node_id, 3, "Highlights", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
let output_minimums = number_widget(document_node, node_id, 4, "Output Minimums", NumberInput::default().min(0.).max(100.).unit("%"), true); let output_minimums = number_widget(document_node, node_id, 4, "Output Minimums", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
let output_maximums = number_widget(document_node, node_id, 5, "Output Maximums", NumberInput::default().min(0.).max(100.).unit("%"), true); let output_maximums = number_widget(document_node, node_id, 5, "Output Maximums", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
vec![ vec![
LayoutGroup::Row { widgets: input_shadows }, LayoutGroup::Row { widgets: input_shadows },
@ -802,12 +802,12 @@ pub fn black_and_white_properties(document_node: &DocumentNode, node_id: NodeId,
const MAX: f64 = 300.; const MAX: f64 = 300.;
// TODO: Add tint color (blended above using the "Color" blend mode) // TODO: Add tint color (blended above using the "Color" blend mode)
let tint = color_widget(document_node, node_id, 1, "Tint", ColorButton::default(), true); let tint = color_widget(document_node, node_id, 1, "Tint", ColorButton::default(), true);
let r_weight = number_widget(document_node, node_id, 2, "Reds", NumberInput::default().min(MIN).max(MAX).unit("%"), true); let r_weight = number_widget(document_node, node_id, 2, "Reds", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
let y_weight = number_widget(document_node, node_id, 3, "Yellows", NumberInput::default().min(MIN).max(MAX).unit("%"), true); let y_weight = number_widget(document_node, node_id, 3, "Yellows", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
let g_weight = number_widget(document_node, node_id, 4, "Greens", NumberInput::default().min(MIN).max(MAX).unit("%"), true); let g_weight = number_widget(document_node, node_id, 4, "Greens", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
let c_weight = number_widget(document_node, node_id, 5, "Cyans", NumberInput::default().min(MIN).max(MAX).unit("%"), true); let c_weight = number_widget(document_node, node_id, 5, "Cyans", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
let b_weight = number_widget(document_node, node_id, 6, "Blues", NumberInput::default().min(MIN).max(MAX).unit("%"), true); let b_weight = number_widget(document_node, node_id, 6, "Blues", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
let m_weight = number_widget(document_node, node_id, 7, "Magentas", NumberInput::default().min(MIN).max(MAX).unit("%"), true); let m_weight = number_widget(document_node, node_id, 7, "Magentas", NumberInput::default().mode_range().min(MIN).max(MAX).unit("%"), true);
vec![ vec![
tint, tint,
@ -823,7 +823,7 @@ pub fn black_and_white_properties(document_node: &DocumentNode, node_id: NodeId,
pub fn blend_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { pub fn blend_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let backdrop = color_widget(document_node, node_id, 1, "Backdrop", ColorButton::default(), true); let backdrop = color_widget(document_node, node_id, 1, "Backdrop", ColorButton::default(), true);
let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true);
let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().min(0.).max(100.).unit("%"), true); let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
vec![backdrop, blend_mode, LayoutGroup::Row { widgets: opacity }] vec![backdrop, blend_mode, LayoutGroup::Row { widgets: opacity }]
} }
@ -1043,8 +1043,8 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
pub fn adjust_hsl_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { pub fn adjust_hsl_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let hue_shift = number_widget(document_node, node_id, 1, "Hue Shift", NumberInput::default().min(-180.).max(180.).unit("°"), true); let hue_shift = number_widget(document_node, node_id, 1, "Hue Shift", NumberInput::default().min(-180.).max(180.).unit("°"), true);
let saturation_shift = number_widget(document_node, node_id, 2, "Saturation Shift", NumberInput::default().min(-100.).max(100.).unit("%"), true); let saturation_shift = number_widget(document_node, node_id, 2, "Saturation Shift", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
let lightness_shift = number_widget(document_node, node_id, 3, "Lightness Shift", NumberInput::default().min(-100.).max(100.).unit("%"), true); let lightness_shift = number_widget(document_node, node_id, 3, "Lightness Shift", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
vec![ vec![
LayoutGroup::Row { widgets: hue_shift }, LayoutGroup::Row { widgets: hue_shift },
@ -1079,15 +1079,15 @@ pub fn _blur_image_properties(document_node: &DocumentNode, node_id: NodeId, _co
} }
pub fn adjust_threshold_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { pub fn adjust_threshold_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let thereshold_min = number_widget(document_node, node_id, 1, "Min Luminance", NumberInput::default().min(0.).max(100.).unit("%"), true); let thereshold_min = number_widget(document_node, node_id, 1, "Min Luminance", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
let thereshold_max = number_widget(document_node, node_id, 2, "Max Luminance", NumberInput::default().min(0.).max(100.).unit("%"), true); let thereshold_max = number_widget(document_node, node_id, 2, "Max Luminance", NumberInput::default().mode_range().min(0.).max(100.).unit("%"), true);
let luminance_calc = luminance_calculation(document_node, node_id, 3, "Luminance Calc", true); let luminance_calc = luminance_calculation(document_node, node_id, 3, "Luminance Calc", true);
vec![LayoutGroup::Row { widgets: thereshold_min }, LayoutGroup::Row { widgets: thereshold_max }, luminance_calc] vec![LayoutGroup::Row { widgets: thereshold_min }, LayoutGroup::Row { widgets: thereshold_max }, luminance_calc]
} }
pub fn adjust_vibrance_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { pub fn adjust_vibrance_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let vibrance = number_widget(document_node, node_id, 1, "Vibrance", NumberInput::default().min(-100.).max(100.).unit("%"), true); let vibrance = number_widget(document_node, node_id, 1, "Vibrance", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
vec![LayoutGroup::Row { widgets: vibrance }] vec![LayoutGroup::Row { widgets: vibrance }]
} }
@ -1140,10 +1140,38 @@ pub fn adjust_channel_mixer_properties(document_node: &DocumentNode, node_id: No
(false, RedGreenBlue::Green) => ((10, "(Green) Red", 0.), (11, "(Green) Green", 100.), (12, "(Green) Blue", 0.), (13, "(Green) Constant", 0.)), (false, RedGreenBlue::Green) => ((10, "(Green) Red", 0.), (11, "(Green) Green", 100.), (12, "(Green) Blue", 0.), (13, "(Green) Constant", 0.)),
(false, RedGreenBlue::Blue) => ((14, "(Blue) Red", 0.), (15, "(Blue) Green", 0.), (16, "(Blue) Blue", 100.), (17, "(Blue) Constant", 0.)), (false, RedGreenBlue::Blue) => ((14, "(Blue) Red", 0.), (15, "(Blue) Green", 0.), (16, "(Blue) Blue", 100.), (17, "(Blue) Constant", 0.)),
}; };
let red = number_widget(document_node, node_id, r.0, r.1, NumberInput::default().min(-200.).max(200.).value(Some(r.2)).unit("%"), true); let red = number_widget(
let green = number_widget(document_node, node_id, g.0, g.1, NumberInput::default().min(-200.).max(200.).value(Some(g.2)).unit("%"), true); document_node,
let blue = number_widget(document_node, node_id, b.0, b.1, NumberInput::default().min(-200.).max(200.).value(Some(b.2)).unit("%"), true); node_id,
let constant = number_widget(document_node, node_id, c.0, c.1, NumberInput::default().min(-200.).max(200.).value(Some(c.2)).unit("%"), true); r.0,
r.1,
NumberInput::default().mode_range().min(-200.).max(200.).value(Some(r.2)).unit("%"),
true,
);
let green = number_widget(
document_node,
node_id,
g.0,
g.1,
NumberInput::default().mode_range().min(-200.).max(200.).value(Some(g.2)).unit("%"),
true,
);
let blue = number_widget(
document_node,
node_id,
b.0,
b.1,
NumberInput::default().mode_range().min(-200.).max(200.).value(Some(b.2)).unit("%"),
true,
);
let constant = number_widget(
document_node,
node_id,
c.0,
c.1,
NumberInput::default().mode_range().min(-200.).max(200.).value(Some(c.2)).unit("%"),
true,
);
// Monochrome // Monochrome
let mut layout = vec![LayoutGroup::Row { widgets: monochrome }]; let mut layout = vec![LayoutGroup::Row { widgets: monochrome }];
@ -1206,10 +1234,10 @@ pub fn adjust_selective_color_properties(document_node: &DocumentNode, node_id:
SelectiveColorChoice::Neutrals => ((30, "(Neutrals) Cyan"), (31, "(Neutrals) Magenta"), (32, "(Neutrals) Yellow"), (33, "(Neutrals) Black")), SelectiveColorChoice::Neutrals => ((30, "(Neutrals) Cyan"), (31, "(Neutrals) Magenta"), (32, "(Neutrals) Yellow"), (33, "(Neutrals) Black")),
SelectiveColorChoice::Blacks => ((34, "(Blacks) Cyan"), (35, "(Blacks) Magenta"), (36, "(Blacks) Yellow"), (37, "(Blacks) Black")), SelectiveColorChoice::Blacks => ((34, "(Blacks) Cyan"), (35, "(Blacks) Magenta"), (36, "(Blacks) Yellow"), (37, "(Blacks) Black")),
}; };
let cyan = number_widget(document_node, node_id, c.0, c.1, NumberInput::default().min(-100.).max(100.).unit("%"), true); let cyan = number_widget(document_node, node_id, c.0, c.1, NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
let magenta = number_widget(document_node, node_id, m.0, m.1, NumberInput::default().min(-100.).max(100.).unit("%"), true); let magenta = number_widget(document_node, node_id, m.0, m.1, NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
let yellow = number_widget(document_node, node_id, y.0, y.1, NumberInput::default().min(-100.).max(100.).unit("%"), true); let yellow = number_widget(document_node, node_id, y.0, y.1, NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
let black = number_widget(document_node, node_id, k.0, k.1, NumberInput::default().min(-100.).max(100.).unit("%"), true); let black = number_widget(document_node, node_id, k.0, k.1, NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true);
// Mode // Mode
let mode_index = 1; let mode_index = 1;

View File

@ -420,14 +420,11 @@ fn new_brush_layer(document: &DocumentMessageHandler, responses: &mut VecDeque<M
let brush_node = resolve_document_node_type("Brush") let brush_node = resolve_document_node_type("Brush")
.expect("Brush node does not exist") .expect("Brush node does not exist")
.to_document_node_default_inputs([], DocumentNodeMetadata::position((-8, 0))); .to_document_node_default_inputs([], DocumentNodeMetadata::position((-8, 0)));
let cull_node = resolve_document_node_type("Cull")
.expect("Cull node does not exist")
.to_document_node_default_inputs([Some(NodeInput::node(NodeId(1), 0))], DocumentNodeMetadata::default());
let id = NodeId(generate_uuid()); let id = NodeId(generate_uuid());
responses.add(GraphOperationMessage::NewCustomLayer { responses.add(GraphOperationMessage::NewCustomLayer {
id, id,
nodes: HashMap::from([(NodeId(1), brush_node), (NodeId(0), cull_node)]), nodes: HashMap::from([(NodeId(0), brush_node)]),
parent: document.new_layer_parent(), parent: document.new_layer_parent(),
insert_index: -1, insert_index: -1,
}); });

View File

@ -173,7 +173,7 @@ register_node!(graphene_core::transform::SetTransformNode<_>, input: VectorData,
## Debugging ## Debugging
Debugging inside your node can be done with the `log` macros, for example `info!("The opacity is {opacity_multiplier}");`. Debugging inside your node can be done with the `log::debug!()` macro, for example `log::debug!("The opacity is {opacity_multiplier}");`.
We need a utility to easily view a graph as the various steps are applied. We also need a way to transparently see which constructors are being run, which nodes are being evaluated, and in what order. We need a utility to easily view a graph as the various steps are applied. We also need a way to transparently see which constructors are being run, which nodes are being evaluated, and in what order.

View File

@ -99,7 +99,6 @@ fn spline_generator(_input: (), positions: Vec<DVec2>) -> VectorData {
// TODO(TrueDoctor): I removed the Arc requirement we should think about when it makes sense to use it vs making a generic value node // TODO(TrueDoctor): I removed the Arc requirement we should think about when it makes sense to use it vs making a generic value node
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PathGenerator<Mirror> { pub struct PathGenerator<Mirror> {
// TODO: Keavon asks: what is this for? Is it dead code? It seems to only be set, never read.
mirror: Mirror, mirror: Mirror,
} }

View File

@ -16,7 +16,8 @@ pub struct VectorData {
pub transform: DAffine2, pub transform: DAffine2,
pub style: PathStyle, pub style: PathStyle,
pub alpha_blending: AlphaBlending, pub alpha_blending: AlphaBlending,
// TODO: Keavon asks: what is this for? Is it dead code? It seems to only be set, never read. /// A list of all manipulator groups (referenced in `subpaths`) that have smooth handles (where their handles are colinear, or locked to 180° angles from one another)
/// This gets read in `graph_operation_message_handler.rs` by calling `inputs.as_mut_slice()` (search for the string `"Shape does not have subpath and mirror angle inputs"` to find it).
pub mirror_angle: Vec<ManipulatorGroupId>, pub mirror_angle: Vec<ManipulatorGroupId>,
} }

View File

@ -998,7 +998,6 @@ impl NodeNetwork {
if let Some(new_output_node) = self.nodes.get_mut(&output.node_id) { if let Some(new_output_node) = self.nodes.get_mut(&output.node_id) {
for source in node.original_location.outputs(i) { for source in node.original_location.outputs(i) {
info!("{:?} {}", source, output.node_output_index);
new_output_node.original_location.outputs_source.insert(source, output.node_output_index); new_output_node.original_location.outputs_source.insert(source, output.node_output_index);
} }
} }

View File

@ -578,16 +578,16 @@ impl core::fmt::Debug for GraphErrorType {
x if x.ends_with('1') && !x.ends_with("11") => format!("{x}st"), x if x.ends_with('1') && !x.ends_with("11") => format!("{x}st"),
x if x.ends_with('2') && !x.ends_with("12") => format!("{x}nd"), x if x.ends_with('2') && !x.ends_with("12") => format!("{x}nd"),
x if x.ends_with('3') && !x.ends_with("13") => format!("{x}rd"), x if x.ends_with('3') && !x.ends_with("13") => format!("{x}rd"),
x => format!("{x}th parameter"), x => format!("{x}th"),
}; };
let format_index = |index: usize| if index == 0 { "primary".to_string() } else { format!("{} parameter", ordinal(index - 1)) }; let format_index = |index: usize| if index == 0 { "primary".to_string() } else { format!("{} parameter", ordinal(index)) };
let format_error = |(index, (real, expected)): &(usize, (Type, Type))| format!("• The {} input expected {} but found {}", format_index(*index), expected, real); let format_error = |(index, (real, expected)): &(usize, (Type, Type))| format!("• The {} input expected {} but found {}", format_index(*index), expected, real);
let format_error_list = |errors: &Vec<(usize, (Type, Type))>| errors.iter().map(format_error).collect::<Vec<_>>().join("\n"); let format_error_list = |errors: &Vec<(usize, (Type, Type))>| errors.iter().map(format_error).collect::<Vec<_>>().join("\n");
let errors = error_inputs.iter().map(format_error_list).collect::<Vec<_>>(); let errors = error_inputs.iter().map(format_error_list).collect::<Vec<_>>();
write!( write!(
f, f,
"Node graph type error! If this just appeared while editing the graph,\n\ "Node graph type error! If this just appeared while editing the graph,\n\
consider using undo to go back and trying another way to connect the nodes.\n\ consider using undo to go back and try another way to connect the nodes.\n\
\n\ \n\
No node implementation exists for type ({parameters}).\n\ No node implementation exists for type ({parameters}).\n\
\n\ \n\