Skip to content

Commit a8e209e

Browse files
authored
Remove the old node macro and fix/clean up several raster nodes (#2650)
* Fix several broken raster nodes and clean up leftover old node system code * Migrate Brightness/Contrast to the new node macro, and fix it * Remove last usages of old_node_fn * Remove old_node_fn
1 parent 77f8bfd commit a8e209e

File tree

17 files changed

+505
-1417
lines changed

17 files changed

+505
-1417
lines changed

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

Lines changed: 36 additions & 216 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use graph_craft::document::value::*;
1616
use graph_craft::document::*;
1717
use graphene_core::raster::brush_cache::BrushCache;
1818
use graphene_core::raster::image::ImageFrameTable;
19-
use graphene_core::raster::{CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, NoiseType, RedGreenBlue, RedGreenBlueAlpha};
19+
use graphene_core::raster::{CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, NoiseType, RedGreenBlueAlpha};
2020
use graphene_core::text::{Font, TypesettingConfig};
2121
use graphene_core::transform::Footprint;
2222
use graphene_core::vector::VectorDataTable;
@@ -94,30 +94,35 @@ static DOCUMENT_NODE_TYPES: once_cell::sync::Lazy<Vec<DocumentNodeDefinition>> =
9494
/// The [`DocumentNode`] is the instance while these [`DocumentNodeDefinition`]s are the "classes" or "blueprints" from which the instances are built.
9595
fn static_nodes() -> Vec<DocumentNodeDefinition> {
9696
let mut custom = vec![
97+
// TODO: Auto-generate this from its proto node macro
9798
DocumentNodeDefinition {
98-
identifier: "Default Network",
99+
identifier: "Identity",
99100
category: "General",
100101
node_template: NodeTemplate {
101102
document_node: DocumentNode {
102-
implementation: DocumentNodeImplementation::Network(NodeNetwork::default()),
103+
implementation: DocumentNodeImplementation::proto("graphene_core::ops::IdentityNode"),
104+
inputs: vec![NodeInput::value(TaggedValue::None, true)],
103105
..Default::default()
104106
},
105107
persistent_node_metadata: DocumentNodePersistentMetadata {
106-
network_metadata: Some(NodeNetworkMetadata::default()),
108+
input_properties: vec![("In", "TODO").into()],
109+
output_names: vec!["Out".to_string()],
107110
..Default::default()
108111
},
109112
},
110-
description: Cow::Borrowed("A default node network you can use to create your own custom nodes."),
111-
properties: None,
113+
description: Cow::Borrowed("Passes-through the input value without changing it. This is useful for rerouting wires for organization purposes."),
114+
properties: Some("identity_properties"),
112115
},
113116
// TODO: Auto-generate this from its proto node macro
114117
DocumentNodeDefinition {
115-
identifier: "Identity",
116-
category: "General",
118+
identifier: "Monitor",
119+
category: "Debug",
117120
node_template: NodeTemplate {
118121
document_node: DocumentNode {
119-
implementation: DocumentNodeImplementation::proto("graphene_core::ops::IdentityNode"),
122+
implementation: DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode"),
120123
inputs: vec![NodeInput::value(TaggedValue::None, true)],
124+
manual_composition: Some(generic!(T)),
125+
skip_deduplication: true,
121126
..Default::default()
122127
},
123128
persistent_node_metadata: DocumentNodePersistentMetadata {
@@ -126,8 +131,24 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
126131
..Default::default()
127132
},
128133
},
129-
description: Cow::Borrowed("Passes-through the input value without changing it. This is useful for rerouting wires for organization purposes."),
130-
properties: Some("identity_properties"),
134+
description: Cow::Borrowed("The Monitor node is used by the editor to access the data flowing through it."),
135+
properties: Some("monitor_properties"),
136+
},
137+
DocumentNodeDefinition {
138+
identifier: "Default Network",
139+
category: "General",
140+
node_template: NodeTemplate {
141+
document_node: DocumentNode {
142+
implementation: DocumentNodeImplementation::Network(NodeNetwork::default()),
143+
..Default::default()
144+
},
145+
persistent_node_metadata: DocumentNodePersistentMetadata {
146+
network_metadata: Some(NodeNetworkMetadata::default()),
147+
..Default::default()
148+
},
149+
},
150+
description: Cow::Borrowed("A default node network you can use to create your own custom nodes."),
151+
properties: None,
131152
},
132153
DocumentNodeDefinition {
133154
identifier: "Cache",
@@ -210,27 +231,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
210231
description: Cow::Borrowed("TODO"),
211232
properties: None,
212233
},
213-
// TODO: Auto-generate this from its proto node macro
214-
DocumentNodeDefinition {
215-
identifier: "Monitor",
216-
category: "Debug",
217-
node_template: NodeTemplate {
218-
document_node: DocumentNode {
219-
implementation: DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode"),
220-
inputs: vec![NodeInput::value(TaggedValue::None, true)],
221-
manual_composition: Some(generic!(T)),
222-
skip_deduplication: true,
223-
..Default::default()
224-
},
225-
persistent_node_metadata: DocumentNodePersistentMetadata {
226-
input_properties: vec![("In", "TODO").into()],
227-
output_names: vec!["Out".to_string()],
228-
..Default::default()
229-
},
230-
},
231-
description: Cow::Borrowed("The Monitor node is used by the editor to access the data flowing through it."),
232-
properties: Some("monitor_properties"),
233-
},
234234
DocumentNodeDefinition {
235235
identifier: "Merge",
236236
category: "General",
@@ -837,92 +837,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
837837
description: Cow::Borrowed("Generates different noise patterns."),
838838
properties: None,
839839
},
840-
// TODO: This needs to work with resolution-aware data.
841-
// TODO: Auto-generate this from its proto node macro
842-
DocumentNodeDefinition {
843-
identifier: "Mask",
844-
category: "Raster",
845-
node_template: NodeTemplate {
846-
document_node: DocumentNode {
847-
implementation: DocumentNodeImplementation::proto("graphene_std::raster::MaskImageNode"),
848-
inputs: vec![
849-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
850-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
851-
],
852-
manual_composition: Some(generic!(T)),
853-
..Default::default()
854-
},
855-
persistent_node_metadata: DocumentNodePersistentMetadata {
856-
input_properties: vec![
857-
("Image", "TODO").into(),
858-
PropertiesRow::with_override("Stencil", "TODO", WidgetOverride::Custom("mask_stencil".to_string())),
859-
],
860-
output_names: vec!["Image".to_string()],
861-
..Default::default()
862-
},
863-
},
864-
description: Cow::Borrowed("TODO"),
865-
properties: None,
866-
},
867-
// TODO: This needs to work with resolution-aware data.
868-
// TODO: Auto-generate this from its proto node macro
869-
DocumentNodeDefinition {
870-
identifier: "Insert Channel",
871-
category: "Raster",
872-
node_template: NodeTemplate {
873-
document_node: DocumentNode {
874-
implementation: DocumentNodeImplementation::proto("graphene_std::raster::InsertChannelNode"),
875-
inputs: vec![
876-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
877-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
878-
NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::default()), false),
879-
],
880-
..Default::default()
881-
},
882-
persistent_node_metadata: DocumentNodePersistentMetadata {
883-
input_properties: vec![
884-
("Image", "TODO").into(),
885-
PropertiesRow::with_override("Insertion", "TODO", WidgetOverride::Hidden),
886-
("Into", "TODO").into(),
887-
],
888-
output_names: vec!["Image".to_string()],
889-
..Default::default()
890-
},
891-
},
892-
description: Cow::Borrowed("TODO"),
893-
properties: None,
894-
},
895-
// TODO: This needs to work with resolution-aware data.
896-
DocumentNodeDefinition {
897-
identifier: "Combine Channels",
898-
category: "Raster",
899-
node_template: NodeTemplate {
900-
document_node: DocumentNode {
901-
implementation: DocumentNodeImplementation::proto("graphene_std::raster::CombineChannelsNode"),
902-
inputs: vec![
903-
NodeInput::value(TaggedValue::None, false),
904-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
905-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
906-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
907-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
908-
],
909-
..Default::default()
910-
},
911-
persistent_node_metadata: DocumentNodePersistentMetadata {
912-
input_properties: vec![
913-
("None", "TODO").into(),
914-
("Red", "TODO").into(),
915-
("Green", "TODO").into(),
916-
("Blue", "TODO").into(),
917-
("Alpha", "TODO").into(),
918-
],
919-
output_names: vec!["Image".to_string()],
920-
..Default::default()
921-
},
922-
},
923-
description: Cow::Borrowed("TODO"),
924-
properties: None,
925-
},
926840
DocumentNodeDefinition {
927841
identifier: "Split Channels",
928842
category: "Raster",
@@ -1937,28 +1851,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
19371851
description: Cow::Borrowed("TODO"),
19381852
properties: None,
19391853
},
1940-
#[cfg(feature = "gpu")]
1941-
DocumentNodeDefinition {
1942-
identifier: "GPU Image",
1943-
category: "Debug: GPU",
1944-
node_template: NodeTemplate {
1945-
document_node: DocumentNode {
1946-
implementation: DocumentNodeImplementation::proto("graphene_std::executor::MapGpuSingleImageNode"),
1947-
inputs: vec![
1948-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
1949-
NodeInput::value(TaggedValue::DocumentNode(DocumentNode::default()), true),
1950-
],
1951-
..Default::default()
1952-
},
1953-
persistent_node_metadata: DocumentNodePersistentMetadata {
1954-
input_properties: vec![("Image", "TODO").into(), ("Node", "TODO").into()],
1955-
output_names: vec!["Image".to_string()],
1956-
..Default::default()
1957-
},
1958-
},
1959-
description: Cow::Borrowed("TODO"),
1960-
properties: None,
1961-
},
19621854
DocumentNodeDefinition {
19631855
identifier: "Extract",
19641856
category: "Debug",
@@ -1977,40 +1869,12 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
19771869
description: Cow::Borrowed("TODO"),
19781870
properties: None,
19791871
},
1980-
DocumentNodeDefinition {
1981-
// Aims for interoperable compatibility with:
1982-
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27brit%27%20%3D%20Brightness/Contrast
1983-
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Padding-,Brightness%20and%20Contrast,-Key%20is%20%27brit
1984-
identifier: "Brightness/Contrast",
1985-
category: "Raster: Adjustment",
1986-
node_template: NodeTemplate {
1987-
document_node: DocumentNode {
1988-
implementation: DocumentNodeImplementation::proto("graphene_core::raster::BrightnessContrastNode"),
1989-
inputs: vec![
1990-
NodeInput::value(TaggedValue::ImageFrame(ImageFrameTable::one_empty_image()), true),
1991-
NodeInput::value(TaggedValue::F64(0.), false),
1992-
NodeInput::value(TaggedValue::F64(0.), false),
1993-
NodeInput::value(TaggedValue::Bool(false), false),
1994-
],
1995-
..Default::default()
1996-
},
1997-
persistent_node_metadata: DocumentNodePersistentMetadata {
1998-
input_properties: vec![
1999-
("Image", "TODO").into(),
2000-
PropertiesRow::with_override("Brightness", "TODO", WidgetOverride::Custom("brightness".to_string())),
2001-
PropertiesRow::with_override("Brightness", "TODO", WidgetOverride::Custom("contrast".to_string())),
2002-
("Use Classic", "TODO").into(),
2003-
],
2004-
output_names: vec!["Image".to_string()],
2005-
..Default::default()
2006-
},
2007-
},
2008-
description: Cow::Borrowed("TODO"),
2009-
properties: None,
2010-
},
20111872
// Aims for interoperable compatibility with:
20121873
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=levl%27%20%3D%20Levels-,%27curv%27%20%3D%20Curves,-%27expA%27%20%3D%20Exposure
20131874
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Max%20input%20range-,Curves,-Curves%20settings%20files
1875+
//
1876+
// Some further analysis available at:
1877+
// https://geraldbakker.nl/psnumbers/curves.html
20141878
// TODO: Fix this, it's currently broken
20151879
// DocumentNodeDefinition {
20161880
// identifier: "Curves",
@@ -2034,51 +1898,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
20341898
// properties: None,
20351899
// },
20361900
// (*IMAGINATE_NODE).clone(),
2037-
DocumentNodeDefinition {
2038-
identifier: "Line",
2039-
category: "Vector: Shape",
2040-
node_template: NodeTemplate {
2041-
document_node: DocumentNode {
2042-
implementation: DocumentNodeImplementation::proto("graphene_core::vector::generator_nodes::LineNode"),
2043-
manual_composition: Some(concrete!(Context)),
2044-
inputs: vec![
2045-
NodeInput::value(TaggedValue::None, false),
2046-
NodeInput::value(TaggedValue::DVec2(DVec2::new(0., -50.)), false),
2047-
NodeInput::value(TaggedValue::DVec2(DVec2::new(0., 50.)), false),
2048-
],
2049-
..Default::default()
2050-
},
2051-
persistent_node_metadata: DocumentNodePersistentMetadata {
2052-
input_properties: vec![
2053-
("None", "TODO").into(),
2054-
PropertiesRow::with_override(
2055-
"Start",
2056-
"TODO",
2057-
WidgetOverride::Vec2(Vec2InputSettings {
2058-
x: "X".to_string(),
2059-
y: "Y".to_string(),
2060-
unit: " px".to_string(),
2061-
..Default::default()
2062-
}),
2063-
),
2064-
PropertiesRow::with_override(
2065-
"End",
2066-
"TODO",
2067-
WidgetOverride::Vec2(Vec2InputSettings {
2068-
x: "X".to_string(),
2069-
y: "Y".to_string(),
2070-
unit: " px".to_string(),
2071-
..Default::default()
2072-
}),
2073-
),
2074-
],
2075-
output_names: vec!["Vector".to_string()],
2076-
..Default::default()
2077-
},
2078-
},
2079-
description: Cow::Borrowed("TODO"),
2080-
properties: None,
2081-
},
20821901
DocumentNodeDefinition {
20831902
identifier: "Path",
20841903
category: "Vector",
@@ -2948,6 +2767,7 @@ pub static NODE_OVERRIDES: once_cell::sync::Lazy<NodeProperties> = once_cell::sy
29482767
/// Defines the logic for inputs to display a custom properties panel widget.
29492768
fn static_node_properties() -> NodeProperties {
29502769
let mut map: NodeProperties = HashMap::new();
2770+
map.insert("brightness_contrast_properties".to_string(), Box::new(node_properties::brightness_contrast_properties));
29512771
map.insert("channel_mixer_properties".to_string(), Box::new(node_properties::channel_mixer_properties));
29522772
map.insert("fill_properties".to_string(), Box::new(node_properties::fill_properties));
29532773
map.insert("stroke_properties".to_string(), Box::new(node_properties::stroke_properties));

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ pub(crate) fn property_from_type(
164164
Some("IntegerCount") => number_widget(default_info, number_input.int().min(min(1.))).into(),
165165
Some("SeedValue") => number_widget(default_info, number_input.int().min(min(0.))).into(),
166166
Some("Resolution") => vector2_widget(default_info, "W", "H", " px", Some(64.)),
167+
Some("PixelSize") => vector2_widget(default_info, "X", "Y", " px", None),
167168

168169
// For all other types, use TypeId-based matching
169170
_ => {
@@ -967,6 +968,56 @@ pub fn query_assign_colors_randomize(node_id: NodeId, context: &NodePropertiesCo
967968
})
968969
}
969970

971+
pub(crate) fn brightness_contrast_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
972+
let document_node = match get_document_node(node_id, context) {
973+
Ok(document_node) => document_node,
974+
Err(err) => {
975+
log::error!("Could not get document node in brightness_contrast_properties: {err}");
976+
return Vec::new();
977+
}
978+
};
979+
980+
// Use Classic
981+
let use_classic_index = 3;
982+
let use_classic = bool_widget(ParameterWidgetsInfo::from_index(document_node, node_id, use_classic_index, true, context), CheckboxInput::default());
983+
let use_classic_value = match document_node.inputs[use_classic_index].as_value() {
984+
Some(TaggedValue::Bool(use_classic_choice)) => *use_classic_choice,
985+
_ => false,
986+
};
987+
988+
// Brightness
989+
let brightness_index = 1;
990+
let brightness = number_widget(
991+
ParameterWidgetsInfo::from_index(document_node, node_id, brightness_index, true, context),
992+
NumberInput::default()
993+
.unit("%")
994+
.mode_range()
995+
.display_decimal_places(2)
996+
.range_min(Some(if use_classic_value { -100. } else { -150. }))
997+
.range_max(Some(if use_classic_value { 100. } else { 150. })),
998+
);
999+
1000+
// Contrast
1001+
let contrast_index = 2;
1002+
let contrast = number_widget(
1003+
ParameterWidgetsInfo::from_index(document_node, node_id, contrast_index, true, context),
1004+
NumberInput::default()
1005+
.unit("%")
1006+
.mode_range()
1007+
.display_decimal_places(2)
1008+
.range_min(Some(if use_classic_value { -100. } else { -50. }))
1009+
.range_max(Some(100.)),
1010+
);
1011+
1012+
let layout = vec![
1013+
LayoutGroup::Row { widgets: brightness },
1014+
LayoutGroup::Row { widgets: contrast },
1015+
LayoutGroup::Row { widgets: use_classic },
1016+
];
1017+
1018+
layout
1019+
}
1020+
9701021
pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
9711022
let document_node = match get_document_node(node_id, context) {
9721023
Ok(document_node) => document_node,

0 commit comments

Comments
 (0)