diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index 4601f4d386..50fd43e2c4 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -41,6 +41,7 @@ impl DispatcherMessageHandlers { /// The last occurrence of the message in the message queue is sufficient to ensure correct behavior. /// In addition, these messages do not change any state in the backend (aside from caches). const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[ + MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::NodeGraph(NodeGraphMessageDiscriminant::SendGraph))), MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::PropertiesPanel( PropertiesPanelMessageDiscriminant::Refresh, ))), diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index 4a63e1a859..5921186733 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -2,13 +2,12 @@ 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, Transform, + BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendNodeType, FrontendXY, Transform, }; use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer}; use crate::messages::portfolio::document::utility_types::wires::{WirePath, WirePathUpdate}; use crate::messages::prelude::*; use crate::messages::tool::utility_types::HintData; -use glam::IVec2; use graph_craft::document::NodeId; use graphene_std::raster::Image; use graphene_std::raster::color::Color; @@ -131,18 +130,14 @@ pub enum FrontendMessage { exports: Vec>, /// The primary import location. #[serde(rename = "importPosition")] - import_position: IVec2, + import_position: FrontendXY, /// The primary export location. #[serde(rename = "exportPosition")] - export_position: IVec2, + export_position: FrontendXY, /// The document network does not have an add import or export button. #[serde(rename = "addImportExport")] add_import_export: bool, }, - UpdateInSelectedNetwork { - #[serde(rename = "inSelectedNetwork")] - in_selected_network: bool, - }, UpdateBox { #[serde(rename = "box")] box_selection: Option, @@ -183,10 +178,6 @@ pub enum FrontendMessage { UpdateLayerWidths { #[serde(rename = "layerWidths")] layer_widths: HashMap, - #[serde(rename = "chainWidths")] - chain_widths: HashMap, - #[serde(rename = "hasLeftInputWire")] - has_left_input_wire: HashMap, }, UpdateDialogButtons { #[serde(rename = "layoutTarget")] @@ -282,7 +273,13 @@ pub enum FrontendMessage { cursor: MouseCursorIcon, }, UpdateNodeGraphNodes { - nodes: Vec, + #[serde(rename = "nodesToRender")] + nodes_to_render: Vec, + #[serde(rename = "inSelectedNetwork")] + in_selected_network: bool, + // Displays a dashed border around the node + #[serde(rename = "previewedNode")] + previewed_node: Option, }, UpdateVisibleNodes { nodes: Vec, @@ -296,9 +293,6 @@ pub enum FrontendMessage { layout_target: LayoutTarget, diff: Vec, }, - UpdateNodeGraphSelection { - selected: Vec, - }, UpdateNodeGraphTransform { transform: Transform, }, diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 8d692d771b..6a9c395ab8 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -1190,7 +1190,7 @@ impl MessageHandler> for DocumentMes } responses.add(PropertiesPanelMessage::Refresh); responses.add(NodeGraphMessage::UpdateLayerPanel); - responses.add(NodeGraphMessage::UpdateInSelectedNetwork); + responses.add(NodeGraphMessage::SendGraph); } DocumentMessage::SetBlendModeForSelectedLayers { blend_mode } => { for layer in self.network_interface.selected_nodes().selected_layers_except_artboards(&self.network_interface) { diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs index 1432046a25..37ac29df44 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs @@ -231,7 +231,5 @@ pub enum NodeGraphMessage { }, UpdateActionButtons, UpdateGraphBarRight, - UpdateInSelectedNetwork, UpdateHints, - SendSelectedNodes, } diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 688f455f5b..7af7cd2ee5 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -6,7 +6,7 @@ use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::document_message_handler::navigation_controls; use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext; use crate::messages::portfolio::document::node_graph::document_node_definitions::NodePropertiesContext; -use crate::messages::portfolio::document::node_graph::utility_types::{ContextMenuData, Direction, FrontendGraphDataType}; +use crate::messages::portfolio::document::node_graph::utility_types::{ContextMenuData, Direction, FrontendGraphDataType, FrontendXY}; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::misc::GroupFolderType; use crate::messages::portfolio::document::utility_types::network_interface::{ @@ -192,7 +192,7 @@ impl<'a> MessageHandler> for NodeG responses.add(MenuBarMessage::SendLayout); responses.add(NodeGraphMessage::UpdateLayerPanel); responses.add(PropertiesPanelMessage::Refresh); - responses.add(NodeGraphMessage::SendSelectedNodes); + responses.add(NodeGraphMessage::SendGraph); responses.add(ArtboardToolMessage::UpdateSelectedArtboard); responses.add(DocumentMessage::DocumentStructureChanged); responses.add(OverlaysMessage::Draw); @@ -1633,21 +1633,22 @@ impl<'a> MessageHandler> for NodeG responses.add(NodeGraphMessage::UpdateLayerPanel); responses.add(DocumentMessage::DocumentStructureChanged); responses.add(PropertiesPanelMessage::Refresh); - if breadcrumb_network_path == selection_network_path && graph_view_overlay_open { - let nodes = network_interface.collect_nodes(&self.node_graph_errors, breadcrumb_network_path); - self.frontend_nodes = nodes.iter().map(|node| node.id).collect(); - responses.add(FrontendMessage::UpdateNodeGraphNodes { nodes }); + 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(); + let previewed_node = network_interface.previewed_node(breadcrumb_network_path); + responses.add(FrontendMessage::UpdateNodeGraphNodes { + nodes_to_render, + in_selected_network: selection_network_path == breadcrumb_network_path, + previewed_node, + }); responses.add(NodeGraphMessage::UpdateVisibleNodes); - let (layer_widths, chain_widths, has_left_input_wire) = network_interface.collect_layer_widths(breadcrumb_network_path); + let layer_widths = network_interface.collect_layer_widths(breadcrumb_network_path); responses.add(NodeGraphMessage::UpdateImportsExports); - responses.add(FrontendMessage::UpdateLayerWidths { - layer_widths, - chain_widths, - has_left_input_wire, - }); - responses.add(NodeGraphMessage::SendSelectedNodes); + responses.add(FrontendMessage::UpdateLayerWidths { layer_widths }); responses.add(NodeGraphMessage::SendWires); self.update_node_graph_hints(responses); } @@ -1956,6 +1957,15 @@ impl<'a> MessageHandler> for NodeG return; }; + let import_position = FrontendXY { + x: import_position.x, + y: import_position.y, + }; + let export_position = FrontendXY { + x: export_position.x, + y: export_position.y, + }; + // Do not show the add import or add export button in the document network; let add_import_export = !breadcrumb_network_path.is_empty(); @@ -2000,22 +2010,9 @@ impl<'a> MessageHandler> for NodeG self.update_graph_bar_right(graph_fade_artwork_percentage, network_interface, breadcrumb_network_path, navigation_handler); self.send_node_bar_layout(responses); } - NodeGraphMessage::UpdateInSelectedNetwork => responses.add(FrontendMessage::UpdateInSelectedNetwork { - in_selected_network: selection_network_path == breadcrumb_network_path, - }), NodeGraphMessage::UpdateHints => { self.update_node_graph_hints(responses); } - NodeGraphMessage::SendSelectedNodes => { - let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(breadcrumb_network_path) else { - log::error!("Could not get selected nodes in NodeGraphMessage::SendSelectedNodes"); - return; - }; - responses.add(NodeGraphMessage::UpdateActionButtons); - responses.add(FrontendMessage::UpdateNodeGraphSelection { - selected: selected_nodes.selected_nodes().cloned().collect::>(), - }); - } } let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(selection_network_path) else { log::error!("Could not get selected nodes in NodeGraphMessageHandler"); diff --git a/editor/src/messages/portfolio/document/node_graph/utility_types.rs b/editor/src/messages/portfolio/document/node_graph/utility_types.rs index 07741ee003..45dd0532f2 100644 --- a/editor/src/messages/portfolio/document/node_graph/utility_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/utility_types.rs @@ -1,4 +1,3 @@ -use glam::IVec2; use graph_craft::document::NodeId; use graph_craft::document::value::TaggedValue; use graphene_std::Type; @@ -51,6 +50,12 @@ impl FrontendGraphDataType { } } +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct FrontendXY { + pub x: i32, + pub y: i32, +} + #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] pub struct FrontendGraphInput { #[serde(rename = "dataType")] @@ -85,6 +90,7 @@ pub struct FrontendNode { pub is_layer: bool, #[serde(rename = "canBeLayer")] pub can_be_layer: bool, + pub selected: bool, pub reference: Option, #[serde(rename = "displayName")] pub display_name: String, @@ -96,11 +102,15 @@ pub struct FrontendNode { pub primary_output: Option, #[serde(rename = "exposedOutputs")] pub exposed_outputs: Vec, + #[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: IVec2, + pub position: FrontendXY, pub visible: bool, pub locked: bool, pub previewed: bool, diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface.rs b/editor/src/messages/portfolio/document/utility_types/network_interface.rs index 96095de94a..7a9b617824 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface.rs @@ -2856,10 +2856,11 @@ impl NodeNetworkInterface { bounding_box_subpath.bounding_box_with_transform(network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport) } - pub fn collect_layer_widths(&mut self, network_path: &[NodeId]) -> (HashMap, HashMap, HashMap) { + // TODO: Remove and get layer click targets from render output + pub fn collect_layer_widths(&mut self, network_path: &[NodeId]) -> HashMap { let Some(network_metadata) = self.network_metadata(network_path) else { log::error!("Could not get nested network_metadata in collect_layer_widths"); - return (HashMap::new(), HashMap::new(), HashMap::new()); + return HashMap::new(); }; let nodes = network_metadata .persistent_metadata @@ -2871,13 +2872,8 @@ impl NodeNetworkInterface { .iter() .filter_map(|node_id| self.layer_width(node_id, network_path).map(|layer_width| (*node_id, layer_width))) .collect::>(); - let chain_widths = nodes.iter().map(|node_id| (*node_id, self.chain_width(node_id, network_path))).collect::>(); - let has_left_input_wire = nodes - .iter() - .map(|node_id| (*node_id, self.layer_has_left_border_gap(node_id, network_path))) - .collect::>(); - (layer_widths, chain_widths, has_left_input_wire) + layer_widths } pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option { diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs index b1d94d9ab8..055003117e 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs @@ -5,7 +5,7 @@ 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}, + node_graph::utility_types::{FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendXY}, utility_types::network_interface::{FlowType, InputConnector, NodeNetworkInterface, OutputConnector}, }, }; @@ -17,6 +17,7 @@ impl NodeNetworkInterface { log::error!("Could not get nested network when collecting nodes"); return Vec::new(); }; + let selected_nodes = self.selected_nodes_in_nested_network(network_path).unwrap_or_default(); let mut nodes = Vec::new(); for (node_id, visible) in network.nodes.iter().map(|(node_id, node)| (*node_id, node.visible)).collect::>() { let node_id_path = [network_path, &[node_id]].concat(); @@ -37,19 +38,12 @@ impl NodeNetworkInterface { 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 (primary_output_connected_to_layer, primary_input_connected_to_layer) = if self.is_layer(&node_id, network_path) { - ( - self.primary_output_connected_to_layer(&node_id, network_path), - self.primary_input_connected_to_layer(&node_id, network_path), - ) - } else { - (false, 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 previewed = self.previewed_node(network_path) == Some(node_id); let locked = self.is_locked(&node_id, network_path); @@ -70,19 +64,24 @@ impl NodeNetworkInterface { id: node_id, is_layer: self.node_metadata(&node_id, network_path).is_some_and(|node_metadata| node_metadata.persistent_metadata.is_layer()), can_be_layer: self.is_eligible_to_be_layer(&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, - primary_output_connected_to_layer, - primary_input_connected_to_layer, position, - previewed, - visible, + locked, - errors, + 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), }); } @@ -259,9 +258,12 @@ impl NodeNetworkInterface { /// Checks if a layer should display a gap in its left border pub fn layer_has_left_border_gap(&self, node_id: &NodeId, network_path: &[NodeId]) -> bool { - self.upstream_flow_back_from_nodes(vec![*node_id], network_path, FlowType::HorizontalFlow) - .skip(1) - .any(|node_id| !self.is_chain(&node_id, network_path)) + self.upstream_flow_back_from_nodes(vec![*node_id], network_path, FlowType::HorizontalFlow).skip(1).any(|node_id| { + !self.is_chain(&node_id, network_path) + || self + .upstream_output_connector(&InputConnector::node(node_id, 0), network_path) + .is_some_and(|output_connector| matches!(output_connector, OutputConnector::Import(_))) + }) } /// Returns the node which should have a dashed border drawn around it diff --git a/frontend/src/components/views/Graph.svelte b/frontend/src/components/views/Graph.svelte index ad1497d36d..84f860f465 100644 --- a/frontend/src/components/views/Graph.svelte +++ b/frontend/src/components/views/Graph.svelte @@ -116,12 +116,11 @@ } function toggleLayerDisplay(displayAsLayer: boolean, toggleId: bigint) { - let node = $nodeGraph.nodes.get(toggleId); - if (node) editor.handle.setToNodeOrLayer(node.id, displayAsLayer); + editor.handle.setToNodeOrLayer(toggleId, displayAsLayer); } function canBeToggledBetweenNodeAndLayer(toggleDisplayAsLayerNodeId: bigint) { - return $nodeGraph.nodes.get(toggleDisplayAsLayerNodeId)?.canBeLayer || false; + return $nodeGraph.nodesToRender.get(toggleDisplayAsLayerNodeId)?.canBeLayer || false; } function createNode(nodeType: string) { @@ -148,7 +147,7 @@ return borderMask(boxes, nodeWidth, nodeHeight); } - function layerBorderMask(nodeWidthFromThumbnail: number, nodeChainAreaLeftExtension: number, hasLeftInputWire: boolean): string { + function layerBorderMask(nodeWidthFromThumbnail: number, nodeChainAreaLeftExtension: number, layerHasLeftBorderGap: boolean): string { const NODE_HEIGHT = 2 * 24; const THUMBNAIL_WIDTH = 72 + 8 * 2; const FUDGE_HEIGHT_BEYOND_LAYER_HEIGHT = 2; @@ -158,7 +157,7 @@ const boxes: { x: number; y: number; width: number; height: number }[] = []; // Left input - if (hasLeftInputWire && nodeChainAreaLeftExtension > 0) { + if (layerHasLeftBorderGap && nodeChainAreaLeftExtension > 0) { boxes.push({ x: -8, y: 16, width: 16, height: 16 }); } @@ -318,8 +317,6 @@ xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" class="connector" - data-connector="output" - data-datatype={frontendOutput.dataType} style:--data-color={`var(--color-data-${frontendOutput.dataType.toLowerCase()})`} style:--data-color-dim={`var(--color-data-${frontendOutput.dataType.toLowerCase()}-dim)`} style:--offset-left={($nodeGraph.updateImportsExports.importPosition.x - 8) / 24} @@ -390,8 +387,6 @@ xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" class="connector" - data-connector="input" - data-datatype={frontendInput.dataType} style:--data-color={`var(--color-data-${frontendInput.dataType.toLowerCase()})`} style:--data-color-dim={`var(--color-data-${frontendInput.dataType.toLowerCase()}-dim)`} style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 8) / 24} @@ -492,54 +487,47 @@
- {#each Array.from($nodeGraph.nodes) - .filter(([nodeId, node]) => node.isLayer && $nodeGraph.visibleNodes.has(nodeId)) - .map(([_, node], nodeIndex) => ({ node, nodeIndex })) as { node, nodeIndex } (nodeIndex)} + {#each Array.from($nodeGraph.nodesToRender).filter(([nodeId, node]) => node.isLayer && $nodeGraph.visibleNodes.has(nodeId)) as [nodeId, layer]} {@const clipPathId = String(Math.random()).substring(2)} - {@const stackDataInput = node.exposedInputs[0]} - {@const layerAreaWidth = $nodeGraph.layerWidths.get(node.id) || 8} - {@const layerChainWidth = $nodeGraph.chainWidths.get(node.id) || 0} - {@const hasLeftInputWire = $nodeGraph.hasLeftInputWire.get(node.id) || false} - {@const description = (node.reference && $nodeGraph.nodeDescriptions.get(node.reference)) || undefined} + {@const layerAreaWidth = $nodeGraph.layerWidths.get(layer.id) || 8} + {@const layerChainWidth = layer.chainWidth !== 0 ? layer.chainWidth + 0.5 : 0} + {@const description = (layer.reference && $nodeGraph.nodeDescriptions.get(layer.reference)) || undefined}
- {#if node.errors} - {node.errors} - {node.errors} + {#if layer.errors} + {layer.errors} + {layer.errors} {/if}
- {#if $nodeGraph.thumbnails.has(node.id)} - {@html $nodeGraph.thumbnails.get(node.id)} + {#if $nodeGraph.thumbnails.has(nodeId)} + {@html $nodeGraph.thumbnails.get(nodeId)} {/if} - {#if node.primaryOutput} + {#if layer.primaryOutput} - {outputTooltip(node.primaryOutput)} - {#if node.primaryOutput.connectedTo.length > 0} + {outputTooltip(layer.primaryOutput)} + {#if layer.primaryOutput.connectedTo.length > 0} - {#if node.primaryOutputConnectedToLayer} + {#if layer.primaryOutputConnectedToLayer} {/if} {:else} @@ -552,17 +540,15 @@ xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 12" class="connector bottom" - data-connector="input" - data-datatype={node.primaryInput?.dataType} - style:--data-color={`var(--color-data-${(node.primaryInput?.dataType || "General").toLowerCase()})`} - style:--data-color-dim={`var(--color-data-${(node.primaryInput?.dataType || "General").toLowerCase()}-dim)`} + style:--data-color={`var(--color-data-${(layer.primaryInput?.dataType || "General").toLowerCase()})`} + style:--data-color-dim={`var(--color-data-${(layer.primaryInput?.dataType || "General").toLowerCase()}-dim)`} > - {#if node.primaryInput} - {inputTooltip(node.primaryInput)} + {#if layer.primaryInput} + {inputTooltip(layer.primaryInput)} {/if} - {#if node.primaryInput?.connectedTo !== "nothing"} + {#if layer.primaryInput?.connectedTo !== "nothing"} - {#if node.primaryInputConnectedToLayer} + {#if layer.primaryInputConnectedToLayer} {/if} {:else} @@ -571,19 +557,17 @@
- {#if node.exposedInputs.length > 0} + {#if layer.exposedInputs.length > 0}
- {inputTooltip(stackDataInput)} - {#if stackDataInput.connectedTo !== undefined} + {inputTooltip(layer.exposedInputs[0])} + {#if layer.exposedInputs[0].connectedTo !== undefined} {:else} @@ -593,25 +577,24 @@ {/if}
- {node.displayName} + {layer.displayName}
{ /* Button is purely visual, clicking is handled in NodeGraphMessage::PointerDown */ }} - tooltip={node.visible ? "Visible" : "Hidden"} + tooltip={layer.visible ? "Visible" : "Hidden"} /> - + @@ -647,15 +630,13 @@
- {#each Array.from($nodeGraph.nodes) - .filter(([nodeId, node]) => !node.isLayer && $nodeGraph.visibleNodes.has(nodeId)) - .map(([_, node], nodeIndex) => ({ node, nodeIndex })) as { node, nodeIndex } (nodeIndex)} + {#each Array.from($nodeGraph.nodesToRender).filter(([nodeId, node]) => !node.isLayer && $nodeGraph.visibleNodes.has(nodeId)) as [nodeId, node]} {@const exposedInputsOutputs = zipWithUndefined(node.exposedInputs, node.exposedOutputs)} {@const clipPathId = String(Math.random()).substring(2)} {@const description = (node.reference && $nodeGraph.nodeDescriptions.get(node.reference)) || undefined}
{#if node.errors} {node.errors} @@ -695,8 +675,6 @@ xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" class="connector primary-connector" - data-connector="input" - data-datatype={node.primaryInput?.dataType} style:--data-color={`var(--color-data-${node.primaryInput.dataType.toLowerCase()})`} style:--data-color-dim={`var(--color-data-${node.primaryInput.dataType.toLowerCase()}-dim)`} > @@ -714,8 +692,6 @@ xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" class="connector" - data-connector="input" - data-datatype={secondary.dataType} style:--data-color={`var(--color-data-${secondary.dataType.toLowerCase()})`} style:--data-color-dim={`var(--color-data-${secondary.dataType.toLowerCase()}-dim)`} > @@ -736,8 +712,6 @@ xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" class="connector primary-connector" - data-connector="output" - data-datatype={node.primaryOutput.dataType} style:--data-color={`var(--color-data-${node.primaryOutput.dataType.toLowerCase()})`} style:--data-color-dim={`var(--color-data-${node.primaryOutput.dataType.toLowerCase()}-dim)`} > @@ -754,8 +728,6 @@ xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8" class="connector" - data-connector="output" - data-datatype={secondary.dataType} style:--data-color={`var(--color-data-${secondary.dataType.toLowerCase()})`} style:--data-color-dim={`var(--color-data-${secondary.dataType.toLowerCase()}-dim)`} > @@ -784,7 +756,6 @@
- {#if $nodeGraph.box}
obj.layerWidths); -const ChainWidths = Transform(({ obj }) => obj.chainWidths); -const HasLeftInputWire = Transform(({ obj }) => obj.hasLeftInputWire); export class UpdateLayerWidths extends JsMessage { @LayerWidths readonly layerWidths!: Map; - @ChainWidths - readonly chainWidths!: Map; - @HasLeftInputWire - readonly hasLeftInputWire!: Map; } export class UpdateNodeGraphNodes extends JsMessage { - @Type(() => FrontendNode) - readonly nodes!: FrontendNode[]; + readonly nodesToRender!: FrontendNode[]; + + readonly inSelectedNetwork!: boolean; + + readonly previewedNode!: bigint | undefined; } export class UpdateVisibleNodes extends JsMessage { @@ -124,11 +115,6 @@ export class UpdateNodeThumbnail extends JsMessage { readonly value!: string; } -export class UpdateNodeGraphSelection extends JsMessage { - @Type(() => BigInt) - readonly selected!: bigint[]; -} - export class UpdateOpenDocumentsList extends JsMessage { @Type(() => FrontendDocumentDetails) readonly openDocuments!: FrontendDocumentDetails[]; @@ -213,11 +199,13 @@ export class FrontendGraphOutput { } export class FrontendNode { + readonly id!: bigint; + readonly isLayer!: boolean; readonly canBeLayer!: boolean; - readonly id!: bigint; + readonly selected!: boolean; readonly reference!: string | undefined; @@ -231,6 +219,10 @@ export class FrontendNode { readonly exposedOutputs!: FrontendGraphOutput[]; + readonly chainWidth!: number; + + readonly layerHasLeftBorderGap!: boolean; + readonly primaryInputConnectedToLayer!: boolean; readonly primaryOutputConnectedToLayer!: boolean; @@ -1686,7 +1678,6 @@ export const messageMakers: Record = { UpdateImportReorderIndex, UpdateImportsExports, UpdateInputHints, - UpdateInSelectedNetwork, UpdateLayersPanelBottomBarLayout, UpdateLayersPanelControlBarLeftLayout, UpdateLayersPanelControlBarRightLayout, @@ -1696,7 +1687,6 @@ export const messageMakers: Record = { UpdateMouseCursor, UpdateNodeGraphControlBarLayout, UpdateNodeGraphNodes, - UpdateNodeGraphSelection, UpdateNodeGraphTransform, UpdateNodeGraphWires, UpdateNodeThumbnail, diff --git a/frontend/src/state-providers/node-graph.ts b/frontend/src/state-providers/node-graph.ts index 9160ad13aa..4b27781fd4 100644 --- a/frontend/src/state-providers/node-graph.ts +++ b/frontend/src/state-providers/node-graph.ts @@ -13,7 +13,6 @@ import { UpdateBox, UpdateClickTargets, UpdateContextMenuInformation, - UpdateInSelectedNetwork, UpdateImportReorderIndex, UpdateExportReorderIndex, UpdateImportsExports, @@ -21,7 +20,6 @@ import { UpdateNodeGraphNodes, UpdateVisibleNodes, UpdateNodeGraphWires, - UpdateNodeGraphSelection, UpdateNodeGraphTransform, UpdateNodeThumbnail, UpdateWirePathInProgress, @@ -34,10 +32,9 @@ export function createNodeGraphState(editor: Editor) { clickTargets: undefined as FrontendClickTargets | undefined, contextMenuInformation: undefined as ContextMenuInformation | undefined, layerWidths: new Map(), - chainWidths: new Map(), - hasLeftInputWire: new Map(), updateImportsExports: undefined as UpdateImportsExports | undefined, - nodes: new Map(), + nodesToRender: new Map(), + visibleNodes: new Set(), /// The index is the exposed input index. The exports have a first key value of u32::MAX. wires: new Map>(), @@ -45,9 +42,9 @@ export function createNodeGraphState(editor: Editor) { nodeDescriptions: new Map(), nodeTypes: [] as FrontendNodeType[], thumbnails: new Map(), - selected: [] as bigint[], transform: { scale: 1, x: 0, y: 0 }, inSelectedNetwork: true, + previewedNode: undefined as bigint | undefined, reorderImportIndex: undefined as number | undefined, reorderExportIndex: undefined as number | undefined, }); @@ -96,26 +93,20 @@ export function createNodeGraphState(editor: Editor) { return state; }); }); - editor.subscriptions.subscribeJsMessage(UpdateInSelectedNetwork, (updateInSelectedNetwork) => { - update((state) => { - state.inSelectedNetwork = updateInSelectedNetwork.inSelectedNetwork; - return state; - }); - }); editor.subscriptions.subscribeJsMessage(UpdateLayerWidths, (updateLayerWidths) => { update((state) => { state.layerWidths = updateLayerWidths.layerWidths; - state.chainWidths = updateLayerWidths.chainWidths; - state.hasLeftInputWire = updateLayerWidths.hasLeftInputWire; return state; }); }); editor.subscriptions.subscribeJsMessage(UpdateNodeGraphNodes, (updateNodeGraphNodes) => { update((state) => { - state.nodes.clear(); - updateNodeGraphNodes.nodes.forEach((node) => { - state.nodes.set(node.id, node); + state.nodesToRender.clear(); + updateNodeGraphNodes.nodesToRender.forEach((node) => { + state.nodesToRender.set(node.id, node); }); + state.inSelectedNetwork = updateNodeGraphNodes.inSelectedNetwork; + state.previewedNode = updateNodeGraphNodes.previewedNode; return state; }); }); @@ -149,12 +140,6 @@ export function createNodeGraphState(editor: Editor) { return state; }); }); - editor.subscriptions.subscribeJsMessage(UpdateNodeGraphSelection, (updateNodeGraphSelection) => { - update((state) => { - state.selected = updateNodeGraphSelection.selected; - return state; - }); - }); editor.subscriptions.subscribeJsMessage(UpdateNodeGraphTransform, (updateNodeGraphTransform) => { update((state) => { state.transform = updateNodeGraphTransform.transform;