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
10 changed files with 445 additions and 65 deletions
@@ -1353,7 +1353,7 @@ impl DocumentMessageHandler {
.max(100.)
.range_min(Some(0.))
.range_max(Some(100.))
.mode(NumberInputMode::Range)
.mode_range()
.on_update(|number_input: &NumberInput| {
if let Some(value) = number_input.value {
DocumentMessage::SetOpacityForSelectedLayers { opacity: value / 100. }.into()
@@ -190,7 +190,6 @@ impl<'a> ModifyInputsContext<'a> {
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())
};
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 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();
@@ -201,10 +200,8 @@ impl<'a> ModifyInputsContext<'a> {
self.insert_node_before(fill_id, stroke_id, 0, fill, IVec2::new(-8, 0));
let transform_id = NodeId(generate_uuid());
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());
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 });
}
@@ -218,7 +215,6 @@ impl<'a> ModifyInputsContext<'a> {
],
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 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();
@@ -229,10 +225,8 @@ impl<'a> ModifyInputsContext<'a> {
self.insert_node_before(fill_id, stroke_id, 0, fill, IVec2::new(-8, 0));
let transform_id = NodeId(generate_uuid());
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());
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 });
}
@@ -241,15 +235,14 @@ impl<'a> ModifyInputsContext<'a> {
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())
};
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_id = NodeId(generate_uuid());
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());
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 });
}
@@ -264,6 +264,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
manual_composition: Some(concrete!(Footprint)),
..Default::default()
},
// TODO: Does this need an internal Cull node to be added to its implementation?
DocumentNodeDefinition {
name: "Input Frame",
category: "Ignore",
@@ -285,7 +286,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
category: "Structural",
implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
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")),
..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()
.enumerate()
@@ -562,7 +570,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Image Frame",
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![
DocumentInputType::value("Image", TaggedValue::Image(Image::empty()), true),
DocumentInputType::value("Transform", TaggedValue::DAffine2(DAffine2::IDENTITY), true),
@@ -574,7 +605,64 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Noise Pattern",
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![
DocumentInputType::value("None", TaggedValue::None, false),
// All
@@ -601,6 +689,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
properties: node_properties::noise_pattern_properties,
..Default::default()
},
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition {
name: "Mask",
category: "Image Adjustments",
@@ -613,6 +702,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
properties: node_properties::mask_properties,
..Default::default()
},
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition {
name: "Insert Channel",
category: "Image Adjustments",
@@ -626,6 +716,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
properties: node_properties::insert_channel_properties,
..Default::default()
},
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition {
name: "Combine Channels",
category: "Image Adjustments",
@@ -643,6 +734,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}],
..Default::default()
},
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition {
name: "Blend",
category: "Image Adjustments",
@@ -871,7 +963,35 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "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![
DocumentInputType::value("Background", TaggedValue::ImageFrame(ImageFrame::empty()), true),
DocumentInputType::value("Bounds", TaggedValue::ImageFrame(ImageFrame::empty()), true),
@@ -907,7 +1027,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Image",
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)],
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
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 {
name: "Circle",
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)],
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
properties: node_properties::circle_properties,
@@ -2022,7 +2188,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Ellipse",
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![
DocumentInputType::none(),
DocumentInputType::value("Radius X", TaggedValue::F32(50.), false),
@@ -2035,7 +2224,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Rectangle",
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![
DocumentInputType::none(),
DocumentInputType::value("Size X", TaggedValue::F32(100.), false),
@@ -2048,7 +2260,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Regular Polygon",
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![
DocumentInputType::none(),
DocumentInputType::value("Sides", TaggedValue::U32(6), false),
@@ -2061,7 +2296,35 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Star",
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![
DocumentInputType::none(),
DocumentInputType::value("Sides", TaggedValue::U32(5), false),
@@ -2075,7 +2338,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Line",
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![
DocumentInputType::none(),
DocumentInputType::value("Start", TaggedValue::DVec2(DVec2::new(0., -50.)), false),
@@ -2088,7 +2374,30 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Spline",
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![
DocumentInputType::none(),
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 {
name: "Shape",
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![
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),
],
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)],
@@ -2139,10 +2473,38 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNodeDefinition {
name: "Text",
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![
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("Size", TaggedValue::F64(24.), false),
],
@@ -2312,6 +2674,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
properties: node_properties::node_no_properties,
..Default::default()
},
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
DocumentNodeDefinition {
name: "Image Segmentation",
category: "Image Adjustments",
@@ -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> {
let input_shadows = number_widget(document_node, node_id, 1, "Shadows", NumberInput::default().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_highlights = number_widget(document_node, node_id, 3, "Highlights", NumberInput::default().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_maximums = number_widget(document_node, node_id, 5, "Output Maximums", 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().mode_range().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().mode_range().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![
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.;
// 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 r_weight = number_widget(document_node, node_id, 2, "Reds", NumberInput::default().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 g_weight = number_widget(document_node, node_id, 4, "Greens", NumberInput::default().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 b_weight = number_widget(document_node, node_id, 6, "Blues", NumberInput::default().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 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().mode_range().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().mode_range().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().mode_range().min(MIN).max(MAX).unit("%"), true);
vec![
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> {
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 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 }]
}
@@ -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> {
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 lightness_shift = number_widget(document_node, node_id, 3, "Lightness 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().mode_range().min(-100.).max(100.).unit("%"), true);
vec![
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> {
let thereshold_min = number_widget(document_node, node_id, 1, "Min Luminance", NumberInput::default().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_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().mode_range().min(0.).max(100.).unit("%"), 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]
}
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 }]
}
@@ -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::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 green = number_widget(document_node, node_id, g.0, g.1, NumberInput::default().min(-200.).max(200.).value(Some(g.2)).unit("%"), true);
let blue = number_widget(document_node, node_id, b.0, b.1, NumberInput::default().min(-200.).max(200.).value(Some(b.2)).unit("%"), true);
let constant = number_widget(document_node, node_id, c.0, c.1, NumberInput::default().min(-200.).max(200.).value(Some(c.2)).unit("%"), true);
let red = number_widget(
document_node,
node_id,
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
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::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 magenta = number_widget(document_node, node_id, m.0, m.1, NumberInput::default().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 black = number_widget(document_node, node_id, k.0, k.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().mode_range().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().mode_range().min(-100.).max(100.).unit("%"), true);
// Mode
let mode_index = 1;
@@ -420,14 +420,11 @@ fn new_brush_layer(document: &DocumentMessageHandler, responses: &mut VecDeque<M
let brush_node = resolve_document_node_type("Brush")
.expect("Brush node does not exist")
.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());
responses.add(GraphOperationMessage::NewCustomLayer {
id,
nodes: HashMap::from([(NodeId(1), brush_node), (NodeId(0), cull_node)]),
nodes: HashMap::from([(NodeId(0), brush_node)]),
parent: document.new_layer_parent(),
insert_index: -1,
});