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
1 change: 1 addition & 0 deletions editor/src/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
))),
Expand Down
26 changes: 10 additions & 16 deletions editor/src/messages/frontend/frontend_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -131,18 +130,14 @@ pub enum FrontendMessage {
exports: Vec<Option<FrontendGraphInput>>,
/// 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<BoxSelection>,
Expand Down Expand Up @@ -183,10 +178,6 @@ pub enum FrontendMessage {
UpdateLayerWidths {
#[serde(rename = "layerWidths")]
layer_widths: HashMap<NodeId, u32>,
#[serde(rename = "chainWidths")]
chain_widths: HashMap<NodeId, u32>,
#[serde(rename = "hasLeftInputWire")]
has_left_input_wire: HashMap<NodeId, bool>,
},
UpdateDialogButtons {
#[serde(rename = "layoutTarget")]
Expand Down Expand Up @@ -282,7 +273,13 @@ pub enum FrontendMessage {
cursor: MouseCursorIcon,
},
UpdateNodeGraphNodes {
nodes: Vec<FrontendNode>,
#[serde(rename = "nodesToRender")]
nodes_to_render: Vec<FrontendNode>,
#[serde(rename = "inSelectedNetwork")]
in_selected_network: bool,
// Displays a dashed border around the node
#[serde(rename = "previewedNode")]
previewed_node: Option<NodeId>,
},
UpdateVisibleNodes {
nodes: Vec<NodeId>,
Expand All @@ -296,9 +293,6 @@ pub enum FrontendMessage {
layout_target: LayoutTarget,
diff: Vec<WidgetDiff>,
},
UpdateNodeGraphSelection {
selected: Vec<NodeId>,
},
UpdateNodeGraphTransform {
transform: Transform,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> 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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,5 @@ pub enum NodeGraphMessage {
},
UpdateActionButtons,
UpdateGraphBarRight,
UpdateInSelectedNetwork,
UpdateHints,
SendSelectedNodes,
}
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -192,7 +192,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> 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);
Expand Down Expand Up @@ -1633,21 +1633,22 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> 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);
}
Expand Down Expand Up @@ -1956,6 +1957,15 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> 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();

Expand Down Expand Up @@ -2000,22 +2010,9 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> 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::<Vec<_>>(),
});
}
}
let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(selection_network_path) else {
log::error!("Could not get selected nodes in NodeGraphMessageHandler");
Expand Down
14 changes: 12 additions & 2 deletions editor/src/messages/portfolio/document/node_graph/utility_types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use glam::IVec2;
use graph_craft::document::NodeId;
use graph_craft::document::value::TaggedValue;
use graphene_std::Type;
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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<String>,
#[serde(rename = "displayName")]
pub display_name: String,
Expand All @@ -96,11 +102,15 @@ pub struct FrontendNode {
pub primary_output: Option<FrontendGraphOutput>,
#[serde(rename = "exposedOutputs")]
pub exposed_outputs: Vec<FrontendGraphOutput>,
#[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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<NodeId, u32>, HashMap<NodeId, u32>, HashMap<NodeId, bool>) {
// TODO: Remove and get layer click targets from render output
pub fn collect_layer_widths(&mut self, network_path: &[NodeId]) -> HashMap<NodeId, u32> {
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
Expand All @@ -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::<HashMap<NodeId, u32>>();
let chain_widths = nodes.iter().map(|node_id| (*node_id, self.chain_width(node_id, network_path))).collect::<HashMap<NodeId, u32>>();
let has_left_input_wire = nodes
.iter()
.map(|node_id| (*node_id, self.layer_has_left_border_gap(node_id, network_path)))
.collect::<HashMap<NodeId, bool>>();

(layer_widths, chain_widths, has_left_input_wire)
layer_widths
}

pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option<Vector> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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},
},
};
Expand All @@ -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::<Vec<_>>() {
let node_id_path = [network_path, &[node_id]].concat();
Expand All @@ -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);
Expand All @@ -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),
});
}

Expand Down Expand Up @@ -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
Expand Down
Loading
Loading