Rename NodeNetwork inputs/outputs to imports/exports

This commit is contained in:
Keavon Chambers 2024-03-10 22:45:22 -07:00
parent 137853eb40
commit fd54cda445
17 changed files with 166 additions and 164 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -179,8 +179,8 @@ fn root_network() -> NodeNetwork {
name: "Output".into(),
inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true), NodeInput::Network(concrete!(WasmEditorApi))],
implementation: graph_craft::document::DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(3), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(3), 0)],
imports: vec![NodeId(3), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(3), 0)],
nodes: [
DocumentNode {
name: "EditorApi".to_string(),

View file

@ -269,7 +269,7 @@ impl<'a> ModifyInputsContext<'a> {
/// Inserts a new node and modifies the inputs
fn modify_new_node(&mut self, name: &'static str, update_input: impl FnOnce(&mut Vec<NodeInput>, NodeId, &DocumentMetadata)) {
let output_node_id = self.layer_node.unwrap_or(self.document_network.outputs[0].node_id);
let output_node_id = self.layer_node.unwrap_or(self.document_network.exports[0].node_id);
let Some(output_node) = self.document_network.nodes.get_mut(&output_node_id) else {
warn!("Output node doesn't exist");
return;
@ -302,7 +302,7 @@ impl<'a> ModifyInputsContext<'a> {
.document_network
.upstream_flow_back_from_nodes(
self.layer_node
.map_or_else(|| self.document_network.outputs.iter().map(|output| output.node_id).collect(), |id| vec![id]),
.map_or_else(|| self.document_network.exports.iter().map(|output| output.node_id).collect(), |id| vec![id]),
true,
)
.find(|(node, _)| node.name == name)
@ -327,7 +327,7 @@ impl<'a> ModifyInputsContext<'a> {
.document_network
.upstream_flow_back_from_nodes(
self.layer_node
.map_or_else(|| self.document_network.outputs.iter().map(|output| output.node_id).collect(), |id| vec![id]),
.map_or_else(|| self.document_network.exports.iter().map(|output| output.node_id).collect(), |id| vec![id]),
true,
)
.filter(|(node, _)| node.name == name)

View file

@ -179,7 +179,7 @@ impl NodeGraphMessageHandler {
let mut widgets = Vec::new();
// Don't allow disabling input or output nodes
let mut selection = selected_nodes.selected_nodes().filter(|&&id| !network.inputs.contains(&id) && !network.original_outputs_contain(id));
let mut selection = selected_nodes.selected_nodes().filter(|&&id| !network.imports.contains(&id) && !network.original_outputs_contain(id));
// If there is at least one other selected node then show the hide or show button
if selection.next().is_some() {
@ -422,7 +422,7 @@ impl NodeGraphMessageHandler {
}
fn remove_references_from_network(network: &mut NodeNetwork, deleting_node_id: NodeId, reconnect: bool) -> bool {
if network.inputs.contains(&deleting_node_id) {
if network.imports.contains(&deleting_node_id) {
warn!("Deleting input node!");
return false;
}
@ -959,7 +959,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if let Some(network) = document_network.nested_network_mut(&self.network) {
if !hidden {
network.disabled.retain(|&id| node_id != id);
} else if !network.inputs.contains(&node_id) && !network.original_outputs().iter().any(|output| output.node_id == node_id) {
} else if !network.imports.contains(&node_id) && !network.original_outputs().iter().any(|output| output.node_id == node_id) {
network.disabled.push(node_id);
}
@ -991,10 +991,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if let Some(network) = document_network.nested_network_mut(&self.network) {
// Check if the node is not already being previewed
if !network.outputs_contain(node_id) {
network.previous_outputs = Some(network.previous_outputs.to_owned().unwrap_or_else(|| network.outputs.clone()));
network.outputs[0] = NodeOutput::new(node_id, 0);
network.previous_outputs = Some(network.previous_outputs.to_owned().unwrap_or_else(|| network.exports.clone()));
network.exports[0] = NodeOutput::new(node_id, 0);
} else if let Some(outputs) = network.previous_outputs.take() {
network.outputs = outputs
network.exports = outputs
} else {
return;
}

View file

@ -197,8 +197,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Layer",
category: "General",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(2)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(0), NodeId(2)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
(
NodeId(0),
@ -279,8 +279,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Load Image",
category: "Structural",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "Load Resource".to_string(),
@ -331,8 +331,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Create Canvas",
category: "Structural",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
DocumentNode {
name: "Create Canvas".to_string(),
@ -370,8 +370,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Draw Canvas",
category: "Structural",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(2)],
outputs: vec![NodeOutput::new(NodeId(3), 0)],
imports: vec![NodeId(0), NodeId(2)],
exports: vec![NodeOutput::new(NodeId(3), 0)],
nodes: [
DocumentNode {
name: "Convert Image Frame".to_string(),
@ -429,8 +429,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Begin Scope",
category: "Ignore",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "SetNode".to_string(),
@ -504,8 +504,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Output",
category: "Ignore",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(3), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(4), 0)],
imports: vec![NodeId(3), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(4), 0)],
nodes: [
DocumentNode {
name: "EditorApi".to_string(),
@ -566,8 +566,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Image Frame",
category: "General",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Image Frame".to_string(),
@ -601,7 +601,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Noise Pattern",
category: "General",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![
imports: vec![
NodeId(0),
NodeId(0),
NodeId(0),
@ -619,7 +619,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
NodeId(0),
NodeId(0),
],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Noise Pattern".to_string(),
@ -896,8 +896,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Split Channels",
category: "Image Adjustments",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![
imports: vec![NodeId(0)],
exports: vec![
NodeOutput::new(NodeId(1), 0),
NodeOutput::new(NodeId(2), 0),
NodeOutput::new(NodeId(3), 0),
@ -959,8 +959,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Brush",
category: "Brush",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Brush".to_string(),
@ -1032,8 +1032,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Image",
category: "Ignore",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Identity".to_string(),
@ -1065,8 +1065,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Uniform",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "Extract Executor".to_string(),
@ -1117,8 +1117,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Storage",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "Extract Executor".to_string(),
@ -1169,8 +1169,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "CreateOutputBuffer",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(1), NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(1), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "Extract Executor".to_string(),
@ -1227,8 +1227,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "CreateComputePass",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(1), NodeId(0), NodeId(1), NodeId(1)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(0), NodeId(1), NodeId(1)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "Extract Executor".to_string(),
@ -1329,8 +1329,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "ExecuteComputePipeline",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "Extract Executor".to_string(),
@ -1381,8 +1381,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "ReadOutputBuffer",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "Extract Executor".to_string(),
@ -1433,8 +1433,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "CreateGpuSurface",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
DocumentNode {
name: "Create Gpu Surface".to_string(),
@ -1472,8 +1472,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "RenderTexture",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(1), NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(1), NodeId(1), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
DocumentNode {
name: "Extract Executor".to_string(),
@ -1526,8 +1526,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "UploadTexture",
category: "Gpu",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "Extract Executor".to_string(),
@ -2161,8 +2161,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Circle",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Circle Generator".to_string(),
@ -2193,8 +2193,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Ellipse",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Ellipse Generator".to_string(),
@ -2229,8 +2229,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Rectangle",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Rectangle Generator".to_string(),
@ -2265,8 +2265,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Regular Polygon",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Regular Polygon Generator".to_string(),
@ -2301,8 +2301,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Star",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Star Generator".to_string(),
@ -2343,8 +2343,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Line",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Line Generator".to_string(),
@ -2379,8 +2379,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Spline",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Spline Generator".to_string(),
@ -2414,8 +2414,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Shape",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Path Generator".to_string(),
@ -2478,8 +2478,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Text",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0), NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
DocumentNode {
name: "Text Generator".to_string(),
@ -2520,8 +2520,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Transform",
category: "Transform",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(1), NodeId(1), NodeId(1), NodeId(1), NodeId(1)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(1), NodeId(1), NodeId(1), NodeId(1), NodeId(1)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
DocumentNode {
inputs: vec![NodeInput::Network(concrete!(VectorData))],
@ -2666,8 +2666,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Sample Points",
category: "Vector",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0), NodeId(2), NodeId(2), NodeId(2), NodeId(2)], // First is given to Identity, the rest are given to Sample Points
outputs: vec![NodeOutput::new(NodeId(2), 0)], // Taken from output 0 of Sample Points
imports: vec![NodeId(0), NodeId(2), NodeId(2), NodeId(2), NodeId(2)], // First is given to Identity, the rest are given to Sample Points
exports: vec![NodeOutput::new(NodeId(2), 0)], // Taken from output 0 of Sample Points
nodes: [
DocumentNode {
name: "Identity".to_string(),
@ -2820,7 +2820,7 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentN
name: "Imaginate",
category: "Image Synthesis",
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![
imports: vec![
NodeId(0),
NodeId(1),
NodeId(1),
@ -2839,7 +2839,7 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentN
NodeId(1),
NodeId(1),
],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
(
NodeId(0),
@ -2973,7 +2973,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork
}
}
let len = network_inputs.len();
network.inputs = network_inputs;
network.imports = network_inputs;
// if the network has no inputs, it doesn't need to be wrapped in a scope
if len == 0 {
@ -3007,8 +3007,8 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork
];
NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: nodes.into_iter().enumerate().map(|(id, node)| (NodeId(id as u64), node)).collect(),
..Default::default()
}
@ -3016,7 +3016,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork
pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetwork {
let mut network = NodeNetwork {
inputs: vec![NodeId(0)],
imports: vec![NodeId(0)],
..Default::default()
};
network.push_node(
@ -3040,7 +3040,7 @@ pub fn new_text_network(text: String, font: Font, size: f64) -> NodeNetwork {
let output = resolve_document_node_type("Output").expect("Output node does not exist");
let mut network = NodeNetwork {
inputs: vec![NodeId(0)],
imports: vec![NodeId(0)],
..Default::default()
};
network.push_node(text_generator.to_document_node(

View file

@ -1825,7 +1825,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
.introspect_node_in_network(
context.network,
&imaginate_node,
|network| network.inputs.first().copied(),
|network| network.imports.first().copied(),
|frame: &IORecord<(), ImageFrame<Color>>| (frame.output.image.width, frame.output.image.height),
)
.unwrap_or_default();

View file

@ -141,7 +141,7 @@ impl DocumentMetadata {
self.folders = HashSet::new();
self.artboards = HashSet::new();
let id = graph.outputs[0].node_id;
let id = graph.exports[0].node_id;
let Some(output_node) = graph.nodes.get(&id) else {
return;
};

View file

@ -211,7 +211,7 @@ impl NodeRuntime {
.collect::<Vec<_>>();
// We assume only one output
assert_eq!(scoped_network.outputs.len(), 1, "Graph with multiple outputs not yet handled");
assert_eq!(scoped_network.exports.len(), 1, "Graph with multiple outputs not yet handled");
let c = Compiler {};
let proto_network = match c.compile_single(scoped_network) {
Ok(network) => network,

View file

@ -37,8 +37,8 @@ fn main() {
fn add_network() -> NodeNetwork {
NodeNetwork {
inputs: vec![],
outputs: vec![NodeOutput::new(NodeId(0), 0)],
imports: vec![],
exports: vec![NodeOutput::new(NodeId(0), 0)],
disabled: vec![],
previous_outputs: None,
nodes: [DocumentNode {

View file

@ -514,24 +514,26 @@ impl NodeOutput {
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// A network (subgraph) of nodes containing each [`DocumentNode`] and its ID, as well as a list of input nodes and [`NodeOutput`]s
pub struct NodeNetwork {
/// The list of nodes that are imported into this network from the parent network. Each is a reference to the node that the input is connected to.
/// Presently, only one is supported— use an Identity node to split an input to multiple user nodes (although this could be changed in the future).
pub inputs: Vec<NodeId>,
/// The list of data outputs that are exported from this network to the parent network. Each is a reference to the node, and its output index, that is the source of the output data.
pub outputs: Vec<NodeOutput>,
/// The list of nodes that are imported into this network from the parent network.
/// Each import is a reference to which node within this network that the input is connected to.
/// Presently, only one is supported— use an Identity node to split an input to multiple user nodes (although this could, and should, be changed in the future).
pub imports: Vec<NodeId>,
/// The list of data outputs that are exported from this network to the parent network.
/// Each export is a reference to a node within this network, paired with its output index, that is the source of the network's exported data.
pub exports: Vec<NodeOutput>,
/// The list of all nodes in this network.
pub nodes: HashMap<NodeId, DocumentNode>,
/// Nodes that the user has disabled/hidden with the visibility eye icon.
/// These nodes get replaced with Identity nodes during the graph flattening step.
pub disabled: Vec<NodeId>,
/// In the case when another node is previewed (chosen by the user as a temporary output), this stores what it used to be so it can be restored later.
/// In the case when another node is previewed (chosen by the user as a temporary output), this stores what it previously was so it can be restored later.
pub previous_outputs: Option<Vec<NodeOutput>>,
}
impl std::hash::Hash for NodeNetwork {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inputs.hash(state);
self.outputs.hash(state);
self.imports.hash(state);
self.exports.hash(state);
let mut nodes: Vec<_> = self.nodes.iter().collect();
nodes.sort_by_key(|(id, _)| *id);
for (id, node) in nodes {
@ -553,17 +555,17 @@ impl NodeNetwork {
/// Get the original output nodes of this network, ignoring any preview node
pub fn original_outputs(&self) -> &Vec<NodeOutput> {
self.previous_outputs.as_ref().unwrap_or(&self.outputs)
self.previous_outputs.as_ref().unwrap_or(&self.exports)
}
pub fn input_types(&self) -> impl Iterator<Item = Type> + '_ {
self.inputs.iter().map(move |id| self.nodes[id].inputs.get(0).map(|i| i.ty()).unwrap_or(concrete!(())))
self.imports.iter().map(move |id| self.nodes[id].inputs.get(0).map(|i| i.ty()).unwrap_or(concrete!(())))
}
pub fn value_network(node: DocumentNode) -> Self {
Self {
inputs: node.inputs.iter().filter(|input| matches!(input, NodeInput::Network(_))).map(|_| NodeId(0)).collect(),
outputs: vec![NodeOutput::new(NodeId(0), 0)],
imports: node.inputs.iter().filter(|input| matches!(input, NodeInput::Network(_))).map(|_| NodeId(0)).collect(),
exports: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [(NodeId(0), node)].into_iter().collect(),
disabled: vec![],
previous_outputs: None,
@ -573,8 +575,8 @@ impl NodeNetwork {
/// A graph with just an input node
pub fn new_network() -> Self {
Self {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(0), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [(
NodeId(0),
DocumentNode {
@ -600,8 +602,8 @@ impl NodeNetwork {
node.metadata.position = pos + IVec2::new(8, 0);
}
}
if !self.outputs.is_empty() {
let input = NodeInput::node(self.outputs[0].node_id, self.outputs[0].node_output_index);
if !self.exports.is_empty() {
let input = NodeInput::node(self.exports[0].node_id, self.exports[0].node_output_index);
if node.inputs.is_empty() {
node.inputs.push(input);
} else {
@ -609,7 +611,7 @@ impl NodeNetwork {
}
}
self.nodes.insert(id, node);
self.outputs = vec![NodeOutput::new(id, 0)];
self.exports = vec![NodeOutput::new(id, 0)];
id
}
@ -630,8 +632,8 @@ impl NodeNetwork {
name: "Cache".into(),
inputs: vec![],
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![
(
NodeId(0),
@ -686,13 +688,13 @@ impl NodeNetwork {
/// Check if the specified node id is connected to the output
pub fn connected_to_output(&self, target_node_id: NodeId) -> bool {
// If the node is the output then return true
if self.outputs.iter().any(|&NodeOutput { node_id, .. }| node_id == target_node_id) {
if self.exports.iter().any(|&NodeOutput { node_id, .. }| node_id == target_node_id) {
return true;
}
// Get the outputs
let mut stack = self.outputs.iter().filter_map(|&output| self.nodes.get(&output.node_id)).collect::<Vec<_>>();
let mut stack = self.exports.iter().filter_map(|&output| self.nodes.get(&output.node_id)).collect::<Vec<_>>();
let mut already_visited = HashSet::new();
already_visited.extend(self.outputs.iter().map(|output| output.node_id));
already_visited.extend(self.exports.iter().map(|output| output.node_id));
while let Some(node) = stack.pop() {
for input in &node.inputs {
@ -720,7 +722,7 @@ impl NodeNetwork {
/// Is the node being used directly as an output?
pub fn outputs_contain(&self, node_id: NodeId) -> bool {
self.outputs.iter().any(|output| output.node_id == node_id)
self.exports.iter().any(|output| output.node_id == node_id)
}
/// Is the node being used directly as an original output?
@ -774,8 +776,8 @@ impl NodeNetwork {
pub fn output_as_input(&self, arg: usize) -> NodeInput {
NodeInput::Node {
node_id: self.outputs[arg].node_id,
output_index: self.outputs[arg].node_output_index,
node_id: self.exports[arg].node_id,
output_index: self.exports[arg].node_output_index,
lambda: false,
}
}
@ -811,8 +813,8 @@ impl<'a> Iterator for FlowIter<'a> {
impl NodeNetwork {
/// Replace all references in the graph of a node ID with a new node ID defined by the function `f`.
pub fn map_ids(&mut self, f: impl Fn(NodeId) -> NodeId + Copy) {
self.inputs.iter_mut().for_each(|id| *id = f(*id));
self.outputs.iter_mut().for_each(|output| output.node_id = f(output.node_id));
self.imports.iter_mut().for_each(|id| *id = f(*id));
self.exports.iter_mut().for_each(|output| output.node_id = f(output.node_id));
self.disabled.iter_mut().for_each(|id| *id = f(*id));
self.previous_outputs
.iter_mut()
@ -875,7 +877,7 @@ impl NodeNetwork {
/// Replace all references in any node of `old_output` with `new_output`
fn replace_network_outputs(&mut self, old_output: NodeOutput, new_output: NodeOutput) {
for output in self.outputs.iter_mut() {
for output in self.exports.iter_mut() {
if *output == old_output {
*output = new_output;
}
@ -886,7 +888,7 @@ impl NodeNetwork {
pub fn remove_dead_nodes(&mut self) -> Vec<bool> {
// Take all the nodes out of the nodes list
let mut old_nodes = std::mem::take(&mut self.nodes);
let mut stack = self.outputs.iter().map(|output| output.node_id).collect::<Vec<_>>();
let mut stack = self.exports.iter().map(|output| output.node_id).collect::<Vec<_>>();
while let Some(node_id) = stack.pop() {
let Some((node_id, mut document_node)) = old_nodes.remove_entry(&node_id) else {
continue;
@ -909,9 +911,9 @@ impl NodeNetwork {
}
// Check if inputs are used and store for return value
let are_inputs_used = self.inputs.iter().map(|input| self.nodes.contains_key(input)).collect();
let are_inputs_used = self.imports.iter().map(|input| self.nodes.contains_key(input)).collect();
// Remove unused inputs from graph
self.inputs.retain(|input| self.nodes.contains_key(input));
self.imports.retain(|input| self.nodes.contains_key(input));
are_inputs_used
}
@ -986,21 +988,21 @@ impl NodeNetwork {
let mut network_offsets = HashMap::new();
assert_eq!(
node.inputs.len(),
inner_network.inputs.len(),
inner_network.imports.len(),
"\n\nThe number of inputs to the node and the inner network must be the same for \"{}\". The node has {} inputs, the network has {} inputs.\n\nNode inputs:\n\n{:?}\n\nNetwork inputs:\n\n{:?}\n",
node.name,
node.inputs.len(),
inner_network.inputs.len(),
inner_network.imports.len(),
node.inputs,
inner_network.inputs
inner_network.imports
);
assert_eq!(
node.inputs.len(),
inner_network.inputs.len(),
inner_network.imports.len(),
"Document Nodes with a Network implementation should have the same number of inner network inputs as inputs declared on the Document Node"
);
// Match the document node input and the inputs of the inner network
for (input_index, (document_input, network_input)) in node.inputs.into_iter().zip(inner_network.inputs.iter()).enumerate() {
for (input_index, (document_input, network_input)) in node.inputs.into_iter().zip(inner_network.imports.iter()).enumerate() {
// Keep track of how many network inputs we have already connected for each node
let offset = network_offsets.entry(network_input).or_insert(0);
match document_input {
@ -1012,8 +1014,8 @@ impl NodeNetwork {
}
NodeInput::Network(_) => {
*network_offsets.get_mut(network_input).unwrap() += 1;
if let Some(index) = self.inputs.iter().position(|i| *i == id) {
self.inputs[index] = *network_input;
if let Some(index) = self.imports.iter().position(|i| *i == id) {
self.imports[index] = *network_input;
}
}
NodeInput::Value { .. } => unreachable!("Value inputs should have been replaced with value nodes"),
@ -1022,7 +1024,7 @@ impl NodeNetwork {
}
// Connect all nodes that were previously connected to this node to the nodes of the inner network
for (i, output) in inner_network.outputs.into_iter().enumerate() {
for (i, output) in inner_network.exports.into_iter().enumerate() {
let node_input = |node_id, output_index, lambda| NodeInput::Node { node_id, output_index, lambda };
self.replace_node_inputs(node_input(id, i, false), node_input(output.node_id, output.node_output_index, false));
@ -1082,7 +1084,7 @@ impl NodeNetwork {
for NodeOutput {
ref mut node_id,
ref mut node_output_index,
} in self.outputs.iter_mut()
} in self.exports.iter_mut()
{
if *node_id == id {
*node_id = input_node_id;
@ -1199,8 +1201,8 @@ impl NodeNetwork {
nodes.sort_unstable_by_key(|(i, _)| *i);
// Create a network to evaluate each output
self.outputs.into_iter().map(move |output| ProtoNetwork {
inputs: self.inputs.clone(),
self.exports.into_iter().map(move |output| ProtoNetwork {
inputs: self.imports.clone(),
output: output.node_id,
nodes: nodes.clone(),
})
@ -1244,8 +1246,8 @@ mod test {
fn add_network() -> NodeNetwork {
NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
(
NodeId(0),
@ -1277,8 +1279,8 @@ mod test {
let mut network = add_network();
network.map_ids(|id| NodeId(id.0 + 1));
let mapped_add = NodeNetwork {
inputs: vec![NodeId(1), NodeId(1)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(1)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [
(
NodeId(1),
@ -1316,8 +1318,8 @@ mod test {
};
// TODO: Extend test cases to test nested network
let mut extraction_network = NodeNetwork {
inputs: vec![],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
id_node.clone(),
DocumentNode {
@ -1343,8 +1345,8 @@ mod test {
#[test]
fn flatten_add() {
let mut network = NodeNetwork {
inputs: vec![NodeId(1)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(1)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [(
NodeId(1),
DocumentNode {
@ -1446,8 +1448,8 @@ mod test {
fn flat_network() -> NodeNetwork {
NodeNetwork {
inputs: vec![NodeId(10)],
outputs: vec![NodeOutput::new(NodeId(11), 0)],
imports: vec![NodeId(10)],
exports: vec![NodeOutput::new(NodeId(11), 0)],
nodes: [
(
NodeId(10),
@ -1509,8 +1511,8 @@ mod test {
fn two_node_identity() -> NodeNetwork {
NodeNetwork {
inputs: vec![NodeId(1), NodeId(2)],
outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(1), NodeId(2)],
exports: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
nodes: [
(
NodeId(1),
@ -1539,8 +1541,8 @@ mod test {
fn output_duplicate(network_outputs: Vec<NodeOutput>, result_node_input: NodeInput) -> NodeNetwork {
let mut network = NodeNetwork {
inputs: Vec::new(),
outputs: network_outputs,
imports: Vec::new(),
exports: network_outputs,
nodes: [
(
NodeId(1),
@ -1576,8 +1578,8 @@ mod test {
fn simple_duplicate() {
let result = output_duplicate(vec![NodeOutput::new(NodeId(1), 0)], NodeInput::node(NodeId(1), 0));
println!("{result:#?}");
assert_eq!(result.outputs.len(), 1, "The number of outputs should remain as 1");
assert_eq!(result.outputs[0], NodeOutput::new(NodeId(11), 0), "The outer network output should be from a duplicated inner network");
assert_eq!(result.exports.len(), 1, "The number of outputs should remain as 1");
assert_eq!(result.exports[0], NodeOutput::new(NodeId(11), 0), "The outer network output should be from a duplicated inner network");
let mut ids = result.nodes.keys().copied().collect::<Vec<_>>();
ids.sort();
assert_eq!(ids, vec![NodeId(11), NodeId(10010)], "Should only contain identity and values");

View file

@ -30,7 +30,7 @@ impl Compiler {
Ok(proto_networks_result.into_iter())
}
pub fn compile_single(&self, network: NodeNetwork) -> Result<ProtoNetwork, String> {
assert_eq!(network.outputs.len(), 1, "Graph with multiple outputs not yet handled");
assert_eq!(network.exports.len(), 1, "Graph with multiple outputs not yet handled");
let Some(proto_network) = self.compile(network)?.next() else {
return Err("Failed to convert graph into proto graph".to_string());
};

View file

@ -114,7 +114,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork) -> NodeNetwork {
}
}
let len = network_inputs.len();
network.inputs = network_inputs;
network.imports = network_inputs;
// if the network has no inputs, it doesn't need to be wrapped in a scope
if len == 0 {
@ -140,8 +140,8 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork) -> NodeNetwork {
},
];
NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(2), 0)],
nodes: nodes.into_iter().enumerate().map(|(id, node)| (NodeId(id as u64), node)).collect(),
..Default::default()
}
@ -151,8 +151,8 @@ fn begin_scope() -> DocumentNode {
DocumentNode {
name: "Begin Scope".to_string(),
implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
nodes: [
DocumentNode {
name: "SetNode".to_string(),

View file

@ -169,11 +169,11 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(
log::debug!("inner_network: {inner_network:?}");
let network = NodeNetwork {
inputs: vec![NodeId(2), NodeId(1)], //vec![0, 1],
imports: vec![NodeId(2), NodeId(1)], //vec![0, 1],
#[cfg(feature = "quantization")]
outputs: vec![NodeOutput::new(NodeId(5), 0)],
exports: vec![NodeOutput::new(NodeId(5), 0)],
#[cfg(not(feature = "quantization"))]
outputs: vec![NodeOutput::new(NodeId(3), 0)],
exports: vec![NodeOutput::new(NodeId(3), 0)],
nodes: [
DocumentNode {
name: "Slice".into(),
@ -434,8 +434,8 @@ async fn blend_gpu_image(foreground: ImageFrame<Color>, background: ImageFrame<C
let compiler = graph_craft::graphene_compiler::Compiler {};
let network = NodeNetwork {
inputs: vec![],
outputs: vec![NodeOutput::new(NodeId(0), 0)],
imports: vec![],
exports: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [DocumentNode {
name: "BlendOp".into(),
inputs: vec![NodeInput::Inline(InlineRust::new(

View file

@ -16,8 +16,8 @@ mod tests {
fn add_network() -> NodeNetwork {
NodeNetwork {
inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0), NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
(
NodeId(0),
@ -45,8 +45,8 @@ mod tests {
}
let network = NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(0), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [(
NodeId(0),
DocumentNode {
@ -86,8 +86,8 @@ mod tests {
use graph_craft::*;
let network = NodeNetwork {
inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(NodeId(1), 0)],
imports: vec![NodeId(0)],
exports: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [
// Simple identity node taking a number as input from outside the graph
(