mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 23:38:06 +08:00
Complete separating node rendering from imports/exports
This commit is contained in:
@@ -2,10 +2,10 @@ use super::utility_types::{DocumentDetails, MouseCursorIcon, OpenDocument};
|
||||
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, FrontendNodeToRender, FrontendNodeType, FrontendXY, Transform,
|
||||
BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendExports, FrontendImport, 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};
|
||||
use crate::messages::portfolio::document::utility_types::wires::WirePathInProgress;
|
||||
use crate::messages::prelude::*;
|
||||
use crate::messages::tool::utility_types::HintData;
|
||||
use graph_craft::document::NodeId;
|
||||
@@ -127,9 +127,8 @@ pub enum FrontendMessage {
|
||||
},
|
||||
UpdateImportsExports {
|
||||
/// If the primary import is not visible, then it is None.
|
||||
imports: Vec<Option<FrontendGraphOutput>>,
|
||||
/// If the primary export is not visible, then it is None.
|
||||
exports: Vec<Option<FrontendGraphInput>>,
|
||||
imports: Vec<Option<FrontendImport>>,
|
||||
exports: FrontendExports,
|
||||
/// The primary import location.
|
||||
#[serde(rename = "importPosition")]
|
||||
import_position: FrontendXY,
|
||||
@@ -140,7 +139,7 @@ pub enum FrontendMessage {
|
||||
#[serde(rename = "addImportExport")]
|
||||
add_import_export: bool,
|
||||
},
|
||||
UpdateBox {
|
||||
UpdateNodeGraphSelectionBox {
|
||||
#[serde(rename = "box")]
|
||||
box_selection: Option<BoxSelection>,
|
||||
},
|
||||
@@ -285,10 +284,6 @@ pub enum FrontendMessage {
|
||||
UpdateVisibleNodes {
|
||||
nodes: Vec<NodeId>,
|
||||
},
|
||||
UpdateNodeGraphWires {
|
||||
wires: Vec<WirePathUpdate>,
|
||||
},
|
||||
ClearAllNodeGraphWires,
|
||||
UpdateNodeGraphControlBarLayout {
|
||||
#[serde(rename = "layoutTarget")]
|
||||
layout_target: LayoutTarget,
|
||||
@@ -321,8 +316,8 @@ pub enum FrontendMessage {
|
||||
diff: Vec<WidgetDiff>,
|
||||
},
|
||||
UpdateWirePathInProgress {
|
||||
#[serde(rename = "wirePath")]
|
||||
wire_path: Option<WirePath>,
|
||||
#[serde(rename = "wirePathInProgress")]
|
||||
wire_path_in_progress: Option<WirePathInProgress>,
|
||||
},
|
||||
UpdateWorkingColorsLayout {
|
||||
#[serde(rename = "layoutTarget")]
|
||||
|
||||
@@ -474,7 +474,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
DocumentMessage::EnterNestedNetwork { node_id } => {
|
||||
self.breadcrumb_network_path.push(node_id);
|
||||
self.selection_network_path.clone_from(&self.breadcrumb_network_path);
|
||||
responses.add(NodeGraphMessage::UnloadWires);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(DocumentMessage::ZoomCanvasToFitAll);
|
||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
||||
@@ -494,7 +493,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
responses.add(FrontendMessage::UpdateContextMenuInformation { context_menu_information: None });
|
||||
self.node_graph_handler.wire_in_progress_from_connector = None;
|
||||
self.node_graph_handler.wire_in_progress_to_connector = None;
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: None });
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path_in_progress: None });
|
||||
} else {
|
||||
responses.add(DocumentMessage::GraphViewOverlay { open: false });
|
||||
}
|
||||
@@ -504,7 +503,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
self.breadcrumb_network_path.pop();
|
||||
self.selection_network_path.clone_from(&self.breadcrumb_network_path);
|
||||
}
|
||||
responses.add(NodeGraphMessage::UnloadWires);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(DocumentMessage::PTZUpdate);
|
||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
||||
@@ -557,7 +555,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
}
|
||||
}
|
||||
DocumentMessage::GraphViewOverlay { open } => {
|
||||
let opened = !self.graph_view_overlay_open && open;
|
||||
self.graph_view_overlay_open = open;
|
||||
|
||||
responses.add(FrontendMessage::UpdateGraphViewOverlay { open });
|
||||
@@ -567,9 +564,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
|
||||
responses.add(DocumentMessage::RenderRulers);
|
||||
responses.add(DocumentMessage::RenderScrollbars);
|
||||
if opened {
|
||||
responses.add(NodeGraphMessage::UnloadWires);
|
||||
}
|
||||
if open {
|
||||
responses.add(ToolMessage::DeactivateTools);
|
||||
responses.add(OverlaysMessage::Draw); // Clear the overlays
|
||||
@@ -1949,7 +1943,6 @@ impl DocumentMessageHandler {
|
||||
responses.add(NodeGraphMessage::ForceRunDocumentGraph);
|
||||
|
||||
// TODO: Remove once the footprint is used to load the imports/export distances from the edge
|
||||
responses.add(NodeGraphMessage::UnloadWires);
|
||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
||||
|
||||
Some(previous_network)
|
||||
@@ -1981,8 +1974,6 @@ impl DocumentMessageHandler {
|
||||
responses.add(PortfolioMessage::UpdateOpenDocumentsList);
|
||||
responses.add(NodeGraphMessage::SelectedNodesUpdated);
|
||||
responses.add(NodeGraphMessage::ForceRunDocumentGraph);
|
||||
responses.add(NodeGraphMessage::UnloadWires);
|
||||
responses.add(NodeGraphMessage::SendWires);
|
||||
Some(previous_network)
|
||||
}
|
||||
|
||||
|
||||
@@ -139,8 +139,6 @@ pub enum NodeGraphMessage {
|
||||
},
|
||||
SendClickTargets,
|
||||
EndSendClickTargets,
|
||||
UnloadWires,
|
||||
SendWires,
|
||||
UpdateVisibleNodes,
|
||||
SendGraph,
|
||||
SetGridAlignedEdges,
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::messages::portfolio::document::utility_types::network_interface::{
|
||||
self, FlowType, InputConnector, NodeNetworkInterface, NodeTemplate, NodeTypePersistentMetadata, OutputConnector, Previewing,
|
||||
};
|
||||
use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, LayerPanelEntry};
|
||||
use crate::messages::portfolio::document::utility_types::wires::{GraphWireStyle, WirePath, WirePathUpdate, build_vector_wire};
|
||||
use crate::messages::portfolio::document::utility_types::wires::{GraphWireStyle, WirePathInProgress, build_vector_wire};
|
||||
use crate::messages::prelude::*;
|
||||
use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils::get_clip_mode;
|
||||
@@ -93,8 +93,6 @@ pub struct NodeGraphMessageHandler {
|
||||
end_index: Option<usize>,
|
||||
/// Used to keep track of what nodes are sent to the front end so that only visible ones are sent to the frontend
|
||||
frontend_nodes: Vec<NodeId>,
|
||||
/// Used to keep track of what wires are sent to the front end so the old ones can be removed
|
||||
frontend_wires: HashSet<(NodeId, usize)>,
|
||||
}
|
||||
|
||||
/// NodeGraphMessageHandler always modifies the network which the selected nodes are in. No GraphOperationMessages should be added here, since those messages will always affect the document network.
|
||||
@@ -297,7 +295,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
self.wire_in_progress_type = FrontendGraphDataType::General;
|
||||
self.wire_in_progress_to_connector = None;
|
||||
}
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: None });
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path_in_progress: None });
|
||||
responses.add(FrontendMessage::UpdateContextMenuInformation {
|
||||
context_menu_information: self.context_menu.clone(),
|
||||
});
|
||||
@@ -470,7 +468,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
}
|
||||
|
||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||
responses.add(NodeGraphMessage::SendWires);
|
||||
}
|
||||
NodeGraphMessage::ExposePrimaryExport { exposed } => {
|
||||
let export_connector: InputConnector = InputConnector::Export(0);
|
||||
@@ -761,7 +758,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet {
|
||||
nodes: self.selection_before_pointer_down.clone(),
|
||||
});
|
||||
responses.add(FrontendMessage::UpdateBox { box_selection: None });
|
||||
responses.add(FrontendMessage::UpdateNodeGraphSelectionBox { box_selection: None });
|
||||
return;
|
||||
}
|
||||
// Abort dragging a wire
|
||||
@@ -770,7 +767,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
self.wire_in_progress_type = FrontendGraphDataType::General;
|
||||
self.wire_in_progress_to_connector = None;
|
||||
responses.add(DocumentMessage::AbortTransaction);
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: None });
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path_in_progress: None });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -851,7 +848,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
responses.add(FrontendMessage::UpdateContextMenuInformation {
|
||||
context_menu_information: self.context_menu.clone(),
|
||||
});
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: None });
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path_in_progress: None });
|
||||
}
|
||||
|
||||
// Toggle visibility of clicked node and return
|
||||
@@ -1058,14 +1055,14 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
to_connector_is_layer,
|
||||
GraphWireStyle::Direct,
|
||||
);
|
||||
let path_string = vector_wire.to_svg();
|
||||
let wire_path = WirePath {
|
||||
path_string,
|
||||
let wire_path = WirePathInProgress {
|
||||
wire: vector_wire.to_svg(),
|
||||
data_type: self.wire_in_progress_type,
|
||||
thick: false,
|
||||
dashed: false,
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: Some(wire_path) });
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress {
|
||||
wire_path_in_progress: Some(wire_path),
|
||||
});
|
||||
}
|
||||
} else if let Some((drag_start, dragged)) = &mut self.drag_start {
|
||||
if drag_start.start_x != point.x || drag_start.start_y != point.y {
|
||||
@@ -1315,7 +1312,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
return None;
|
||||
}
|
||||
|
||||
let (wire, is_stack) = network_interface.vector_wire_from_input(&input, preferences.graph_wire_style, selection_network_path)?;
|
||||
let wire = network_interface.wire_from_input(&input, preferences.graph_wire_style, selection_network_path)?;
|
||||
let thick = network_interface.wire_is_thick(&input, selection_network_path);
|
||||
|
||||
let node_bbox = kurbo::Rect::new(node_bbox[0].x, node_bbox[0].y, node_bbox[1].x, node_bbox[1].y).to_path(DEFAULT_ACCURACY);
|
||||
let inside = bezpath_is_inside_bezpath(&wire, &node_bbox, None, None);
|
||||
@@ -1324,7 +1322,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
.segments()
|
||||
.any(|segment| node_bbox.segments().filter_map(|segment| segment.as_line()).any(|line| !segment.intersect_line(line).is_empty()));
|
||||
|
||||
(intersect || inside).then_some((input, is_stack))
|
||||
(intersect || inside).then_some((input, thick))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -1391,8 +1389,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
self.reordering_export = None;
|
||||
self.reordering_import = None;
|
||||
responses.add(DocumentMessage::EndTransaction);
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path: None });
|
||||
responses.add(FrontendMessage::UpdateBox { box_selection: None });
|
||||
responses.add(FrontendMessage::UpdateWirePathInProgress { wire_path_in_progress: None });
|
||||
responses.add(FrontendMessage::UpdateNodeGraphSelectionBox { box_selection: None });
|
||||
responses.add(FrontendMessage::UpdateImportReorderIndex { index: None });
|
||||
responses.add(FrontendMessage::UpdateExportReorderIndex { index: None });
|
||||
self.update_node_graph_hints(responses);
|
||||
@@ -1591,17 +1589,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
click_targets: Some(network_interface.collect_frontend_click_targets(breadcrumb_network_path)),
|
||||
}),
|
||||
NodeGraphMessage::EndSendClickTargets => responses.add(FrontendMessage::UpdateClickTargets { click_targets: None }),
|
||||
NodeGraphMessage::UnloadWires => {
|
||||
for input in network_interface.node_graph_input_connectors(breadcrumb_network_path) {
|
||||
network_interface.unload_wire(&input, breadcrumb_network_path);
|
||||
}
|
||||
|
||||
responses.add(FrontendMessage::ClearAllNodeGraphWires);
|
||||
}
|
||||
NodeGraphMessage::SendWires => {
|
||||
let wires = self.collect_wires(network_interface, preferences.graph_wire_style, breadcrumb_network_path);
|
||||
responses.add(FrontendMessage::UpdateNodeGraphWires { wires });
|
||||
}
|
||||
NodeGraphMessage::UpdateVisibleNodes => {
|
||||
let Some(network_metadata) = network_interface.network_metadata(breadcrumb_network_path) else {
|
||||
return;
|
||||
@@ -1634,7 +1621,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
responses.add(DocumentMessage::DocumentStructureChanged);
|
||||
responses.add(PropertiesPanelMessage::Refresh);
|
||||
responses.add(NodeGraphMessage::UpdateActionButtons);
|
||||
let nodes_to_render = network_interface.collect_nodes(&self.node_graph_errors, breadcrumb_network_path);
|
||||
let nodes_to_render = network_interface.collect_nodes(&self.node_graph_errors, preferences.graph_wire_style, breadcrumb_network_path);
|
||||
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::UpdateNodeGraphRender {
|
||||
@@ -1650,7 +1637,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
|
||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||
responses.add(FrontendMessage::UpdateLayerWidths { layer_widths });
|
||||
responses.add(NodeGraphMessage::SendWires);
|
||||
self.update_node_graph_hints(responses);
|
||||
}
|
||||
NodeGraphMessage::SetGridAlignedEdges => {
|
||||
@@ -1725,8 +1711,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
Ordering::Equal => {}
|
||||
}
|
||||
}
|
||||
|
||||
responses.add(NodeGraphMessage::SendWires);
|
||||
}
|
||||
NodeGraphMessage::ToggleSelectedAsLayersOrNodes => {
|
||||
let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(selection_network_path) else {
|
||||
@@ -1746,8 +1730,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
}
|
||||
NodeGraphMessage::ShiftNodePosition { node_id, x, y } => {
|
||||
network_interface.shift_absolute_node_position(&node_id, IVec2::new(x, y), selection_network_path);
|
||||
|
||||
responses.add(NodeGraphMessage::SendWires);
|
||||
}
|
||||
NodeGraphMessage::SetToNodeOrLayer { node_id, is_layer } => {
|
||||
if is_layer && !network_interface.is_eligible_to_be_layer(&node_id, selection_network_path) {
|
||||
@@ -1761,7 +1743,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
});
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(NodeGraphMessage::SendWires);
|
||||
}
|
||||
NodeGraphMessage::SetDisplayName {
|
||||
node_id,
|
||||
@@ -1945,12 +1926,12 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
nodes: nodes.into_iter().collect::<Vec<_>>(),
|
||||
});
|
||||
}
|
||||
responses.add(FrontendMessage::UpdateBox { box_selection })
|
||||
responses.add(FrontendMessage::UpdateNodeGraphSelectionBox { box_selection })
|
||||
}
|
||||
}
|
||||
NodeGraphMessage::UpdateImportsExports => {
|
||||
let imports = network_interface.frontend_imports(breadcrumb_network_path);
|
||||
let exports = network_interface.frontend_exports(breadcrumb_network_path);
|
||||
let imports = network_interface.frontend_imports(preferences.graph_wire_style, breadcrumb_network_path);
|
||||
let exports = network_interface.frontend_exports(preferences.graph_wire_style, breadcrumb_network_path);
|
||||
|
||||
let Some((import_position, export_position)) = network_interface.import_export_position(breadcrumb_network_path) else {
|
||||
log::error!("Could not get import export positions");
|
||||
@@ -1970,7 +1951,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
let add_import_export = !breadcrumb_network_path.is_empty();
|
||||
|
||||
responses.add(NodeGraphMessage::UpdateVisibleNodes);
|
||||
responses.add(NodeGraphMessage::SendWires);
|
||||
responses.add(FrontendMessage::UpdateImportsExports {
|
||||
imports,
|
||||
exports,
|
||||
@@ -2461,41 +2441,6 @@ impl NodeGraphMessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_wires(&mut self, network_interface: &mut NodeNetworkInterface, graph_wire_style: GraphWireStyle, breadcrumb_network_path: &[NodeId]) -> Vec<WirePathUpdate> {
|
||||
let mut added_wires = network_interface
|
||||
.node_graph_input_connectors(breadcrumb_network_path)
|
||||
.iter()
|
||||
.filter_map(|connector| network_interface.newly_loaded_input_wire(connector, graph_wire_style, breadcrumb_network_path))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let changed_wire_inputs = added_wires.iter().map(|update| (update.id, update.input_index)).collect::<Vec<_>>();
|
||||
self.frontend_wires.extend(changed_wire_inputs);
|
||||
|
||||
let mut orphaned_wire_inputs = self.frontend_wires.clone();
|
||||
self.frontend_wires = network_interface
|
||||
.node_graph_wire_inputs(breadcrumb_network_path)
|
||||
.iter()
|
||||
.filter_map(|visible_wire_input| orphaned_wire_inputs.take(visible_wire_input))
|
||||
.collect::<HashSet<_>>();
|
||||
added_wires.extend(orphaned_wire_inputs.into_iter().map(|(id, input_index)| WirePathUpdate {
|
||||
id,
|
||||
input_index,
|
||||
wire_path_update: None,
|
||||
}));
|
||||
|
||||
if let Some(wire_to_root) = network_interface.wire_to_root(graph_wire_style, breadcrumb_network_path) {
|
||||
added_wires.push(wire_to_root);
|
||||
} else {
|
||||
added_wires.push(WirePathUpdate {
|
||||
id: NodeId(u64::MAX),
|
||||
input_index: u32::MAX as usize,
|
||||
wire_path_update: None,
|
||||
})
|
||||
}
|
||||
|
||||
added_wires
|
||||
}
|
||||
|
||||
fn collect_subgraph_names(network_interface: &mut NodeNetworkInterface, breadcrumb_network_path: &[NodeId]) -> Option<Vec<String>> {
|
||||
let mut current_network_path = vec![];
|
||||
let mut current_network = network_interface.nested_network(¤t_network_path).unwrap();
|
||||
@@ -2667,7 +2612,6 @@ impl Default for NodeGraphMessageHandler {
|
||||
reordering_import: None,
|
||||
end_index: None,
|
||||
frontend_nodes: Vec::new(),
|
||||
frontend_wires: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,10 +60,10 @@ pub struct FrontendXY {
|
||||
pub struct FrontendGraphInput {
|
||||
#[serde(rename = "dataType")]
|
||||
pub data_type: FrontendGraphDataType,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
#[serde(rename = "resolvedType")]
|
||||
pub resolved_type: String,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
/// Either "nothing", "import index {index}", or "{node name} output {output_index}".
|
||||
#[serde(rename = "connectedToString")]
|
||||
pub connected_to: String,
|
||||
@@ -86,6 +86,26 @@ pub struct FrontendGraphOutput {
|
||||
pub connected_to: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendExport {
|
||||
pub port: FrontendGraphInput,
|
||||
pub wire: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendExports {
|
||||
/// If the primary export is not visible, then it is None.
|
||||
pub exports: Vec<Option<FrontendExport>>,
|
||||
#[serde(rename = "previewWire")]
|
||||
pub preview_wire: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendImport {
|
||||
pub port: FrontendGraphOutput,
|
||||
pub wires: Vec<String>,
|
||||
}
|
||||
|
||||
// Metadata that is common to nodes and layers
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct FrontendNodeMetadata {
|
||||
@@ -159,6 +179,8 @@ pub struct FrontendNodeToRender {
|
||||
pub metadata: FrontendNodeMetadata,
|
||||
#[serde(rename = "nodeOrLayer")]
|
||||
pub node_or_layer: FrontendNodeOrLayer,
|
||||
//TODO: Remove
|
||||
pub wires: Vec<(String, bool, FrontendGraphDataType)>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
|
||||
@@ -4,9 +4,8 @@ use super::nodes::SelectedNodes;
|
||||
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};
|
||||
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
|
||||
use crate::messages::portfolio::document::node_graph::document_node_definitions::{DocumentNodeDefinition, resolve_document_node_type};
|
||||
use crate::messages::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets, FrontendGraphDataType};
|
||||
use crate::messages::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets};
|
||||
use crate::messages::portfolio::document::utility_types::network_interface::resolved_types::ResolvedDocumentNodeTypes;
|
||||
use crate::messages::portfolio::document::utility_types::wires::{GraphWireStyle, WirePath, WirePathUpdate, build_vector_wire};
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
use crate::messages::tool::tool_messages::tool_prelude::NumberInputMode;
|
||||
use deserialization::deserialize_node_persistent_metadata;
|
||||
@@ -20,7 +19,6 @@ use graphene_std::subpath::Subpath;
|
||||
use graphene_std::transform::Footprint;
|
||||
use graphene_std::vector::click_target::{ClickTarget, ClickTargetType};
|
||||
use graphene_std::vector::{PointId, Vector, VectorModificationType};
|
||||
use kurbo::BezPath;
|
||||
use serde_json::{Value, json};
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::hash::Hash;
|
||||
@@ -684,13 +682,6 @@ impl NodeNetworkInterface {
|
||||
Some(&metadata.persistent_metadata)
|
||||
}
|
||||
|
||||
fn transient_input_metadata(&self, node_id: &NodeId, index: usize, network_path: &[NodeId]) -> Option<&InputTransientMetadata> {
|
||||
let metadata = self
|
||||
.node_metadata(node_id, network_path)
|
||||
.and_then(|node_metadata| node_metadata.persistent_metadata.input_metadata.get(index))?;
|
||||
Some(&metadata.transient_metadata)
|
||||
}
|
||||
|
||||
/// Returns the input name to display in the properties panel. If the name is empty then the type is used.
|
||||
pub fn displayed_input_name_and_description(&mut self, node_id: &NodeId, input_index: usize, network_path: &[NodeId]) -> (String, String) {
|
||||
let Some(input_metadata) = self.persistent_input_metadata(node_id, input_index, network_path) else {
|
||||
@@ -1538,30 +1529,6 @@ impl NodeNetworkInterface {
|
||||
return;
|
||||
};
|
||||
network_metadata.transient_metadata.import_export_ports.unload();
|
||||
|
||||
// Always unload all wires connected to them as well
|
||||
let number_of_imports = self.number_of_imports(network_path);
|
||||
let Some(outward_wires) = self.outward_wires(network_path) else {
|
||||
log::error!("Could not get outward wires in remove_import");
|
||||
return;
|
||||
};
|
||||
let mut input_connectors = Vec::new();
|
||||
for import_index in 0..number_of_imports {
|
||||
let Some(outward_wires_for_import) = outward_wires.get(&OutputConnector::Import(import_index)).cloned() else {
|
||||
log::error!("Could not get outward wires for import in remove_import");
|
||||
return;
|
||||
};
|
||||
input_connectors.extend(outward_wires_for_import);
|
||||
}
|
||||
let Some(network) = self.nested_network(network_path) else {
|
||||
return;
|
||||
};
|
||||
for export_index in 0..network.exports.len() {
|
||||
input_connectors.push(InputConnector::Export(export_index));
|
||||
}
|
||||
for input in &input_connectors {
|
||||
self.unload_wire(input, network_path);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_import_export(&mut self, network_path: &[NodeId]) -> Option<&ModifyImportExportClickTarget> {
|
||||
@@ -1980,99 +1947,6 @@ impl NodeNetworkInterface {
|
||||
.find_map(|(input_index, click_target)| if index == input_index { click_target.bounding_box_center() } else { None })
|
||||
}
|
||||
|
||||
pub fn newly_loaded_input_wire(&mut self, input: &InputConnector, graph_wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<WirePathUpdate> {
|
||||
if !self.wire_is_loaded(input, network_path) {
|
||||
self.load_wire(input, graph_wire_style, network_path);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
||||
let wire = match input {
|
||||
InputConnector::Node { node_id, input_index } => {
|
||||
let input_metadata = self.transient_input_metadata(node_id, *input_index, network_path)?;
|
||||
let TransientMetadata::Loaded(wire) = &input_metadata.wire else {
|
||||
log::error!("Could not load wire for input: {input:?}");
|
||||
return None;
|
||||
};
|
||||
wire.clone()
|
||||
}
|
||||
InputConnector::Export(export_index) => {
|
||||
let network_metadata = self.network_metadata(network_path)?;
|
||||
let Some(TransientMetadata::Loaded(wire)) = network_metadata.transient_metadata.wires.get(*export_index) else {
|
||||
log::error!("Could not load wire for input: {input:?}");
|
||||
return None;
|
||||
};
|
||||
wire.clone()
|
||||
}
|
||||
};
|
||||
Some(wire)
|
||||
}
|
||||
|
||||
pub fn wire_is_loaded(&mut self, input: &InputConnector, network_path: &[NodeId]) -> bool {
|
||||
match input {
|
||||
InputConnector::Node { node_id, input_index } => {
|
||||
let Some(input_metadata) = self.transient_input_metadata(node_id, *input_index, network_path) else {
|
||||
log::error!("Input metadata should always exist for input");
|
||||
return false;
|
||||
};
|
||||
input_metadata.wire.is_loaded()
|
||||
}
|
||||
InputConnector::Export(export_index) => {
|
||||
let Some(network_metadata) = self.network_metadata(network_path) else {
|
||||
return false;
|
||||
};
|
||||
match network_metadata.transient_metadata.wires.get(*export_index) {
|
||||
Some(wire) => wire.is_loaded(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_wire(&mut self, input: &InputConnector, graph_wire_style: GraphWireStyle, network_path: &[NodeId]) {
|
||||
let dashed = match self.previewing(network_path) {
|
||||
Previewing::Yes { .. } => match input {
|
||||
InputConnector::Node { .. } => false,
|
||||
InputConnector::Export(export_index) => *export_index == 0,
|
||||
},
|
||||
Previewing::No => false,
|
||||
};
|
||||
let Some(wire) = self.wire_path_from_input(input, graph_wire_style, dashed, network_path) else {
|
||||
log::error!("Could not load wire path from input");
|
||||
return;
|
||||
};
|
||||
match input {
|
||||
InputConnector::Node { node_id, input_index } => {
|
||||
let Some(node_metadata) = self.node_metadata_mut(node_id, network_path) else { return };
|
||||
let Some(input_metadata) = node_metadata.persistent_metadata.input_metadata.get_mut(*input_index) else {
|
||||
// log::warn!("Node metadata must exist on node: {input:?}");
|
||||
return;
|
||||
};
|
||||
let wire_update = WirePathUpdate {
|
||||
id: *node_id,
|
||||
input_index: *input_index,
|
||||
wire_path_update: Some(wire),
|
||||
};
|
||||
input_metadata.transient_metadata.wire = TransientMetadata::Loaded(wire_update);
|
||||
}
|
||||
InputConnector::Export(export_index) => {
|
||||
let Some(network_metadata) = self.network_metadata_mut(network_path) else { return };
|
||||
if *export_index >= network_metadata.transient_metadata.wires.len() {
|
||||
network_metadata.transient_metadata.wires.resize(export_index + 1, TransientMetadata::Unloaded);
|
||||
}
|
||||
let Some(input_metadata) = network_metadata.transient_metadata.wires.get_mut(*export_index) else {
|
||||
return;
|
||||
};
|
||||
let wire_update = WirePathUpdate {
|
||||
id: NodeId(u64::MAX),
|
||||
input_index: *export_index,
|
||||
wire_path_update: Some(wire),
|
||||
};
|
||||
*input_metadata = TransientMetadata::Loaded(wire_update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_input_connectors(&self, network_path: &[NodeId]) -> Vec<InputConnector> {
|
||||
let mut input_connectors = Vec::new();
|
||||
let Some(network) = self.nested_network(network_path) else {
|
||||
@@ -2097,141 +1971,6 @@ impl NodeNetworkInterface {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Maps to the frontend representation of a wire start. Includes disconnected value wire inputs.
|
||||
pub fn node_graph_wire_inputs(&self, network_path: &[NodeId]) -> Vec<(NodeId, usize)> {
|
||||
self.node_graph_input_connectors(network_path)
|
||||
.iter()
|
||||
.map(|input| match input {
|
||||
InputConnector::Node { node_id, input_index } => (*node_id, *input_index),
|
||||
InputConnector::Export(export_index) => (NodeId(u64::MAX), *export_index),
|
||||
})
|
||||
.chain(std::iter::once((NodeId(u64::MAX), u32::MAX as usize)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn unload_wires_for_node(&mut self, node_id: &NodeId, network_path: &[NodeId]) {
|
||||
let number_of_outputs = self.number_of_outputs(node_id, network_path);
|
||||
let Some(outward_wires) = self.outward_wires(network_path) else {
|
||||
log::error!("Could not get outward wires in reorder_export");
|
||||
return;
|
||||
};
|
||||
let mut input_connectors = Vec::new();
|
||||
for output_index in 0..number_of_outputs {
|
||||
let Some(inputs) = outward_wires.get(&OutputConnector::node(*node_id, output_index)) else {
|
||||
continue;
|
||||
};
|
||||
input_connectors.extend(inputs.clone())
|
||||
}
|
||||
for input_index in 0..self.number_of_inputs(node_id, network_path) {
|
||||
input_connectors.push(InputConnector::node(*node_id, input_index));
|
||||
}
|
||||
for input in input_connectors {
|
||||
self.unload_wire(&input, network_path);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unload_wire(&mut self, input: &InputConnector, network_path: &[NodeId]) {
|
||||
match input {
|
||||
InputConnector::Node { node_id, input_index } => {
|
||||
let Some(node_metadata) = self.node_metadata_mut(node_id, network_path) else {
|
||||
return;
|
||||
};
|
||||
let Some(input_metadata) = node_metadata.persistent_metadata.input_metadata.get_mut(*input_index) else {
|
||||
// log::warn!("Node metadata must exist on node: {input:?}");
|
||||
return;
|
||||
};
|
||||
input_metadata.transient_metadata.wire = TransientMetadata::Unloaded;
|
||||
}
|
||||
InputConnector::Export(export_index) => {
|
||||
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
|
||||
return;
|
||||
};
|
||||
if *export_index >= network_metadata.transient_metadata.wires.len() {
|
||||
network_metadata.transient_metadata.wires.resize(export_index + 1, TransientMetadata::Unloaded);
|
||||
}
|
||||
let Some(input_metadata) = network_metadata.transient_metadata.wires.get_mut(*export_index) else {
|
||||
return;
|
||||
};
|
||||
*input_metadata = TransientMetadata::Unloaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When previewing, there may be a second path to the root node.
|
||||
pub fn wire_to_root(&mut self, graph_wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<WirePathUpdate> {
|
||||
let input = InputConnector::Export(0);
|
||||
let current_export = self.upstream_output_connector(&input, network_path)?;
|
||||
|
||||
let root_node = match self.previewing(network_path) {
|
||||
Previewing::Yes { root_node_to_restore } => root_node_to_restore,
|
||||
Previewing::No => None,
|
||||
}?;
|
||||
|
||||
if Some(root_node.node_id) == current_export.node_id() {
|
||||
return None;
|
||||
}
|
||||
let Some(input_position) = self.get_input_center(&input, network_path) else {
|
||||
log::error!("Could not get input position for wire end in root node: {input:?}");
|
||||
return None;
|
||||
};
|
||||
let upstream_output = OutputConnector::node(root_node.node_id, root_node.output_index);
|
||||
let Some(output_position) = self.get_output_center(&upstream_output, network_path) else {
|
||||
log::error!("Could not get output position for wire start in root node: {upstream_output:?}");
|
||||
return None;
|
||||
};
|
||||
let vertical_end = input.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path) && input.input_index() == 0);
|
||||
let vertical_start: bool = upstream_output.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path));
|
||||
let thick = vertical_end && vertical_start;
|
||||
let vector_wire = build_vector_wire(output_position, input_position, vertical_start, vertical_end, graph_wire_style);
|
||||
|
||||
let path_string = vector_wire.to_svg();
|
||||
let data_type = FrontendGraphDataType::displayed_type(&self.input_type(&input, network_path));
|
||||
let wire_path_update = Some(WirePath {
|
||||
path_string,
|
||||
data_type,
|
||||
thick,
|
||||
dashed: false,
|
||||
});
|
||||
|
||||
Some(WirePathUpdate {
|
||||
id: NodeId(u64::MAX),
|
||||
input_index: u32::MAX as usize,
|
||||
wire_path_update,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the vector subpath and a boolean of whether the wire should be thick.
|
||||
pub fn vector_wire_from_input(&mut self, input: &InputConnector, wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<(BezPath, bool)> {
|
||||
let Some(input_position) = self.get_input_center(input, network_path) else {
|
||||
log::error!("Could not get dom rect for wire end: {input:?}");
|
||||
return None;
|
||||
};
|
||||
// An upstream output could not be found, so the wire does not exist, but it should still be loaded as as empty vector
|
||||
let Some(upstream_output) = self.upstream_output_connector(input, network_path) else {
|
||||
return Some((BezPath::new(), false));
|
||||
};
|
||||
let Some(output_position) = self.get_output_center(&upstream_output, network_path) else {
|
||||
log::error!("Could not get output port for wire start: {:?}", upstream_output);
|
||||
return None;
|
||||
};
|
||||
let vertical_end = input.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path) && input.input_index() == 0);
|
||||
let vertical_start = upstream_output.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path));
|
||||
let thick = vertical_end && vertical_start;
|
||||
Some((build_vector_wire(output_position, input_position, vertical_start, vertical_end, wire_style), thick))
|
||||
}
|
||||
|
||||
pub fn wire_path_from_input(&mut self, input: &InputConnector, graph_wire_style: GraphWireStyle, dashed: bool, network_path: &[NodeId]) -> Option<WirePath> {
|
||||
let (vector_wire, thick) = self.vector_wire_from_input(input, graph_wire_style, network_path)?;
|
||||
let path_string = vector_wire.to_svg();
|
||||
let data_type = FrontendGraphDataType::displayed_type(&self.input_type(input, network_path));
|
||||
Some(WirePath {
|
||||
path_string,
|
||||
data_type,
|
||||
thick,
|
||||
dashed,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn node_click_targets(&mut self, node_id: &NodeId, network_path: &[NodeId]) -> Option<&DocumentNodeClickTargets> {
|
||||
self.try_load_node_click_targets(node_id, network_path);
|
||||
self.try_get_node_click_targets(node_id, network_path)
|
||||
@@ -2469,7 +2208,6 @@ impl NodeNetworkInterface {
|
||||
return;
|
||||
};
|
||||
node_metadata.transient_metadata.click_targets.unload();
|
||||
self.unload_wires_for_node(node_id, network_path);
|
||||
}
|
||||
|
||||
pub fn unload_upstream_node_click_targets(&mut self, node_ids: Vec<NodeId>, network_path: &[NodeId]) {
|
||||
@@ -3792,17 +3530,14 @@ impl NodeNetworkInterface {
|
||||
// If a connection is made to the imports
|
||||
(NodeInput::Value { .. } | NodeInput::Scope { .. } | NodeInput::Inline { .. }, NodeInput::Network { .. }) => {
|
||||
self.unload_outward_wires(network_path);
|
||||
self.unload_wire(input_connector, network_path);
|
||||
}
|
||||
// If a connection to the imports is disconnected
|
||||
(NodeInput::Network { .. }, NodeInput::Value { .. } | NodeInput::Scope { .. } | NodeInput::Inline { .. }) => {
|
||||
self.unload_outward_wires(network_path);
|
||||
self.unload_wire(input_connector, network_path);
|
||||
}
|
||||
// If a node is disconnected.
|
||||
(NodeInput::Node { .. }, NodeInput::Value { .. } | NodeInput::Scope { .. } | NodeInput::Inline { .. }) => {
|
||||
self.unload_outward_wires(network_path);
|
||||
self.unload_wire(input_connector, network_path);
|
||||
|
||||
if let Some((old_upstream_node_id, previous_position)) = previous_metadata {
|
||||
let old_upstream_node_is_layer = self.is_layer(&old_upstream_node_id, network_path);
|
||||
@@ -5848,9 +5583,6 @@ pub struct NodeNetworkTransientMetadata {
|
||||
pub modify_import_export: TransientMetadata<ModifyImportExportClickTarget>,
|
||||
// Distance to the edges of the network, where the import/export ports are displayed. Rounded to nearest grid space when the panning ends.
|
||||
pub rounded_network_edge_distance: TransientMetadata<NetworkEdgeDistance>,
|
||||
|
||||
// Wires from the exports
|
||||
pub wires: Vec<TransientMetadata<WirePathUpdate>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -6029,12 +5761,11 @@ impl InputPersistentMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct InputTransientMetadata {
|
||||
wire: TransientMetadata<WirePathUpdate>,
|
||||
// downstream_protonode: populated for all inputs after each compile
|
||||
// types: populated for each protonode after each
|
||||
}
|
||||
// #[derive(Debug, Clone, Default)]
|
||||
// struct InputTransientMetadata {
|
||||
// // downstream_protonode: populated for all inputs after each compile
|
||||
// // types: populated for each protonode after each
|
||||
// }
|
||||
|
||||
/// Persistent metadata for each node in the network, which must be included when creating, serializing, and deserializing saving a node.
|
||||
#[derive(Default, Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
@@ -6073,15 +5804,15 @@ impl DocumentNodePersistentMetadata {
|
||||
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
pub struct InputMetadata {
|
||||
pub persistent_metadata: InputPersistentMetadata,
|
||||
#[serde(skip)]
|
||||
transient_metadata: InputTransientMetadata,
|
||||
// #[serde(skip)]
|
||||
// transient_metadata: InputTransientMetadata,
|
||||
}
|
||||
|
||||
impl Clone for InputMetadata {
|
||||
fn clone(&self) -> Self {
|
||||
InputMetadata {
|
||||
persistent_metadata: self.persistent_metadata.clone(),
|
||||
transient_metadata: Default::default(),
|
||||
// transient_metadata: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
use glam::{DVec2, IVec2};
|
||||
use graph_craft::proto::GraphErrors;
|
||||
use graphene_std::uuid::NodeId;
|
||||
use kurbo::BezPath;
|
||||
|
||||
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, FrontendLayer, FrontendNode, FrontendNodeMetadata, FrontendNodeOrLayer, FrontendNodeToRender, FrontendXY,
|
||||
FrontendExport, FrontendExports, FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput, FrontendImport, FrontendLayer, FrontendNode, FrontendNodeMetadata, FrontendNodeOrLayer,
|
||||
FrontendNodeToRender, FrontendXY,
|
||||
},
|
||||
utility_types::{
|
||||
network_interface::{FlowType, InputConnector, NodeNetworkInterface, OutputConnector, Previewing},
|
||||
wires::{GraphWireStyle, build_vector_wire},
|
||||
},
|
||||
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<FrontendNodeToRender> {
|
||||
pub fn collect_nodes(&mut self, node_graph_errors: &GraphErrors, wire_style: GraphWireStyle, 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();
|
||||
@@ -99,7 +104,25 @@ impl NodeNetworkInterface {
|
||||
}
|
||||
};
|
||||
|
||||
let frontend_node_to_render = FrontendNodeToRender { metadata, node_or_layer };
|
||||
let wires = (0..self.number_of_displayed_inputs(&node_id, network_path))
|
||||
.filter_map(|input_index| {
|
||||
self.wire_from_input(&InputConnector::node(node_id, input_index), wire_style, network_path)
|
||||
.filter(|_| {
|
||||
self.upstream_output_connector(&InputConnector::node(node_id, input_index), network_path)
|
||||
.is_some_and(|output| !matches!(output, OutputConnector::Import(_)))
|
||||
})
|
||||
.map(|path| path.to_svg())
|
||||
.map(|wire| {
|
||||
(
|
||||
wire,
|
||||
self.wire_is_thick(&InputConnector::node(node_id, input_index), network_path),
|
||||
FrontendGraphDataType::displayed_type(&self.input_type(&InputConnector::node(node_id, input_index), network_path)),
|
||||
)
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
let frontend_node_to_render = FrontendNodeToRender { metadata, node_or_layer, wires };
|
||||
|
||||
nodes.push(frontend_node_to_render);
|
||||
}
|
||||
@@ -318,16 +341,35 @@ impl NodeNetworkInterface {
|
||||
.is_some_and(|node_id| self.is_layer(&node_id, network_path))
|
||||
}
|
||||
|
||||
pub fn frontend_imports(&mut self, network_path: &[NodeId]) -> Vec<Option<FrontendGraphOutput>> {
|
||||
/// The imports contain both the output port and the outward wires
|
||||
pub fn frontend_imports(&mut self, graph_wire_style: GraphWireStyle, network_path: &[NodeId]) -> Vec<Option<FrontendImport>> {
|
||||
match network_path.split_last() {
|
||||
Some((node_id, encapsulatingnetwork_path)) => {
|
||||
let Some(node) = self.document_node(node_id, encapsulatingnetwork_path) else {
|
||||
log::error!("Could not get node {node_id} in network {encapsulatingnetwork_path:?}");
|
||||
Some((node_id, encapsulating_network_path)) => {
|
||||
let Some(node) = self.document_node(node_id, encapsulating_network_path) else {
|
||||
log::error!("Could not get node {node_id} in network {encapsulating_network_path:?}");
|
||||
return Vec::new();
|
||||
};
|
||||
let mut frontend_imports = (0..node.inputs.len())
|
||||
.map(|import_index| self.frontend_output_from_connector(&OutputConnector::Import(import_index), network_path))
|
||||
.map(|import_index| {
|
||||
let port = self.frontend_output_from_connector(&OutputConnector::Import(import_index), network_path);
|
||||
port.and_then(|port| {
|
||||
let outward_wires = self.outward_wires(network_path)?;
|
||||
let downstream_inputs = outward_wires.get(&OutputConnector::Import(import_index)).cloned()?;
|
||||
let wires = downstream_inputs
|
||||
.iter()
|
||||
.filter_map(|input_connector| {
|
||||
let Some(wire) = self.wire_from_input(&input_connector, graph_wire_style, network_path) else {
|
||||
log::error!("Could not get wire path for import input: {input_connector:?}");
|
||||
return None;
|
||||
};
|
||||
Some(wire.to_svg())
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
Some(FrontendImport { port, wires })
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if frontend_imports.is_empty() {
|
||||
frontend_imports.push(None);
|
||||
}
|
||||
@@ -338,13 +380,29 @@ impl NodeNetworkInterface {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn frontend_exports(&mut self, network_path: &[NodeId]) -> Vec<Option<FrontendGraphInput>> {
|
||||
let Some(network) = self.nested_network(network_path) else { return Vec::new() };
|
||||
let mut frontend_exports = ((0..network.exports.len()).map(|export_index| self.frontend_input_from_connector(&InputConnector::Export(export_index), network_path))).collect::<Vec<_>>();
|
||||
if frontend_exports.is_empty() {
|
||||
frontend_exports.push(None);
|
||||
/// The imports contain the export port, the outward wires, and the preview wire if it exists
|
||||
pub fn frontend_exports(&mut self, graph_wire_style: GraphWireStyle, network_path: &[NodeId]) -> FrontendExports {
|
||||
let Some(network) = self.nested_network(network_path) else {
|
||||
log::error!("Could not get nested network in frontend exports");
|
||||
return FrontendExports::default();
|
||||
};
|
||||
let mut exports = (0..network.exports.len())
|
||||
.map(|export_index| {
|
||||
let export_connector = InputConnector::Export(export_index);
|
||||
let frontend_export = self.frontend_input_from_connector(&export_connector, network_path);
|
||||
|
||||
frontend_export.and_then(|export| {
|
||||
let wire = self.wire_from_input(&export_connector, graph_wire_style, network_path).map(|path| path.to_svg());
|
||||
Some(FrontendExport { port: export, wire })
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if exports.is_empty() {
|
||||
exports.push(None);
|
||||
}
|
||||
frontend_exports
|
||||
let preview_wire = self.wire_to_root(graph_wire_style, network_path);
|
||||
FrontendExports { exports, preview_wire }
|
||||
}
|
||||
|
||||
pub fn import_export_position(&mut self, network_path: &[NodeId]) -> Option<(IVec2, IVec2)> {
|
||||
@@ -424,4 +482,60 @@ impl NodeNetworkInterface {
|
||||
|
||||
Some((rounded_import_top_left.as_ivec2(), rounded_export_top_right.as_ivec2()))
|
||||
}
|
||||
|
||||
pub fn wire_is_thick(&self, input: &InputConnector, network_path: &[NodeId]) -> bool {
|
||||
let Some(upstream_output) = self.upstream_output_connector(input, network_path) else {
|
||||
return false;
|
||||
};
|
||||
let vertical_end = input.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path) && input.input_index() == 0);
|
||||
let vertical_start = upstream_output.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path));
|
||||
vertical_end && vertical_start
|
||||
}
|
||||
|
||||
/// Returns the vector subpath and a boolean of whether the wire should be thick.
|
||||
pub fn wire_from_input(&mut self, input: &InputConnector, wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<BezPath> {
|
||||
let Some(input_position) = self.get_input_center(input, network_path) else {
|
||||
log::error!("Could not get dom rect for wire end: {input:?}");
|
||||
return None;
|
||||
};
|
||||
// An upstream output could not be found
|
||||
let Some(upstream_output) = self.upstream_output_connector(input, network_path) else {
|
||||
return None;
|
||||
};
|
||||
let Some(output_position) = self.get_output_center(&upstream_output, network_path) else {
|
||||
log::error!("Could not get output port for wire start: {:?}", upstream_output);
|
||||
return None;
|
||||
};
|
||||
let vertical_end = input.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path) && input.input_index() == 0);
|
||||
let vertical_start = upstream_output.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path));
|
||||
Some(build_vector_wire(output_position, input_position, vertical_start, vertical_end, wire_style))
|
||||
}
|
||||
|
||||
/// When previewing, there may be a second path to the root node.
|
||||
pub fn wire_to_root(&mut self, graph_wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<String> {
|
||||
let input = InputConnector::Export(0);
|
||||
let current_export = self.upstream_output_connector(&input, network_path)?;
|
||||
|
||||
let root_node = match self.previewing(network_path) {
|
||||
Previewing::Yes { root_node_to_restore } => root_node_to_restore,
|
||||
Previewing::No => None,
|
||||
}?;
|
||||
|
||||
if Some(root_node.node_id) == current_export.node_id() {
|
||||
return None;
|
||||
}
|
||||
let Some(input_position) = self.get_input_center(&input, network_path) else {
|
||||
log::error!("Could not get input position for wire end in root node: {input:?}");
|
||||
return None;
|
||||
};
|
||||
let upstream_output = OutputConnector::node(root_node.node_id, root_node.output_index);
|
||||
let Some(output_position) = self.get_output_center(&upstream_output, network_path) else {
|
||||
log::error!("Could not get output position for wire start in root node: {upstream_output:?}");
|
||||
return None;
|
||||
};
|
||||
let vertical_start = upstream_output.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path));
|
||||
let vector_wire = build_vector_wire(output_position, input_position, vertical_start, false, graph_wire_style);
|
||||
|
||||
Some(vector_wire.to_svg())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,14 @@
|
||||
use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType;
|
||||
use glam::{DVec2, IVec2};
|
||||
use graphene_std::{uuid::NodeId, vector::misc::dvec2_to_point};
|
||||
use graphene_std::vector::misc::dvec2_to_point;
|
||||
use kurbo::{BezPath, DEFAULT_ACCURACY, Line, Point, Shape};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct WirePath {
|
||||
#[serde(rename = "pathString")]
|
||||
pub path_string: String,
|
||||
pub struct WirePathInProgress {
|
||||
pub wire: String,
|
||||
#[serde(rename = "dataType")]
|
||||
pub data_type: FrontendGraphDataType,
|
||||
pub thick: bool,
|
||||
pub dashed: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct WirePathUpdate {
|
||||
pub id: NodeId,
|
||||
#[serde(rename = "inputIndex")]
|
||||
pub input_index: usize,
|
||||
// If none, then remove the wire from the map
|
||||
#[serde(rename = "wirePathUpdate")]
|
||||
pub wire_path_update: Option<WirePath>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Default, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
|
||||
@@ -909,8 +909,6 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||
responses.add(DocumentMessage::GraphViewOverlay { open: node_graph_open });
|
||||
if node_graph_open {
|
||||
responses.add(NodeGraphMessage::UpdateGraphBarRight);
|
||||
responses.add(NodeGraphMessage::UnloadWires);
|
||||
responses.add(NodeGraphMessage::SendWires)
|
||||
} else {
|
||||
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
||||
}
|
||||
|
||||
@@ -87,8 +87,7 @@ impl MessageHandler<PreferencesMessage, ()> for PreferencesMessageHandler {
|
||||
}
|
||||
PreferencesMessage::GraphWireStyle { style } => {
|
||||
self.graph_wire_style = style;
|
||||
responses.add(NodeGraphMessage::UnloadWires);
|
||||
responses.add(NodeGraphMessage::SendWires);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
}
|
||||
PreferencesMessage::ViewportZoomWheelRate { rate } => {
|
||||
self.viewport_zoom_wheel_rate = rate;
|
||||
|
||||
@@ -564,8 +564,9 @@
|
||||
</canvas>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<Graph />
|
||||
<div class="graph-view" class:open={$document.graphViewOverlayOpen} data-graph>
|
||||
<Graph />
|
||||
</div>
|
||||
</LayoutCol>
|
||||
<LayoutCol class="ruler-or-scrollbar right-scrollbar">
|
||||
<ScrollbarInput
|
||||
@@ -823,6 +824,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
.graph-view {
|
||||
pointer-events: none;
|
||||
transition: opacity 0.2s;
|
||||
opacity: 0;
|
||||
|
||||
&.open {
|
||||
cursor: auto;
|
||||
pointer-events: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-artwork,
|
||||
.graph {
|
||||
position: absolute;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,13 +26,37 @@ export type XY = { x: number; y: number };
|
||||
// ============================================================================
|
||||
|
||||
export class UpdateBox extends JsMessage {
|
||||
readonly box!: Box | undefined;
|
||||
readonly box!: FrontendSelectionBox | undefined;
|
||||
}
|
||||
|
||||
export class FrontendClickTargets {
|
||||
readonly nodeClickTargets!: string[];
|
||||
readonly layerClickTargets!: string[];
|
||||
readonly connectorClickTargets!: string[];
|
||||
readonly iconClickTargets!: string[];
|
||||
readonly allNodesBoundingBox!: string;
|
||||
readonly importExportsBoundingBox!: string;
|
||||
readonly modifyImportExport!: string[];
|
||||
}
|
||||
|
||||
export class UpdateClickTargets extends JsMessage {
|
||||
readonly clickTargets!: FrontendClickTargets | undefined;
|
||||
}
|
||||
|
||||
export class FrontendSelectionBox {
|
||||
readonly startX!: number;
|
||||
|
||||
readonly startY!: number;
|
||||
|
||||
readonly endX!: number;
|
||||
|
||||
readonly endY!: number;
|
||||
}
|
||||
|
||||
export class UpdateNodeGraphSelectionBox extends JsMessage {
|
||||
readonly box!: FrontendSelectionBox | undefined;
|
||||
}
|
||||
|
||||
const ContextTupleToVec2 = Transform((data) => {
|
||||
if (data.obj.contextMenuInformation === undefined) return undefined;
|
||||
const contextMenuCoordinates = { x: data.obj.contextMenuInformation.contextMenuCoordinates[0], y: data.obj.contextMenuInformation.contextMenuCoordinates[1] };
|
||||
@@ -45,15 +69,20 @@ const ContextTupleToVec2 = Transform((data) => {
|
||||
return { contextMenuCoordinates, contextMenuData };
|
||||
});
|
||||
|
||||
export class ContextMenuInformation {
|
||||
readonly contextMenuCoordinates!: XY;
|
||||
readonly contextMenuData!: "CreateNode" | { type: "CreateNode"; compatibleType: string } | { nodeId: bigint; currentlyIsNode: boolean };
|
||||
}
|
||||
|
||||
export class UpdateContextMenuInformation extends JsMessage {
|
||||
@ContextTupleToVec2
|
||||
readonly contextMenuInformation!: ContextMenuInformation | undefined;
|
||||
}
|
||||
|
||||
export class UpdateImportsExports extends JsMessage {
|
||||
readonly imports!: (FrontendGraphOutput | undefined)[];
|
||||
readonly imports!: (FrontendImport | undefined)[];
|
||||
|
||||
readonly exports!: (FrontendGraphInput | undefined)[];
|
||||
readonly exports!: FrontendExports;
|
||||
|
||||
readonly importPosition!: XY;
|
||||
|
||||
@@ -93,12 +122,6 @@ export class UpdateVisibleNodes extends JsMessage {
|
||||
readonly nodes!: bigint[];
|
||||
}
|
||||
|
||||
export class UpdateNodeGraphWires extends JsMessage {
|
||||
readonly wires!: WireUpdate[];
|
||||
}
|
||||
|
||||
export class ClearAllNodeGraphWires extends JsMessage {}
|
||||
|
||||
export class UpdateNodeGraphTransform extends JsMessage {
|
||||
readonly transform!: NodeGraphTransform;
|
||||
}
|
||||
@@ -123,8 +146,14 @@ export class UpdateOpenDocumentsList extends JsMessage {
|
||||
readonly openDocuments!: OpenDocument[];
|
||||
}
|
||||
|
||||
export class WirePathInProgress {
|
||||
readonly wire!: string;
|
||||
readonly thick!: boolean;
|
||||
readonly dataType!: FrontendGraphDataType;
|
||||
}
|
||||
|
||||
export class UpdateWirePathInProgress extends JsMessage {
|
||||
readonly wirePath!: WirePath | undefined;
|
||||
readonly wirePathInProgress!: WirePathInProgress | undefined;
|
||||
}
|
||||
|
||||
export class OpenDocument {
|
||||
@@ -149,6 +178,7 @@ export class DocumentDetails {
|
||||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
export class Box {
|
||||
readonly startX!: number;
|
||||
|
||||
@@ -174,6 +204,12 @@ export type ContextMenuInformation = {
|
||||
contextMenuData: "CreateNode" | { type: "CreateNode"; compatibleType: string } | { nodeId: bigint; currentlyIsNode: boolean };
|
||||
};
|
||||
|
||||
=======
|
||||
export class FrontendDocumentDetails extends DocumentDetails {
|
||||
readonly id!: bigint;
|
||||
}
|
||||
|
||||
>>>>>>> 17a1a3d5 (Complete separating node rendering from imports/exports)
|
||||
export type FrontendGraphDataType = "General" | "Number" | "Artboard" | "Graphic" | "Raster" | "Vector" | "Color";
|
||||
|
||||
export class FrontendGraphInput {
|
||||
@@ -202,6 +238,21 @@ export class FrontendGraphOutput {
|
||||
readonly connectedTo!: string[];
|
||||
}
|
||||
|
||||
export class FrontendExport {
|
||||
readonly port!: FrontendGraphInput;
|
||||
readonly wire!: string | undefined;
|
||||
}
|
||||
|
||||
export class FrontendExports {
|
||||
readonly exports!: (FrontendExport | undefined)[];
|
||||
readonly previewWire!: string | undefined;
|
||||
}
|
||||
|
||||
export class FrontendImport {
|
||||
readonly port!: FrontendGraphOutput;
|
||||
readonly wires!: string[];
|
||||
}
|
||||
|
||||
export class FrontendNodeMetadata {
|
||||
readonly nodeId!: bigint;
|
||||
|
||||
@@ -268,6 +319,8 @@ export class FrontendNodeOrLayer {
|
||||
export class FrontendNodeToRender {
|
||||
readonly metadata!: FrontendNodeMetadata;
|
||||
readonly nodeOrLayer!: FrontendNodeOrLayer;
|
||||
// TODO: Remove
|
||||
readonly wires!: [string, boolean, FrontendGraphDataType][];
|
||||
}
|
||||
|
||||
export class UpdateCentralNodeGraph extends JsMessage {
|
||||
@@ -1647,7 +1700,6 @@ type JSMessageFactory = (data: any, wasm: WebAssembly.Memory, handle: EditorHand
|
||||
type MessageMaker = typeof JsMessage | JSMessageFactory;
|
||||
|
||||
export const messageMakers: Record<string, MessageMaker> = {
|
||||
ClearAllNodeGraphWires,
|
||||
DisplayDialog,
|
||||
DisplayDialogDismiss,
|
||||
DisplayDialogPanic,
|
||||
@@ -1676,7 +1728,6 @@ export const messageMakers: Record<string, MessageMaker> = {
|
||||
TriggerTextCopy,
|
||||
TriggerVisitLink,
|
||||
UpdateActiveDocument,
|
||||
UpdateBox,
|
||||
UpdateClickTargets,
|
||||
UpdateContextMenuInformation,
|
||||
UpdateDialogButtons,
|
||||
@@ -1704,8 +1755,8 @@ export const messageMakers: Record<string, MessageMaker> = {
|
||||
UpdateMouseCursor,
|
||||
UpdateNodeGraphControlBarLayout,
|
||||
UpdateNodeGraphRender,
|
||||
UpdateNodeGraphSelectionBox,
|
||||
UpdateNodeGraphTransform,
|
||||
UpdateNodeGraphWires,
|
||||
UpdateNodeThumbnail,
|
||||
UpdateOpenDocumentsList,
|
||||
UpdatePlatform,
|
||||
|
||||
@@ -2,15 +2,13 @@ import { writable } from "svelte/store";
|
||||
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import {
|
||||
type Box,
|
||||
type FrontendSelectionBox,
|
||||
type FrontendClickTargets,
|
||||
type ContextMenuInformation,
|
||||
type FrontendNodeToRender,
|
||||
type FrontendNodeType,
|
||||
type WirePath,
|
||||
ClearAllNodeGraphWires,
|
||||
type WirePathInProgress,
|
||||
SendUIMetadata,
|
||||
UpdateBox,
|
||||
UpdateClickTargets,
|
||||
UpdateContextMenuInformation,
|
||||
UpdateImportReorderIndex,
|
||||
@@ -19,35 +17,39 @@ import {
|
||||
UpdateLayerWidths,
|
||||
UpdateNodeGraphRender,
|
||||
UpdateVisibleNodes,
|
||||
UpdateNodeGraphWires,
|
||||
UpdateNodeGraphTransform,
|
||||
UpdateNodeThumbnail,
|
||||
UpdateWirePathInProgress,
|
||||
UpdateNodeGraphSelectionBox,
|
||||
} from "@graphite/messages";
|
||||
|
||||
export function createNodeGraphState(editor: Editor) {
|
||||
const { subscribe, update } = writable({
|
||||
box: undefined as Box | undefined,
|
||||
// Data that will continue to be rendered in Svelte for now
|
||||
selectionBox: undefined as FrontendSelectionBox | undefined,
|
||||
clickTargets: undefined as FrontendClickTargets | undefined,
|
||||
contextMenuInformation: undefined as ContextMenuInformation | undefined,
|
||||
layerWidths: new Map<bigint, number>(),
|
||||
wirePathInProgress: undefined as WirePathInProgress | undefined,
|
||||
updateImportsExports: undefined as UpdateImportsExports | undefined,
|
||||
nodesToRender: new Map<bigint, FrontendNodeToRender>(),
|
||||
open: false,
|
||||
opacity: 0.8,
|
||||
|
||||
visibleNodes: new Set<bigint>(),
|
||||
/// The index is the exposed input index. The exports have a first key value of u32::MAX.
|
||||
wires: new Map<bigint, Map<number, WirePath>>(),
|
||||
wirePathInProgress: undefined as WirePath | undefined,
|
||||
nodeDescriptions: new Map<string, string>(),
|
||||
nodeTypes: [] as FrontendNodeType[],
|
||||
thumbnails: new Map<bigint, string>(),
|
||||
transform: { scale: 1, x: 0, y: 0 },
|
||||
inSelectedNetwork: true,
|
||||
previewedNode: undefined as bigint | undefined,
|
||||
reorderImportIndex: undefined as number | undefined,
|
||||
reorderExportIndex: undefined as number | undefined,
|
||||
|
||||
contextMenuInformation: undefined as ContextMenuInformation | undefined,
|
||||
nodeTypes: [] as FrontendNodeType[],
|
||||
nodeDescriptions: new Map<string, string>(),
|
||||
|
||||
// Data that will be moved into the node graph to be rendered natively
|
||||
nodesToRender: new Map<bigint, FrontendNodeToRender>(),
|
||||
opacity: 0.8,
|
||||
inSelectedNetwork: true,
|
||||
previewedNode: undefined as bigint | undefined,
|
||||
|
||||
// TODO: Remove these fields
|
||||
visibleNodes: new Set<bigint>(),
|
||||
layerWidths: new Map<bigint, number>(),
|
||||
|
||||
// Data that will be passed in the context
|
||||
thumbnails: new Map<bigint, string>(),
|
||||
transform: { scale: 1, x: 0, y: 0 },
|
||||
});
|
||||
|
||||
// Set up message subscriptions on creation
|
||||
@@ -58,15 +60,21 @@ export function createNodeGraphState(editor: Editor) {
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateBox, (updateBox) => {
|
||||
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphSelectionBox, (updateBox) => {
|
||||
update((state) => {
|
||||
state.box = updateBox.box;
|
||||
state.selectionBox = updateBox.box;
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateClickTargets, (UpdateClickTargets) => {
|
||||
editor.subscriptions.subscribeJsMessage(UpdateClickTargets, (updateClickTargets) => {
|
||||
update((state) => {
|
||||
state.clickTargets = UpdateClickTargets.clickTargets;
|
||||
state.clickTargets = updateClickTargets.clickTargets;
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateWirePathInProgress, (updateWirePathInProgress) => {
|
||||
update((state) => {
|
||||
state.wirePathInProgress = updateWirePathInProgress.wirePathInProgress;
|
||||
return state;
|
||||
});
|
||||
});
|
||||
@@ -107,7 +115,6 @@ export function createNodeGraphState(editor: Editor) {
|
||||
updateNodeGraphRender.nodesToRender.forEach((node) => {
|
||||
state.nodesToRender.set(node.metadata.nodeId, node);
|
||||
});
|
||||
state.open = updateNodeGraphRender.open;
|
||||
state.opacity = updateNodeGraphRender.opacity;
|
||||
state.inSelectedNetwork = updateNodeGraphRender.inSelectedNetwork;
|
||||
state.previewedNode = updateNodeGraphRender.previewedNode;
|
||||
@@ -120,30 +127,6 @@ export function createNodeGraphState(editor: Editor) {
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphWires, (updateNodeWires) => {
|
||||
update((state) => {
|
||||
updateNodeWires.wires.forEach((wireUpdate) => {
|
||||
let inputMap = state.wires.get(wireUpdate.id);
|
||||
// If it doesn't exist, create it and set it in the outer map
|
||||
if (!inputMap) {
|
||||
inputMap = new Map();
|
||||
state.wires.set(wireUpdate.id, inputMap);
|
||||
}
|
||||
if (wireUpdate.wirePathUpdate !== undefined) {
|
||||
inputMap.set(wireUpdate.inputIndex, wireUpdate.wirePathUpdate);
|
||||
} else {
|
||||
inputMap.delete(wireUpdate.inputIndex);
|
||||
}
|
||||
});
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(ClearAllNodeGraphWires, (_) => {
|
||||
update((state) => {
|
||||
state.wires.clear();
|
||||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphTransform, (updateNodeGraphTransform) => {
|
||||
update((state) => {
|
||||
state.transform = updateNodeGraphTransform.transform;
|
||||
@@ -158,7 +141,7 @@ export function createNodeGraphState(editor: Editor) {
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateWirePathInProgress, (updateWirePathInProgress) => {
|
||||
update((state) => {
|
||||
state.wirePathInProgress = updateWirePathInProgress.wirePath;
|
||||
state.wirePathInProgress = updateWirePathInProgress.wirePathInProgress;
|
||||
return state;
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user