Skip to content

Commit d8f1124

Browse files
committed
Improve collect_nodes
1 parent 56d8f84 commit d8f1124

6 files changed

Lines changed: 91 additions & 58 deletions

File tree

editor/src/messages/frontend/frontend_message.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::utility_types::{FrontendDocumentDetails, MouseCursorIcon};
22
use crate::messages::app_window::app_window_message_handler::AppWindowPlatform;
33
use crate::messages::layout::utility_types::widget_prelude::*;
44
use crate::messages::portfolio::document::node_graph::utility_types::{
5-
BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendNodeOrLayer, FrontendNodeType, FrontendXY, FrontendXY, Transform,
5+
BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNodeToRender, FrontendNodeType, FrontendXY, Transform,
66
};
77
use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer};
88
use crate::messages::portfolio::document::utility_types::wires::{WirePath, WirePathUpdate};

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use crate::messages::layout::utility_types::widget_prelude::*;
66
use crate::messages::portfolio::document::document_message_handler::navigation_controls;
77
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
88
use crate::messages::portfolio::document::node_graph::document_node_definitions::NodePropertiesContext;
9-
use crate::messages::portfolio::document::node_graph::utility_types::{
10-
ContextMenuData, Direction, FrontendGraphDataType, FrontendLayer, FrontendNodeMetadata, FrontendNodeOrLayer, FrontendXY, FrontendXY,
11-
};
9+
use crate::messages::portfolio::document::node_graph::utility_types::{ContextMenuData, Direction, FrontendGraphDataType, FrontendXY};
1210
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
1311
use crate::messages::portfolio::document::utility_types::misc::GroupFolderType;
1412
use crate::messages::portfolio::document::utility_types::network_interface::{
@@ -24,7 +22,7 @@ use crate::messages::tool::tool_messages::tool_prelude::{Key, MouseMotion};
2422
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
2523
use glam::{DAffine2, DVec2, IVec2};
2624
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput};
27-
use graph_craft::proto::{GraphErrors, NodeMetadata};
25+
use graph_craft::proto::GraphErrors;
2826
use graphene_std::math::math_ext::QuadExt;
2927
use graphene_std::vector::algorithms::bezpath_algorithms::bezpath_is_inside_bezpath;
3028
use graphene_std::*;
@@ -1638,7 +1636,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
16381636
responses.add(NodeGraphMessage::UpdateActionButtons);
16391637
if graph_view_overlay_open {
16401638
let nodes_to_render = network_interface.collect_nodes(&self.node_graph_errors, breadcrumb_network_path);
1641-
self.frontend_nodes = nodes_to_render.iter().map(|node| node.id).collect();
1639+
self.frontend_nodes = nodes_to_render.iter().map(|node| node.metadata.node_id).collect();
16421640
let previewed_node = network_interface.previewed_node(breadcrumb_network_path);
16431641
responses.add(FrontendMessage::UpdateNodeGraphNodes {
16441642
nodes_to_render,

editor/src/messages/portfolio/document/node_graph/utility_types.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ pub struct FrontendGraphOutput {
8989
// Metadata that is common to nodes and layers
9090
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
9191
pub struct FrontendNodeMetadata {
92+
#[serde(rename = "node_id")]
93+
pub node_id: NodeId,
9294
// TODO: Remove and replace with popup manager system
9395
#[serde(rename = "canBeLayer")]
9496
pub can_be_layer: bool,
@@ -125,7 +127,7 @@ pub struct FrontendLayer {
125127
#[serde(rename = "chainWidth")]
126128
pub chain_width: u32,
127129
#[serde(rename = "layerHasLeftBorderGap")]
128-
layer_has_left_border_gap: bool,
130+
pub layer_has_left_border_gap: bool,
129131
#[serde(rename = "primaryInputConnectedToLayer")]
130132
pub primary_input_connected_to_layer: bool,
131133
#[serde(rename = "primaryOutputConnectedToLayer")]
@@ -148,11 +150,17 @@ pub struct FrontendLayer {
148150

149151
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
150152
pub struct FrontendNodeOrLayer {
151-
pub metadata: FrontendNodeMetadata,
152153
pub node: Option<FrontendNode>,
153154
pub layer: Option<FrontendLayer>,
154155
}
155156

157+
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
158+
pub struct FrontendNodeToRender {
159+
pub metadata: FrontendNodeMetadata,
160+
#[serde(rename = "nodeOrLayer")]
161+
pub node_or_layer: FrontendNodeOrLayer,
162+
}
163+
156164
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
157165
pub struct FrontendNodeType {
158166
pub name: Cow<'static, str>,

editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs

Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ use graphene_std::uuid::NodeId;
55
use crate::{
66
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},
77
messages::portfolio::document::{
8-
node_graph::utility_types::{FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendXY},
8+
node_graph::utility_types::{
9+
FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput, FrontendLayer, FrontendNode, FrontendNodeMetadata, FrontendNodeOrLayer, FrontendNodeToRender, FrontendXY,
10+
},
911
utility_types::network_interface::{FlowType, InputConnector, NodeNetworkInterface, OutputConnector},
1012
},
1113
};
1214

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

25-
let primary_input_connector = InputConnector::node(node_id, 0);
26-
27-
let primary_input = if self.input_from_connector(&primary_input_connector, network_path).is_some_and(|input| input.is_exposed()) {
28-
self.frontend_input_from_connector(&primary_input_connector, network_path)
29-
} else {
30-
None
31-
};
32-
let exposed_inputs = (1..self.number_of_inputs(&node_id, network_path))
33-
.filter_map(|input_index| self.frontend_input_from_connector(&InputConnector::node(node_id, input_index), network_path))
34-
.collect();
35-
36-
let primary_output = self.frontend_output_from_connector(&OutputConnector::node(node_id, 0), network_path);
37-
38-
let exposed_outputs = (1..self.number_of_outputs(&node_id, network_path))
39-
.filter_map(|output_index| self.frontend_output_from_connector(&OutputConnector::node(node_id, output_index), network_path))
40-
.collect();
41-
42-
let Some(position) = self.position(&node_id, network_path) else {
43-
log::error!("Could not get position for node: {node_id}");
44-
continue;
45-
};
46-
let position = FrontendXY { x: position.x, y: position.y };
47-
let previewed = self.previewed_node(network_path) == Some(node_id);
48-
49-
let locked = self.is_locked(&node_id, network_path);
50-
5127
let errors = node_graph_errors
5228
.iter()
5329
.find(|error| error.node_path == node_id_path)
@@ -60,31 +36,73 @@ impl NodeNetworkInterface {
6036
}
6137
});
6238

63-
nodes.push(FrontendNode {
64-
id: node_id,
65-
is_layer: self.node_metadata(&node_id, network_path).is_some_and(|node_metadata| node_metadata.persistent_metadata.is_layer()),
39+
let metadata = FrontendNodeMetadata {
40+
node_id,
6641
can_be_layer: self.is_eligible_to_be_layer(&node_id, network_path),
42+
display_name: self.display_name(&node_id, network_path),
6743
selected: selected_nodes.0.contains(&node_id),
6844
reference: self.reference(&node_id, network_path).cloned().unwrap_or_default(),
69-
display_name: self.display_name(&node_id, network_path),
70-
previewed,
7145
visible,
7246
errors,
47+
};
7348

74-
primary_input,
75-
exposed_inputs,
76-
primary_output,
77-
exposed_outputs,
78-
position,
79-
80-
locked,
81-
chain_width: self.chain_width(&node_id, network_path),
82-
layer_has_left_border_gap: self.layer_has_left_border_gap(&node_id, network_path),
83-
primary_input_connected_to_layer: self.primary_output_connected_to_layer(&node_id, network_path),
84-
primary_output_connected_to_layer: self.primary_input_connected_to_layer(&node_id, network_path),
85-
});
86-
}
49+
let node_or_layer = match self.is_layer(&node_id, network_path) {
50+
true => {
51+
let Some(position) = self.position(&node_id, network_path) else {
52+
log::error!("Could not get position for node: {node_id}");
53+
continue;
54+
};
55+
let position = FrontendXY { x: position.x, y: position.y };
56+
57+
let Some(bottom_input) = self.frontend_input_from_connector(&InputConnector::node(node_id, 0), network_path) else {
58+
log::error!("Layer must have a visible primary input");
59+
continue;
60+
};
61+
let side_input = self.frontend_input_from_connector(&InputConnector::node(node_id, 1), network_path);
62+
let Some(output) = self.frontend_output_from_connector(&OutputConnector::node(node_id, 0), network_path) else {
63+
log::error!("Layer must have a visible primary output");
64+
continue;
65+
};
66+
67+
let layer = Some(FrontendLayer {
68+
bottom_input,
69+
side_input,
70+
output,
71+
position,
72+
locked: self.is_locked(&node_id, network_path),
73+
chain_width: self.chain_width(&node_id, network_path),
74+
layer_has_left_border_gap: self.layer_has_left_border_gap(&node_id, network_path),
75+
primary_input_connected_to_layer: self.primary_output_connected_to_layer(&node_id, network_path),
76+
primary_output_connected_to_layer: self.primary_input_connected_to_layer(&node_id, network_path),
77+
});
78+
FrontendNodeOrLayer { node: None, layer }
79+
}
80+
false => {
81+
let Some(position) = self.position(&node_id, network_path) else {
82+
log::error!("Could not get position for node: {node_id}");
83+
continue;
84+
};
85+
86+
let position = FrontendXY { x: position.x, y: position.y };
87+
88+
let inputs = (0..self.number_of_inputs(&node_id, network_path))
89+
.map(|input_index| self.frontend_input_from_connector(&InputConnector::node(node_id, input_index), network_path))
90+
.collect();
8791

92+
let outputs = (0..self.number_of_outputs(&node_id, network_path))
93+
.map(|output_index| self.frontend_output_from_connector(&OutputConnector::node(node_id, output_index), network_path))
94+
.collect();
95+
96+
let node = Some(FrontendNode { position, inputs, outputs });
97+
98+
FrontendNodeOrLayer { node, layer: None }
99+
}
100+
};
101+
102+
let frontend_node_to_render = FrontendNodeToRender { metadata, node_or_layer };
103+
104+
nodes.push(frontend_node_to_render);
105+
}
88106
nodes
89107
}
90108

@@ -146,12 +164,15 @@ impl NodeNetworkInterface {
146164
// }
147165
// };
148166

167+
let connected_to_node = self.upstream_output_connector(input_connector, network_path).and_then(|output_connector| output_connector.node_id());
168+
149169
Some(FrontendGraphInput {
150170
data_type,
151171
resolved_type,
152172
name,
153173
description,
154174
connected_to,
175+
connected_to_node,
155176
})
156177
}
157178

frontend/src/messages.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export class UpdateLayerWidths extends JsMessage {
7979
}
8080

8181
export class UpdateNodeGraphNodes extends JsMessage {
82-
readonly nodesToRender!: FrontendNode[];
82+
readonly nodesToRender!: FrontendNodeToRender[];
8383

8484
readonly inSelectedNetwork!: boolean;
8585

@@ -201,6 +201,8 @@ export class FrontendGraphOutput {
201201
}
202202

203203
export class FrontendNodeMetadata {
204+
readonly nodeId!: bigint;
205+
204206
readonly canBeLayer!: boolean;
205207

206208
readonly displayName!: string;
@@ -257,11 +259,15 @@ export class FrontendLayerPosition {
257259
}
258260

259261
export class FrontendNodeOrLayer {
260-
readonly metadata!: FrontendNodeMetadata;
261262
readonly node!: FrontendNode | undefined;
262263
readonly layer!: FrontendLayer | undefined;
263264
}
264265

266+
export class FrontendNodeToRender {
267+
readonly metadata!: FrontendNodeMetadata;
268+
readonly nodeOrLayer!: FrontendNodeOrLayer;
269+
}
270+
265271
export class UpdateCentralNodeGraph extends JsMessage {
266272
readonly nodeOrLayer!: FrontendNodeOrLayer[];
267273
readonly inSelectedNetwork!: boolean;

frontend/src/state-providers/node-graph.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { writable } from "svelte/store";
22

33
import { type Editor } from "@graphite/editor";
4-
import type { FrontendNodeOrLayer } from "@graphite/messages";
54
import {
65
type Box,
76
type FrontendClickTargets,
87
type ContextMenuInformation,
8+
type FrontendNodeToRender,
99
type FrontendNodeType,
1010
type WirePath,
1111
ClearAllNodeGraphWires,
@@ -103,7 +103,7 @@ export function createNodeGraphState(editor: Editor) {
103103
update((state) => {
104104
state.nodesToRender.clear();
105105
updateNodeGraphNodes.nodesToRender.forEach((node) => {
106-
state.nodesToRender.set(node.id, node);
106+
state.nodesToRender.set(node.metadata.nodeId, node);
107107
});
108108
state.inSelectedNetwork = updateNodeGraphNodes.inSelectedNetwork;
109109
state.previewedNode = updateNodeGraphNodes.previewedNode;

0 commit comments

Comments
 (0)