Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions editor/src/messages/frontend/frontend_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::utility_types::{FrontendDocumentDetails, MouseCursorIcon};
use crate::messages::app_window::app_window_message_handler::AppWindowPlatform;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::node_graph::utility_types::{
BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendNodeType, FrontendXY, Transform,
BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNodeToRender, FrontendNodeType, FrontendXY, Transform,
};
use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer};
use crate::messages::portfolio::document::utility_types::wires::{WirePath, WirePathUpdate};
Expand Down Expand Up @@ -274,7 +274,7 @@ pub enum FrontendMessage {
},
UpdateNodeGraphNodes {
#[serde(rename = "nodesToRender")]
nodes_to_render: Vec<FrontendNode>,
nodes_to_render: Vec<FrontendNodeToRender>,
#[serde(rename = "inSelectedNetwork")]
in_selected_network: bool,
// Displays a dashed border around the node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1636,7 +1636,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
responses.add(NodeGraphMessage::UpdateActionButtons);
if graph_view_overlay_open {
let nodes_to_render = network_interface.collect_nodes(&self.node_graph_errors, breadcrumb_network_path);
self.frontend_nodes = nodes_to_render.iter().map(|node| node.id).collect();
self.frontend_nodes = nodes_to_render.iter().map(|node| node.metadata.node_id).collect();
let previewed_node = network_interface.previewed_node(breadcrumb_network_path);
responses.add(FrontendMessage::UpdateNodeGraphNodes {
nodes_to_render,
Expand Down
88 changes: 66 additions & 22 deletions editor/src/messages/portfolio/document/node_graph/utility_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ pub struct FrontendGraphInput {
pub description: String,
#[serde(rename = "resolvedType")]
pub resolved_type: String,
#[serde(rename = "connectedTo")]
/// Either "nothing", "import index {index}", or "{node name} output {output_index}".
#[serde(rename = "connectedToString")]
pub connected_to: String,
/// Used to render the upstream node once this node is rendered
#[serde(rename = "connectedToNode")]
pub connected_to_node: Option<NodeId>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
Expand All @@ -83,38 +86,79 @@ pub struct FrontendGraphOutput {
pub connected_to: Vec<String>,
}

// Metadata that is common to nodes and layers
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendNode {
pub id: graph_craft::document::NodeId,
#[serde(rename = "isLayer")]
pub is_layer: bool,
pub struct FrontendNodeMetadata {
#[serde(rename = "nodeId")]
pub node_id: NodeId,
// TODO: Remove and replace with popup manager system
#[serde(rename = "canBeLayer")]
pub can_be_layer: bool,
pub selected: bool,
pub reference: Option<String>,
#[serde(rename = "displayName")]
pub display_name: String,
#[serde(rename = "primaryInput")]
pub primary_input: Option<FrontendGraphInput>,
#[serde(rename = "exposedInputs")]
pub exposed_inputs: Vec<FrontendGraphInput>,
#[serde(rename = "primaryOutput")]
pub primary_output: Option<FrontendGraphOutput>,
#[serde(rename = "exposedOutputs")]
pub exposed_outputs: Vec<FrontendGraphOutput>,
pub selected: bool,
// Used to get the description, which is stored in a global hashmap
pub reference: Option<String>,
// Reduces opacity of node/hidden eye icon
pub visible: bool,
// The svg string for each input
// pub wires: Vec<Option<String>>,
pub errors: Option<String>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendNode {
// pub position: FrontendNodePosition,
pub position: FrontendXY,
pub inputs: Vec<Option<FrontendGraphInput>>,
pub outputs: Vec<Option<FrontendGraphOutput>>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendLayer {
#[serde(rename = "bottomInput")]
pub bottom_input: FrontendGraphInput,
#[serde(rename = "sideInput")]
pub side_input: Option<FrontendGraphInput>,
pub output: FrontendGraphOutput,
// pub position: FrontendLayerPosition,
pub position: FrontendXY,
pub locked: bool,
#[serde(rename = "chainWidth")]
pub chain_width: u32,
#[serde(rename = "layerHasLeftBorderGap")]
pub layer_has_left_border_gap: bool,
#[serde(rename = "primaryOutputConnectedToLayer")]
pub primary_output_connected_to_layer: bool,
#[serde(rename = "primaryInputConnectedToLayer")]
pub primary_input_connected_to_layer: bool,
pub position: FrontendXY,
pub visible: bool,
pub locked: bool,
pub previewed: bool,
pub errors: Option<String>,
#[serde(rename = "primaryOutputConnectedToLayer")]
pub primary_output_connected_to_layer: bool,
}

// // Should be an enum but those are hard to serialize/deserialize to TS
// #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
// pub struct FrontendNodePosition {
// pub absolute: Option<FrontendXY>,
// pub chain: Option<bool>,
// }

// // Should be an enum but those are hard to serialize/deserialize to TS
// #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
// pub struct FrontendLayerPosition {
// pub absolute: Option<FrontendXY>,
// pub stack: Option<u32>,
// }

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendNodeOrLayer {
pub node: Option<FrontendNode>,
pub layer: Option<FrontendLayer>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendNodeToRender {
pub metadata: FrontendNodeMetadata,
#[serde(rename = "nodeOrLayer")]
pub node_or_layer: FrontendNodeOrLayer,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ use graphene_std::uuid::NodeId;
use crate::{
consts::{EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP, EXPORTS_TO_TOP_EDGE_PIXEL_GAP, GRID_SIZE, IMPORTS_TO_LEFT_EDGE_PIXEL_GAP, IMPORTS_TO_TOP_EDGE_PIXEL_GAP},
messages::portfolio::document::{
node_graph::utility_types::{FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendXY},
node_graph::utility_types::{
FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput, FrontendLayer, FrontendNode, FrontendNodeMetadata, FrontendNodeOrLayer, FrontendNodeToRender, FrontendXY,
},
utility_types::network_interface::{FlowType, InputConnector, NodeNetworkInterface, OutputConnector},
},
};

// Functions used to collect data from the network interface for use in rendering the node graph
impl NodeNetworkInterface {
pub fn collect_nodes(&mut self, node_graph_errors: &GraphErrors, network_path: &[NodeId]) -> Vec<FrontendNode> {
pub fn collect_nodes(&mut self, node_graph_errors: &GraphErrors, network_path: &[NodeId]) -> Vec<FrontendNodeToRender> {
let Some(network) = self.nested_network(network_path) else {
log::error!("Could not get nested network when collecting nodes");
return Vec::new();
Expand All @@ -22,32 +24,6 @@ impl NodeNetworkInterface {
for (node_id, visible) in network.nodes.iter().map(|(node_id, node)| (*node_id, node.visible)).collect::<Vec<_>>() {
let node_id_path = [network_path, &[node_id]].concat();

let primary_input_connector = InputConnector::node(node_id, 0);

let primary_input = if self.input_from_connector(&primary_input_connector, network_path).is_some_and(|input| input.is_exposed()) {
self.frontend_input_from_connector(&primary_input_connector, network_path)
} else {
None
};
let exposed_inputs = (1..self.number_of_inputs(&node_id, network_path))
.filter_map(|input_index| self.frontend_input_from_connector(&InputConnector::node(node_id, input_index), network_path))
.collect();

let primary_output = self.frontend_output_from_connector(&OutputConnector::node(node_id, 0), network_path);

let exposed_outputs = (1..self.number_of_outputs(&node_id, network_path))
.filter_map(|output_index| self.frontend_output_from_connector(&OutputConnector::node(node_id, output_index), network_path))
.collect();

let Some(position) = self.position(&node_id, network_path) else {
log::error!("Could not get position for node: {node_id}");
continue;
};
let position = FrontendXY { x: position.x, y: position.y };
let previewed = self.previewed_node(network_path) == Some(node_id);

let locked = self.is_locked(&node_id, network_path);

let errors = node_graph_errors
.iter()
.find(|error| error.node_path == node_id_path)
Expand All @@ -60,31 +36,73 @@ impl NodeNetworkInterface {
}
});

nodes.push(FrontendNode {
id: node_id,
is_layer: self.node_metadata(&node_id, network_path).is_some_and(|node_metadata| node_metadata.persistent_metadata.is_layer()),
let metadata = FrontendNodeMetadata {
node_id,
can_be_layer: self.is_eligible_to_be_layer(&node_id, network_path),
display_name: self.display_name(&node_id, network_path),
selected: selected_nodes.0.contains(&node_id),
reference: self.reference(&node_id, network_path).cloned().unwrap_or_default(),
display_name: self.display_name(&node_id, network_path),
previewed,
visible,
errors,
};

primary_input,
exposed_inputs,
primary_output,
exposed_outputs,
position,

locked,
chain_width: self.chain_width(&node_id, network_path),
layer_has_left_border_gap: self.layer_has_left_border_gap(&node_id, network_path),
primary_input_connected_to_layer: self.primary_output_connected_to_layer(&node_id, network_path),
primary_output_connected_to_layer: self.primary_input_connected_to_layer(&node_id, network_path),
});
}
let node_or_layer = match self.is_layer(&node_id, network_path) {
true => {
let Some(position) = self.position(&node_id, network_path) else {
log::error!("Could not get position for node: {node_id}");
continue;
};
let position = FrontendXY { x: position.x, y: position.y };

let Some(bottom_input) = self.frontend_input_from_connector(&InputConnector::node(node_id, 0), network_path) else {
log::error!("Layer must have a visible primary input");
continue;
};
let side_input = self.frontend_input_from_connector(&InputConnector::node(node_id, 1), network_path);
let Some(output) = self.frontend_output_from_connector(&OutputConnector::node(node_id, 0), network_path) else {
log::error!("Layer must have a visible primary output");
continue;
};

let layer = Some(FrontendLayer {
bottom_input,
side_input,
output,
position,
locked: self.is_locked(&node_id, network_path),
chain_width: self.chain_width(&node_id, network_path),
layer_has_left_border_gap: self.layer_has_left_border_gap(&node_id, network_path),
primary_input_connected_to_layer: self.primary_input_connected_to_layer(&node_id, network_path),
primary_output_connected_to_layer: self.primary_output_connected_to_layer(&node_id, network_path),
});
FrontendNodeOrLayer { node: None, layer }
}
false => {
let Some(position) = self.position(&node_id, network_path) else {
log::error!("Could not get position for node: {node_id}");
continue;
};

let position = FrontendXY { x: position.x, y: position.y };

let inputs = (0..self.number_of_inputs(&node_id, network_path))
.map(|input_index| self.frontend_input_from_connector(&InputConnector::node(node_id, input_index), network_path))
.collect();

let outputs = (0..self.number_of_outputs(&node_id, network_path))
.map(|output_index| self.frontend_output_from_connector(&OutputConnector::node(node_id, output_index), network_path))
.collect();

let node = Some(FrontendNode { position, inputs, outputs });

FrontendNodeOrLayer { node, layer: None }
}
};

let frontend_node_to_render = FrontendNodeToRender { metadata, node_or_layer };

nodes.push(frontend_node_to_render);
}
nodes
}

Expand Down Expand Up @@ -146,12 +164,15 @@ impl NodeNetworkInterface {
// }
// };

let connected_to_node = self.upstream_output_connector(input_connector, network_path).and_then(|output_connector| output_connector.node_id());

Some(FrontendGraphInput {
data_type,
resolved_type,
name,
description,
connected_to,
connected_to_node,
})
}

Expand Down
Loading
Loading