Skip to content

Commit ac9fb2b

Browse files
authored
Improve instancing nodes (make them output group data, add 'Instance Repeat', fix Flatten Vector Elements click targets, and more) (#2610)
* Improve instancing nodes (make them output group data, add 'Instance Repeat', fix Flatten Vector Elements click targets, and more) * Fix test? * Fix more tests? * Fix moar test?? * Clean up instance method naming
1 parent a29802d commit ac9fb2b

33 files changed

+806
-524
lines changed

demo-artwork/changing-seasons.graphite

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demo-artwork/procedural-string-lights.graphite

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

+164-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use graph_craft::document::value::*;
1515
use graph_craft::document::*;
1616
use graphene_core::raster::brush_cache::BrushCache;
1717
use graphene_core::raster::image::ImageFrameTable;
18-
use graphene_core::raster::{Color, RedGreenBlue, RedGreenBlueAlpha};
18+
use graphene_core::raster::{CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, NoiseType, RedGreenBlue, RedGreenBlueAlpha};
1919
use graphene_core::text::{Font, TypesettingConfig};
2020
use graphene_core::transform::Footprint;
2121
use graphene_core::vector::VectorDataTable;
@@ -128,6 +128,87 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
128128
description: Cow::Borrowed("Passes-through the input value without changing it. This is useful for rerouting wires for organization purposes."),
129129
properties: Some("identity_properties"),
130130
},
131+
DocumentNodeDefinition {
132+
identifier: "Cache",
133+
category: "General",
134+
node_template: NodeTemplate {
135+
document_node: DocumentNode {
136+
implementation: DocumentNodeImplementation::Network(NodeNetwork {
137+
exports: vec![NodeInput::node(NodeId(2), 0)],
138+
nodes: [
139+
DocumentNode {
140+
inputs: vec![NodeInput::network(generic!(T), 0)],
141+
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode")),
142+
manual_composition: Some(generic!(T)),
143+
..Default::default()
144+
},
145+
DocumentNode {
146+
inputs: vec![NodeInput::node(NodeId(0), 0)],
147+
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::transform::FreezeRealTimeNode")),
148+
manual_composition: Some(generic!(T)),
149+
..Default::default()
150+
},
151+
DocumentNode {
152+
inputs: vec![NodeInput::node(NodeId(1), 0)],
153+
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::transform::BoundlessFootprintNode")),
154+
manual_composition: Some(generic!(T)),
155+
..Default::default()
156+
},
157+
]
158+
.into_iter()
159+
.enumerate()
160+
.map(|(id, node)| (NodeId(id as u64), node))
161+
.collect(),
162+
..Default::default()
163+
}),
164+
inputs: vec![NodeInput::value(TaggedValue::None, true)],
165+
..Default::default()
166+
},
167+
persistent_node_metadata: DocumentNodePersistentMetadata {
168+
network_metadata: Some(NodeNetworkMetadata {
169+
persistent_metadata: NodeNetworkPersistentMetadata {
170+
node_metadata: [
171+
DocumentNodeMetadata {
172+
persistent_metadata: DocumentNodePersistentMetadata {
173+
display_name: "Memoize".to_string(),
174+
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
175+
..Default::default()
176+
},
177+
..Default::default()
178+
},
179+
DocumentNodeMetadata {
180+
persistent_metadata: DocumentNodePersistentMetadata {
181+
display_name: "Freeze Real Time".to_string(),
182+
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(7, 0)),
183+
..Default::default()
184+
},
185+
..Default::default()
186+
},
187+
DocumentNodeMetadata {
188+
persistent_metadata: DocumentNodePersistentMetadata {
189+
display_name: "Boundless Footprint".to_string(),
190+
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(14, 0)),
191+
..Default::default()
192+
},
193+
..Default::default()
194+
},
195+
]
196+
.into_iter()
197+
.enumerate()
198+
.map(|(id, node)| (NodeId(id as u64), node))
199+
.collect(),
200+
..Default::default()
201+
},
202+
..Default::default()
203+
}),
204+
input_properties: vec![("Data", "TODO").into()],
205+
output_names: vec!["Data".to_string()],
206+
..Default::default()
207+
},
208+
},
209+
description: Cow::Borrowed("TODO"),
210+
properties: None,
211+
},
131212
// TODO: Auto-generate this from its proto node macro
132213
DocumentNodeDefinition {
133214
identifier: "Monitor",
@@ -716,6 +797,87 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
716797
description: Cow::Borrowed("Rasterizes the given vector data"),
717798
properties: None,
718799
},
800+
DocumentNodeDefinition {
801+
identifier: "Noise Pattern",
802+
category: "Raster",
803+
node_template: NodeTemplate {
804+
document_node: DocumentNode {
805+
manual_composition: Some(concrete!(Context)),
806+
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::raster::NoisePatternNode")),
807+
inputs: vec![
808+
NodeInput::value(TaggedValue::None, false),
809+
NodeInput::value(TaggedValue::Bool(true), false),
810+
NodeInput::value(TaggedValue::U32(0), false),
811+
NodeInput::value(TaggedValue::F64(10.), false),
812+
NodeInput::value(TaggedValue::NoiseType(NoiseType::default()), false),
813+
NodeInput::value(TaggedValue::DomainWarpType(DomainWarpType::default()), false),
814+
NodeInput::value(TaggedValue::F64(100.), false),
815+
NodeInput::value(TaggedValue::FractalType(FractalType::default()), false),
816+
NodeInput::value(TaggedValue::U32(3), false),
817+
NodeInput::value(TaggedValue::F64(2.), false),
818+
NodeInput::value(TaggedValue::F64(0.5), false),
819+
NodeInput::value(TaggedValue::F64(0.), false), // 0-1 range
820+
NodeInput::value(TaggedValue::F64(2.), false),
821+
NodeInput::value(TaggedValue::CellularDistanceFunction(CellularDistanceFunction::default()), false),
822+
NodeInput::value(TaggedValue::CellularReturnType(CellularReturnType::default()), false),
823+
NodeInput::value(TaggedValue::F64(1.), false),
824+
],
825+
..Default::default()
826+
},
827+
persistent_node_metadata: DocumentNodePersistentMetadata {
828+
input_properties: vec![
829+
("Spacer", "TODO").into(),
830+
("Clip", "TODO").into(),
831+
("Seed", "TODO").into(),
832+
PropertiesRow::with_override("Scale", "TODO", WidgetOverride::Custom("noise_properties_scale".to_string())),
833+
PropertiesRow::with_override("Noise Type", "TODO", WidgetOverride::Custom("noise_properties_noise_type".to_string())),
834+
PropertiesRow::with_override("Domain Warp Type", "TODO", WidgetOverride::Custom("noise_properties_domain_warp_type".to_string())),
835+
PropertiesRow::with_override("Domain Warp Amplitude", "TODO", WidgetOverride::Custom("noise_properties_domain_warp_amplitude".to_string())),
836+
PropertiesRow::with_override("Fractal Type", "TODO", WidgetOverride::Custom("noise_properties_fractal_type".to_string())),
837+
PropertiesRow::with_override("Fractal Octaves", "TODO", WidgetOverride::Custom("noise_properties_fractal_octaves".to_string())),
838+
PropertiesRow::with_override("Fractal Lacunarity", "TODO", WidgetOverride::Custom("noise_properties_fractal_lacunarity".to_string())),
839+
PropertiesRow::with_override("Fractal Gain", "TODO", WidgetOverride::Custom("noise_properties_fractal_gain".to_string())),
840+
PropertiesRow::with_override("Fractal Weighted Strength", "TODO", WidgetOverride::Custom("noise_properties_fractal_weighted_strength".to_string())),
841+
PropertiesRow::with_override("Fractal Ping Pong Strength", "TODO", WidgetOverride::Custom("noise_properties_ping_pong_strength".to_string())),
842+
PropertiesRow::with_override("Cellular Distance Function", "TODO", WidgetOverride::Custom("noise_properties_cellular_distance_function".to_string())),
843+
PropertiesRow::with_override("Cellular Return Type", "TODO", WidgetOverride::Custom("noise_properties_cellular_return_type".to_string())),
844+
PropertiesRow::with_override("Cellular Jitter", "TODO", WidgetOverride::Custom("noise_properties_cellular_jitter".to_string())),
845+
],
846+
output_names: vec!["Image".to_string()],
847+
network_metadata: Some(NodeNetworkMetadata {
848+
persistent_metadata: NodeNetworkPersistentMetadata {
849+
node_metadata: [
850+
DocumentNodeMetadata {
851+
persistent_metadata: DocumentNodePersistentMetadata {
852+
display_name: "Noise Pattern".to_string(),
853+
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
854+
..Default::default()
855+
},
856+
..Default::default()
857+
},
858+
DocumentNodeMetadata {
859+
persistent_metadata: DocumentNodePersistentMetadata {
860+
display_name: "Cull".to_string(),
861+
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
862+
..Default::default()
863+
},
864+
..Default::default()
865+
},
866+
]
867+
.into_iter()
868+
.enumerate()
869+
.map(|(id, node)| (NodeId(id as u64), node))
870+
.collect(),
871+
..Default::default()
872+
},
873+
..Default::default()
874+
}),
875+
..Default::default()
876+
},
877+
},
878+
description: Cow::Borrowed("Generates different noise patterns."),
879+
properties: None,
880+
},
719881
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
720882
// TODO: Auto-generate this from its proto node macro
721883
DocumentNodeDefinition {
@@ -3559,7 +3721,7 @@ impl DocumentNodeDefinition {
35593721
};
35603722
nested_node_metadata.persistent_metadata.input_properties.resize_with(input_length, PropertiesRow::default);
35613723

3562-
//Recurse over all sub nodes if the current node is a network implementation
3724+
// Recurse over all sub-nodes if the current node is a network implementation
35633725
let mut current_path = path.clone();
35643726
current_path.push(current_node);
35653727
let DocumentNodeImplementation::Network(template_network) = &node_template.document_node.implementation else {

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ pub fn expose_widget(node_id: NodeId, index: usize, data_type: FrontendGraphData
5454
ParameterExposeButton::new()
5555
.exposed(exposed)
5656
.data_type(data_type)
57-
.tooltip("Expose this parameter as a node input in the graph")
57+
.tooltip(if exposed {
58+
"Stop exposing this parameter as a node input in the graph"
59+
} else {
60+
"Expose this parameter as a node input in the graph"
61+
})
5862
.on_update(move |_parameter| {
5963
Message::Batched(Box::new([
6064
NodeGraphMessage::ExposeInput {

editor/src/messages/portfolio/document/utility_types/network_interface.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,7 @@ impl NodeNetworkInterface {
11411141

11421142
pub fn input_description<'a>(&'a self, node_id: NodeId, index: usize, network_path: &[NodeId]) -> Option<&'a str> {
11431143
let Some(input_row) = self.input_properties_row(&node_id, index, network_path) else {
1144-
log::error!("Could not get node_metadata in input_description");
1144+
log::error!("Could not get input_row in input_description");
11451145
return None;
11461146
};
11471147
let description = input_row.input_description.as_str();
@@ -1162,7 +1162,7 @@ impl NodeNetworkInterface {
11621162

11631163
pub fn input_metadata(&self, node_id: &NodeId, index: usize, field: &str, network_path: &[NodeId]) -> Option<&Value> {
11641164
let Some(input_row) = self.input_properties_row(node_id, index, network_path) else {
1165-
log::error!("Could not get node_metadata in get_input_metadata");
1165+
log::error!("Could not get input_row in get_input_metadata");
11661166
return None;
11671167
};
11681168
input_row.input_data.get(field)
@@ -3781,6 +3781,7 @@ impl NodeNetworkInterface {
37813781
self.unload_stack_dependents(network_path);
37823782
}
37833783

3784+
// TODO: Eventually remove this document upgrade code
37843785
/// Keep metadata in sync with the new implementation if this is used by anything other than the upgrade scripts
37853786
pub fn replace_implementation(&mut self, node_id: &NodeId, network_path: &[NodeId], implementation: DocumentNodeImplementation) {
37863787
let Some(network) = self.network_mut(network_path) else {

editor/src/messages/portfolio/portfolio_message_handler.rs

+15
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,21 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
862862
document.network_interface.set_input(&InputConnector::node(*node_id, i + 1), input.clone(), network_path);
863863
}
864864
}
865+
866+
if reference == "Instance on Points" && inputs_count == 2 {
867+
let node_definition = resolve_document_node_type(reference).unwrap();
868+
let new_node_template = node_definition.default_node_template();
869+
let document_node = new_node_template.document_node;
870+
document.network_interface.replace_implementation(node_id, network_path, document_node.implementation.clone());
871+
document
872+
.network_interface
873+
.replace_implementation_metadata(node_id, network_path, new_node_template.persistent_node_metadata);
874+
875+
let old_inputs = document.network_interface.replace_inputs(node_id, document_node.inputs.clone(), network_path);
876+
877+
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
878+
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
879+
}
865880
}
866881

867882
// TODO: Eventually remove this document upgrade code

editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ impl<T: InstanceLayout> InstanceLayout for Instances<T> {
258258
}
259259

260260
let mut rows = self
261-
.instances()
261+
.instance_ref_iter()
262262
.enumerate()
263263
.map(|(index, instance)| {
264264
vec![

editor/src/node_graph_executor/runtime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ impl NodeRuntime {
293293
Self::process_graphic_element(&mut self.thumbnail_renders, parent_network_node_id, &io.output, responses, update_thumbnails)
294294
// Insert the vector modify if we are dealing with vector data
295295
} else if let Some(record) = introspected_data.downcast_ref::<IORecord<Context, VectorDataTable>>() {
296-
self.vector_modify.insert(parent_network_node_id, record.output.one_instance().instance.clone());
296+
self.vector_modify.insert(parent_network_node_id, record.output.one_instance_ref().instance.clone());
297297
} else {
298298
log::warn!("failed to downcast monitor node output {parent_network_node_id:?}");
299299
}

0 commit comments

Comments
 (0)