diff --git a/node-graph/graph-craft/src/document.rs b/node-graph/graph-craft/src/document.rs index 99f48650..d18fc921 100644 --- a/node-graph/graph-craft/src/document.rs +++ b/node-graph/graph-craft/src/document.rs @@ -897,7 +897,8 @@ impl NodeNetwork { for (dep_id, output_index, node_id) in dep_changes { let node = self.nodes.get_mut(&dep_id).expect("Encountered invalid node id"); let len = node.original_location.dependants.len(); - node.original_location.dependants.extend(vec![vec![]; (output_index).max(len) - len]); + // One must be added to the index to find the length because indexing in rust starts from 0. + node.original_location.dependants.extend(vec![vec![]; (output_index + 1).max(len) - len]); // println!("{node_id} {output_index} {}", node.implementation.output_count()); node.original_location.dependants[output_index].push(node_id); } @@ -1061,7 +1062,7 @@ impl NodeNetwork { NodeInput::Node { node_id, output_index, lambda } => { let skip = node.original_location.skip_inputs; nested_node.populate_first_network_input(node_id, output_index, nested_input_index, lambda, node.original_location.inputs(*import_index), skip); - let input_node = self.nodes.get_mut(&node_id).unwrap(); + let input_node = self.nodes.get_mut(&node_id).unwrap_or_else(|| panic!("unable find input node {node_id:?}")); input_node.original_location.dependants[output_index].push(nested_node_id); } NodeInput::Network { import_index, .. } => { diff --git a/node-graph/graphene-cli/src/main.rs b/node-graph/graphene-cli/src/main.rs index f5ac0cde..f37c728d 100644 --- a/node-graph/graphene-cli/src/main.rs +++ b/node-graph/graphene-cli/src/main.rs @@ -78,9 +78,32 @@ fn init_logging() { .unwrap(); } +// Migrations are done in the editor which is unfortunately not available here. +// TODO: remove this and share migrations between the edtior and the CLI. +fn fix_nodes(network: &mut NodeNetwork) { + for node in network.nodes.values_mut() { + match &mut node.implementation { + // Recursively fix + DocumentNodeImplementation::Network(network) => fix_nodes(network), + // This replicates the migration from the editor linked: + // https://github.com/GraphiteEditor/Graphite/blob/d68f91ccca69e90e6d2df78d544d36cd1aaf348e/editor/src/messages/portfolio/portfolio_message_handler.rs#L535 + // Since the CLI doesn't have the document node definitions, a less robust method of just patching the inputs is used. + DocumentNodeImplementation::ProtoNode(proto_node_identifier) + if (proto_node_identifier.name.starts_with("graphene_core::ConstructLayerNode") || proto_node_identifier.name.starts_with("graphene_core::AddArtboardNode")) + && node.inputs.len() < 3 => + { + node.inputs.push(NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath)); + } + _ => {} + } + } +} + fn create_executor(document_string: String, editor_api: Arc) -> Result> { let document: serde_json::Value = serde_json::from_str(&document_string).expect("Failed to parse document"); - let network = serde_json::from_value::(document["network"].clone()).expect("Failed to parse document"); + let mut network = serde_json::from_value::(document["network_interface"]["network"].clone()).expect("Failed to parse document"); + fix_nodes(&mut network); + let wrapped_network = wrap_network_in_scope(network.clone(), editor_api); let compiler = Compiler {}; let protograph = compiler.compile_single(wrapped_network)?; @@ -88,23 +111,31 @@ fn create_executor(document_string: String, editor_api: Arc) -> R Ok(executor) } +// TODO: this is copy pasta from the editor (and does get out of sync) pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc) -> NodeNetwork { network.generate_node_paths(&[]); let inner_network = DocumentNode { implementation: DocumentNodeImplementation::Network(network), - inputs: vec![NodeInput::node(NodeId(0), 1)], + inputs: vec![], ..Default::default() }; + // TODO: Replace with "Output" definition? + // let render_node = resolve_document_node_type("Output") + // .expect("Output node type not found") + // .node_template_input_override(vec![Some(NodeInput::node(NodeId(1), 0)), Some(NodeInput::node(NodeId(0), 1))]) + // .document_node; + let render_node = graph_craft::document::DocumentNode { - inputs: vec![NodeInput::node(NodeId(1), 0), NodeInput::node(NodeId(0), 1)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(2), 0)], implementation: graph_craft::document::DocumentNodeImplementation::Network(NodeNetwork { exports: vec![NodeInput::node(NodeId(2), 0)], nodes: [ DocumentNode { inputs: vec![NodeInput::scope("editor-api")], - implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")), + manual_composition: Some(concrete!(())), + implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("wgpu_executor::CreateGpuSurfaceNode")), skip_deduplication: true, ..Default::default() }, @@ -114,9 +145,11 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc