mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 07:18:04 +08:00
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
This commit is contained in:
@@ -15,7 +15,7 @@ use graph_craft::document::value::*;
|
||||
use graph_craft::document::*;
|
||||
use graphene_core::raster::brush_cache::BrushCache;
|
||||
use graphene_core::raster::image::ImageFrameTable;
|
||||
use graphene_core::raster::{Color, RedGreenBlue, RedGreenBlueAlpha};
|
||||
use graphene_core::raster::{CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, NoiseType, RedGreenBlue, RedGreenBlueAlpha};
|
||||
use graphene_core::text::{Font, TypesettingConfig};
|
||||
use graphene_core::transform::Footprint;
|
||||
use graphene_core::vector::VectorDataTable;
|
||||
@@ -128,6 +128,87 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
description: Cow::Borrowed("Passes-through the input value without changing it. This is useful for rerouting wires for organization purposes."),
|
||||
properties: Some("identity_properties"),
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
identifier: "Cache",
|
||||
category: "General",
|
||||
node_template: NodeTemplate {
|
||||
document_node: DocumentNode {
|
||||
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
||||
exports: vec![NodeInput::node(NodeId(2), 0)],
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::network(generic!(T), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode")),
|
||||
manual_composition: Some(generic!(T)),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::transform::FreezeRealTimeNode")),
|
||||
manual_composition: Some(generic!(T)),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::node(NodeId(1), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::transform::BoundlessFootprintNode")),
|
||||
manual_composition: Some(generic!(T)),
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, node)| (NodeId(id as u64), node))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![NodeInput::value(TaggedValue::None, true)],
|
||||
..Default::default()
|
||||
},
|
||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||
network_metadata: Some(NodeNetworkMetadata {
|
||||
persistent_metadata: NodeNetworkPersistentMetadata {
|
||||
node_metadata: [
|
||||
DocumentNodeMetadata {
|
||||
persistent_metadata: DocumentNodePersistentMetadata {
|
||||
display_name: "Memoize".to_string(),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeMetadata {
|
||||
persistent_metadata: DocumentNodePersistentMetadata {
|
||||
display_name: "Freeze Real Time".to_string(),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(7, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeMetadata {
|
||||
persistent_metadata: DocumentNodePersistentMetadata {
|
||||
display_name: "Boundless Footprint".to_string(),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(14, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, node)| (NodeId(id as u64), node))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}),
|
||||
input_properties: vec![("Data", "TODO").into()],
|
||||
output_names: vec!["Data".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
description: Cow::Borrowed("TODO"),
|
||||
properties: None,
|
||||
},
|
||||
// TODO: Auto-generate this from its proto node macro
|
||||
DocumentNodeDefinition {
|
||||
identifier: "Monitor",
|
||||
@@ -716,6 +797,87 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
description: Cow::Borrowed("Rasterizes the given vector data"),
|
||||
properties: None,
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
identifier: "Noise Pattern",
|
||||
category: "Raster",
|
||||
node_template: NodeTemplate {
|
||||
document_node: DocumentNode {
|
||||
manual_composition: Some(concrete!(Context)),
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::raster::NoisePatternNode")),
|
||||
inputs: vec![
|
||||
NodeInput::value(TaggedValue::None, false),
|
||||
NodeInput::value(TaggedValue::Bool(true), false),
|
||||
NodeInput::value(TaggedValue::U32(0), false),
|
||||
NodeInput::value(TaggedValue::F64(10.), false),
|
||||
NodeInput::value(TaggedValue::NoiseType(NoiseType::default()), false),
|
||||
NodeInput::value(TaggedValue::DomainWarpType(DomainWarpType::default()), false),
|
||||
NodeInput::value(TaggedValue::F64(100.), false),
|
||||
NodeInput::value(TaggedValue::FractalType(FractalType::default()), false),
|
||||
NodeInput::value(TaggedValue::U32(3), false),
|
||||
NodeInput::value(TaggedValue::F64(2.), false),
|
||||
NodeInput::value(TaggedValue::F64(0.5), false),
|
||||
NodeInput::value(TaggedValue::F64(0.), false), // 0-1 range
|
||||
NodeInput::value(TaggedValue::F64(2.), false),
|
||||
NodeInput::value(TaggedValue::CellularDistanceFunction(CellularDistanceFunction::default()), false),
|
||||
NodeInput::value(TaggedValue::CellularReturnType(CellularReturnType::default()), false),
|
||||
NodeInput::value(TaggedValue::F64(1.), false),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||
input_properties: vec![
|
||||
("Spacer", "TODO").into(),
|
||||
("Clip", "TODO").into(),
|
||||
("Seed", "TODO").into(),
|
||||
PropertiesRow::with_override("Scale", "TODO", WidgetOverride::Custom("noise_properties_scale".to_string())),
|
||||
PropertiesRow::with_override("Noise Type", "TODO", WidgetOverride::Custom("noise_properties_noise_type".to_string())),
|
||||
PropertiesRow::with_override("Domain Warp Type", "TODO", WidgetOverride::Custom("noise_properties_domain_warp_type".to_string())),
|
||||
PropertiesRow::with_override("Domain Warp Amplitude", "TODO", WidgetOverride::Custom("noise_properties_domain_warp_amplitude".to_string())),
|
||||
PropertiesRow::with_override("Fractal Type", "TODO", WidgetOverride::Custom("noise_properties_fractal_type".to_string())),
|
||||
PropertiesRow::with_override("Fractal Octaves", "TODO", WidgetOverride::Custom("noise_properties_fractal_octaves".to_string())),
|
||||
PropertiesRow::with_override("Fractal Lacunarity", "TODO", WidgetOverride::Custom("noise_properties_fractal_lacunarity".to_string())),
|
||||
PropertiesRow::with_override("Fractal Gain", "TODO", WidgetOverride::Custom("noise_properties_fractal_gain".to_string())),
|
||||
PropertiesRow::with_override("Fractal Weighted Strength", "TODO", WidgetOverride::Custom("noise_properties_fractal_weighted_strength".to_string())),
|
||||
PropertiesRow::with_override("Fractal Ping Pong Strength", "TODO", WidgetOverride::Custom("noise_properties_ping_pong_strength".to_string())),
|
||||
PropertiesRow::with_override("Cellular Distance Function", "TODO", WidgetOverride::Custom("noise_properties_cellular_distance_function".to_string())),
|
||||
PropertiesRow::with_override("Cellular Return Type", "TODO", WidgetOverride::Custom("noise_properties_cellular_return_type".to_string())),
|
||||
PropertiesRow::with_override("Cellular Jitter", "TODO", WidgetOverride::Custom("noise_properties_cellular_jitter".to_string())),
|
||||
],
|
||||
output_names: vec!["Image".to_string()],
|
||||
network_metadata: Some(NodeNetworkMetadata {
|
||||
persistent_metadata: NodeNetworkPersistentMetadata {
|
||||
node_metadata: [
|
||||
DocumentNodeMetadata {
|
||||
persistent_metadata: DocumentNodePersistentMetadata {
|
||||
display_name: "Noise Pattern".to_string(),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeMetadata {
|
||||
persistent_metadata: DocumentNodePersistentMetadata {
|
||||
display_name: "Cull".to_string(),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, node)| (NodeId(id as u64), node))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
description: Cow::Borrowed("Generates different noise patterns."),
|
||||
properties: None,
|
||||
},
|
||||
// TODO: This needs to work with resolution-aware (raster with footprint, post-Cull node) data.
|
||||
// TODO: Auto-generate this from its proto node macro
|
||||
DocumentNodeDefinition {
|
||||
@@ -3559,7 +3721,7 @@ impl DocumentNodeDefinition {
|
||||
};
|
||||
nested_node_metadata.persistent_metadata.input_properties.resize_with(input_length, PropertiesRow::default);
|
||||
|
||||
//Recurse over all sub nodes if the current node is a network implementation
|
||||
// Recurse over all sub-nodes if the current node is a network implementation
|
||||
let mut current_path = path.clone();
|
||||
current_path.push(current_node);
|
||||
let DocumentNodeImplementation::Network(template_network) = &node_template.document_node.implementation else {
|
||||
|
||||
@@ -54,7 +54,11 @@ pub fn expose_widget(node_id: NodeId, index: usize, data_type: FrontendGraphData
|
||||
ParameterExposeButton::new()
|
||||
.exposed(exposed)
|
||||
.data_type(data_type)
|
||||
.tooltip("Expose this parameter as a node input in the graph")
|
||||
.tooltip(if exposed {
|
||||
"Stop exposing this parameter as a node input in the graph"
|
||||
} else {
|
||||
"Expose this parameter as a node input in the graph"
|
||||
})
|
||||
.on_update(move |_parameter| {
|
||||
Message::Batched(Box::new([
|
||||
NodeGraphMessage::ExposeInput {
|
||||
|
||||
@@ -1141,7 +1141,7 @@ impl NodeNetworkInterface {
|
||||
|
||||
pub fn input_description<'a>(&'a self, node_id: NodeId, index: usize, network_path: &[NodeId]) -> Option<&'a str> {
|
||||
let Some(input_row) = self.input_properties_row(&node_id, index, network_path) else {
|
||||
log::error!("Could not get node_metadata in input_description");
|
||||
log::error!("Could not get input_row in input_description");
|
||||
return None;
|
||||
};
|
||||
let description = input_row.input_description.as_str();
|
||||
@@ -1162,7 +1162,7 @@ impl NodeNetworkInterface {
|
||||
|
||||
pub fn input_metadata(&self, node_id: &NodeId, index: usize, field: &str, network_path: &[NodeId]) -> Option<&Value> {
|
||||
let Some(input_row) = self.input_properties_row(node_id, index, network_path) else {
|
||||
log::error!("Could not get node_metadata in get_input_metadata");
|
||||
log::error!("Could not get input_row in get_input_metadata");
|
||||
return None;
|
||||
};
|
||||
input_row.input_data.get(field)
|
||||
@@ -3781,6 +3781,7 @@ impl NodeNetworkInterface {
|
||||
self.unload_stack_dependents(network_path);
|
||||
}
|
||||
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
/// Keep metadata in sync with the new implementation if this is used by anything other than the upgrade scripts
|
||||
pub fn replace_implementation(&mut self, node_id: &NodeId, network_path: &[NodeId], implementation: DocumentNodeImplementation) {
|
||||
let Some(network) = self.network_mut(network_path) else {
|
||||
|
||||
@@ -862,6 +862,21 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, i + 1), input.clone(), network_path);
|
||||
}
|
||||
}
|
||||
|
||||
if reference == "Instance on Points" && inputs_count == 2 {
|
||||
let node_definition = resolve_document_node_type(reference).unwrap();
|
||||
let new_node_template = node_definition.default_node_template();
|
||||
let document_node = new_node_template.document_node;
|
||||
document.network_interface.replace_implementation(node_id, network_path, document_node.implementation.clone());
|
||||
document
|
||||
.network_interface
|
||||
.replace_implementation_metadata(node_id, network_path, new_node_template.persistent_node_metadata);
|
||||
|
||||
let old_inputs = document.network_interface.replace_inputs(node_id, document_node.inputs.clone(), network_path);
|
||||
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
|
||||
@@ -258,7 +258,7 @@ impl<T: InstanceLayout> InstanceLayout for Instances<T> {
|
||||
}
|
||||
|
||||
let mut rows = self
|
||||
.instances()
|
||||
.instance_ref_iter()
|
||||
.enumerate()
|
||||
.map(|(index, instance)| {
|
||||
vec![
|
||||
|
||||
@@ -293,7 +293,7 @@ impl NodeRuntime {
|
||||
Self::process_graphic_element(&mut self.thumbnail_renders, parent_network_node_id, &io.output, responses, update_thumbnails)
|
||||
// Insert the vector modify if we are dealing with vector data
|
||||
} else if let Some(record) = introspected_data.downcast_ref::<IORecord<Context, VectorDataTable>>() {
|
||||
self.vector_modify.insert(parent_network_node_id, record.output.one_instance().instance.clone());
|
||||
self.vector_modify.insert(parent_network_node_id, record.output.one_instance_ref().instance.clone());
|
||||
} else {
|
||||
log::warn!("failed to downcast monitor node output {parent_network_node_id:?}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user