Skip to content

Commit 7afbeaa

Browse files
adamgerhantKeavon
andauthored
Separate graph error diagnostics from frontend node metadata (#3385)
* Separate error popup from node * Improve context menu data * Code review --------- Co-authored-by: Keavon Chambers <[email protected]>
1 parent 548e0df commit 7afbeaa

File tree

7 files changed

+193
-157
lines changed

7 files changed

+193
-157
lines changed

editor/src/messages/frontend/frontend_message.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::utility_types::{DocumentDetails, MouseCursorIcon, OpenDocument};
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, FrontendNodeType, Transform,
5+
BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendNodeType, NodeGraphErrorDiagnostic, 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};
@@ -289,6 +289,9 @@ pub enum FrontendMessage {
289289
UpdateNodeGraphNodes {
290290
nodes: Vec<FrontendNode>,
291291
},
292+
UpdateNodeGraphErrorDiagnostic {
293+
error: Option<NodeGraphErrorDiagnostic>,
294+
},
292295
UpdateVisibleNodes {
293296
nodes: Vec<NodeId>,
294297
},

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

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +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::{ContextMenuData, Direction, FrontendGraphDataType};
9+
use crate::messages::portfolio::document::node_graph::utility_types::{ContextMenuData, Direction, FrontendGraphDataType, NodeGraphErrorDiagnostic};
1010
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
1111
use crate::messages::portfolio::document::utility_types::misc::GroupFolderType;
1212
use crate::messages::portfolio::document::utility_types::network_interface::{
@@ -776,8 +776,13 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
776776
}
777777

778778
let context_menu_data = if let Some(node_id) = clicked_id {
779-
let currently_is_node = !network_interface.is_layer(&node_id, selection_network_path);
780-
ContextMenuData::ToggleLayer { node_id, currently_is_node }
779+
let currently_is_node = !network_interface.is_layer(&node_id, breadcrumb_network_path);
780+
let can_be_layer = network_interface.is_eligible_to_be_layer(&node_id, breadcrumb_network_path);
781+
ContextMenuData::ModifyNode {
782+
can_be_layer,
783+
currently_is_node,
784+
node_id,
785+
}
781786
} else {
782787
ContextMenuData::CreateNode { compatible_type: None }
783788
};
@@ -793,10 +798,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
793798
DVec2::new(appear_right_of_mouse, appear_above_mouse) / network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.matrix2.x_axis.x
794799
};
795800

796-
let context_menu_coordinates = ((node_graph_point.x + node_graph_shift.x) as i32, (node_graph_point.y + node_graph_shift.y) as i32);
797-
798801
self.context_menu = Some(ContextMenuInformation {
799-
context_menu_coordinates,
802+
context_menu_coordinates: (node_graph_point + node_graph_shift).into(),
800803
context_menu_data,
801804
});
802805

@@ -1222,7 +1225,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
12221225
let compatible_type = network_interface.output_type(&output_connector, selection_network_path).add_node_string();
12231226

12241227
self.context_menu = Some(ContextMenuInformation {
1225-
context_menu_coordinates: ((point.x + node_graph_shift.x) as i32, (point.y + node_graph_shift.y) as i32),
1228+
context_menu_coordinates: (point + node_graph_shift).into(),
12261229
context_menu_data: ContextMenuData::CreateNode { compatible_type },
12271230
});
12281231

@@ -1646,6 +1649,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
16461649
responses.add(FrontendMessage::UpdateNodeGraphNodes { nodes });
16471650
responses.add(NodeGraphMessage::UpdateVisibleNodes);
16481651

1652+
let error = self.node_graph_error(network_interface, breadcrumb_network_path);
1653+
responses.add(FrontendMessage::UpdateNodeGraphErrorDiagnostic { error });
16491654
let (layer_widths, chain_widths, has_left_input_wire) = network_interface.collect_layer_widths(breadcrumb_network_path);
16501655

16511656
responses.add(NodeGraphMessage::UpdateImportsExports);
@@ -2509,8 +2514,6 @@ impl NodeGraphMessageHandler {
25092514
};
25102515
let mut nodes = Vec::new();
25112516
for (node_id, visible) in network.nodes.iter().map(|(node_id, node)| (*node_id, node.visible)).collect::<Vec<_>>() {
2512-
let node_id_path = [breadcrumb_network_path, &[node_id]].concat();
2513-
25142517
let primary_input_connector = InputConnector::node(node_id, 0);
25152518

25162519
let primary_input = if network_interface
@@ -2552,20 +2555,6 @@ impl NodeGraphMessageHandler {
25522555

25532556
let locked = network_interface.is_locked(&node_id, breadcrumb_network_path);
25542557

2555-
let errors = network_interface
2556-
.resolved_types
2557-
.node_graph_errors
2558-
.iter()
2559-
.find(|error| error.node_path == node_id_path)
2560-
.map(|error| format!("{:?}", error.error.clone()))
2561-
.or_else(|| {
2562-
if network_interface.resolved_types.node_graph_errors.iter().any(|error| error.node_path.starts_with(&node_id_path)) {
2563-
Some("Node graph type error within this node".to_string())
2564-
} else {
2565-
None
2566-
}
2567-
});
2568-
25692558
nodes.push(FrontendNode {
25702559
id: node_id,
25712560
is_layer: network_interface
@@ -2584,7 +2573,6 @@ impl NodeGraphMessageHandler {
25842573
previewed,
25852574
visible,
25862575
locked,
2587-
errors,
25882576
});
25892577
}
25902578

@@ -2606,6 +2594,29 @@ impl NodeGraphMessageHandler {
26062594
Some(subgraph_names)
26072595
}
26082596

2597+
fn node_graph_error(&self, network_interface: &mut NodeNetworkInterface, breadcrumb_network_path: &[NodeId]) -> Option<NodeGraphErrorDiagnostic> {
2598+
let graph_error = network_interface
2599+
.resolved_types
2600+
.node_graph_errors
2601+
.iter()
2602+
.find(|error| error.node_path.starts_with(breadcrumb_network_path) && error.node_path.len() > breadcrumb_network_path.len())?;
2603+
let error = if graph_error.node_path.len() == breadcrumb_network_path.len() + 1 {
2604+
format!("{:?}", graph_error.error)
2605+
} else {
2606+
"Node graph type error within this node".to_string()
2607+
};
2608+
let error_node = graph_error.node_path[breadcrumb_network_path.len()];
2609+
2610+
let mut position = network_interface.position(&error_node, breadcrumb_network_path)?;
2611+
// Convert to graph space
2612+
position *= 24;
2613+
if network_interface.is_layer(&error_node, breadcrumb_network_path) {
2614+
position += IVec2::new(12, -12)
2615+
}
2616+
2617+
Some(NodeGraphErrorDiagnostic { position: position.into(), error })
2618+
}
2619+
26092620
fn update_layer_panel(network_interface: &NodeNetworkInterface, selection_network_path: &[NodeId], collapsed: &CollapsedLayers, layers_panel_open: bool, responses: &mut VecDeque<Message>) {
26102621
if !layers_panel_open {
26112622
return;

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

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use glam::IVec2;
1+
use glam::{DVec2, IVec2};
22
use graph_craft::document::NodeId;
33
use graph_craft::document::value::TaggedValue;
44
use graphene_std::Type;
@@ -90,15 +90,14 @@ pub struct FrontendNode {
9090
pub primary_output: Option<FrontendGraphOutput>,
9191
#[serde(rename = "exposedOutputs")]
9292
pub exposed_outputs: Vec<FrontendGraphOutput>,
93-
#[serde(rename = "primaryOutputConnectedToLayer")]
94-
pub primary_output_connected_to_layer: bool,
9593
#[serde(rename = "primaryInputConnectedToLayer")]
9694
pub primary_input_connected_to_layer: bool,
95+
#[serde(rename = "primaryOutputConnectedToLayer")]
96+
pub primary_output_connected_to_layer: bool,
9797
pub position: IVec2,
98+
pub previewed: bool,
9899
pub visible: bool,
99100
pub locked: bool,
100-
pub previewed: bool,
101-
pub errors: Option<String>,
102101
}
103102

104103
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
@@ -154,16 +153,18 @@ pub struct BoxSelection {
154153
}
155154

156155
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
156+
#[serde(tag = "type", content = "data")]
157157
pub enum ContextMenuData {
158-
ToggleLayer {
158+
ModifyNode {
159159
#[serde(rename = "nodeId")]
160160
node_id: NodeId,
161+
#[serde(rename = "canBeLayer")]
162+
can_be_layer: bool,
161163
#[serde(rename = "currentlyIsNode")]
162164
currently_is_node: bool,
163165
},
164166
CreateNode {
165167
#[serde(rename = "compatibleType")]
166-
#[serde(default)]
167168
compatible_type: Option<String>,
168169
},
169170
}
@@ -172,11 +173,17 @@ pub enum ContextMenuData {
172173
pub struct ContextMenuInformation {
173174
// Stores whether the context menu is open and its position in graph coordinates
174175
#[serde(rename = "contextMenuCoordinates")]
175-
pub context_menu_coordinates: (i32, i32),
176+
pub context_menu_coordinates: FrontendXY,
176177
#[serde(rename = "contextMenuData")]
177178
pub context_menu_data: ContextMenuData,
178179
}
179180

181+
#[derive(Clone, Debug, PartialEq, Default, serde::Serialize, serde::Deserialize, specta::Type)]
182+
pub struct NodeGraphErrorDiagnostic {
183+
pub position: FrontendXY,
184+
pub error: String,
185+
}
186+
180187
#[derive(Clone, Debug, PartialEq, Default, serde::Serialize, serde::Deserialize, specta::Type)]
181188
pub struct FrontendClickTargets {
182189
#[serde(rename = "nodeClickTargets")]
@@ -200,3 +207,22 @@ pub enum Direction {
200207
Left,
201208
Right,
202209
}
210+
211+
/// Stores node graph coordinates which are then transformed in Svelte based on the node graph transform
212+
#[derive(Clone, Debug, PartialEq, Default, serde::Serialize, serde::Deserialize, specta::Type)]
213+
pub struct FrontendXY {
214+
pub x: i32,
215+
pub y: i32,
216+
}
217+
218+
impl From<DVec2> for FrontendXY {
219+
fn from(v: DVec2) -> Self {
220+
FrontendXY { x: v.x as i32, y: v.y as i32 }
221+
}
222+
}
223+
224+
impl From<IVec2> for FrontendXY {
225+
fn from(v: IVec2) -> Self {
226+
FrontendXY { x: v.x, y: v.y }
227+
}
228+
}

editor/src/test_utils.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,9 @@ pub trait FrontendMessageTestUtils {
326326

327327
impl FrontendMessageTestUtils for FrontendMessage {
328328
fn check_node_graph_error(&self) {
329-
let FrontendMessage::UpdateNodeGraphNodes { nodes, .. } = self else { return };
330-
331-
for node in nodes {
332-
if let Some(error) = &node.errors {
333-
panic!("error on {}: {}", node.display_name, error);
334-
}
329+
let FrontendMessage::UpdateNodeGraphErrorDiagnostic { error } = self else { return };
330+
if let Some(error) = error {
331+
panic!("error: {:?}", error);
335332
}
336333
}
337334
}

0 commit comments

Comments
 (0)