mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-21 21:38:12 +08:00
Add icons
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::messages::portfolio::document::utility_types::wires::WirePathInProgre
|
|||||||
use crate::messages::prelude::*;
|
use crate::messages::prelude::*;
|
||||||
use crate::messages::tool::utility_types::HintData;
|
use crate::messages::tool::utility_types::HintData;
|
||||||
use graph_craft::document::NodeId;
|
use graph_craft::document::NodeId;
|
||||||
use graphene_std::node_graph_overlay::types::{FrontendExports, FrontendImport, FrontendNodeToRender, FrontendXY, NodeGraphTransform};
|
use graphene_std::node_graph_overlay::types::{FrontendExports, FrontendImport, FrontendXY, NodeGraphTransform};
|
||||||
use graphene_std::raster::Image;
|
use graphene_std::raster::Image;
|
||||||
use graphene_std::raster::color::Color;
|
use graphene_std::raster::color::Color;
|
||||||
use graphene_std::text::{Font, TextAlign};
|
use graphene_std::text::{Font, TextAlign};
|
||||||
@@ -270,17 +270,10 @@ pub enum FrontendMessage {
|
|||||||
cursor: MouseCursorIcon,
|
cursor: MouseCursorIcon,
|
||||||
},
|
},
|
||||||
RequestNativeNodeGraphRender,
|
RequestNativeNodeGraphRender,
|
||||||
UpdateShouldRenderSvelteNodes {
|
|
||||||
#[serde(rename = "shouldRenderSvelteNodes")]
|
|
||||||
should_render_svelte_nodes: bool,
|
|
||||||
},
|
|
||||||
UpdateNativeNodeGraphSVG {
|
UpdateNativeNodeGraphSVG {
|
||||||
#[serde(rename = "svgString")]
|
#[serde(rename = "svgString")]
|
||||||
svg_string: String,
|
svg_string: String,
|
||||||
},
|
},
|
||||||
UpdateVisibleNodes {
|
|
||||||
nodes: Vec<NodeId>,
|
|
||||||
},
|
|
||||||
UpdateNodeGraphControlBarLayout {
|
UpdateNodeGraphControlBarLayout {
|
||||||
#[serde(rename = "layoutTarget")]
|
#[serde(rename = "layoutTarget")]
|
||||||
layout_target: LayoutTarget,
|
layout_target: LayoutTarget,
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ impl MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageContext> f
|
|||||||
self.viewport_bounds = bounds;
|
self.viewport_bounds = bounds;
|
||||||
|
|
||||||
responses.add(NavigationMessage::CanvasPan { delta: DVec2::ZERO });
|
responses.add(NavigationMessage::CanvasPan { delta: DVec2::ZERO });
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
}
|
}
|
||||||
responses.add(DeferMessage::AfterGraphRun {
|
responses.add(DeferMessage::AfterGraphRun {
|
||||||
messages: vec![
|
messages: vec![
|
||||||
|
|||||||
@@ -476,7 +476,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
|||||||
self.selection_network_path.clone_from(&self.breadcrumb_network_path);
|
self.selection_network_path.clone_from(&self.breadcrumb_network_path);
|
||||||
responses.add(NodeGraphMessage::SendGraph);
|
responses.add(NodeGraphMessage::SendGraph);
|
||||||
responses.add(DocumentMessage::ZoomCanvasToFitAll);
|
responses.add(DocumentMessage::ZoomCanvasToFitAll);
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
}
|
}
|
||||||
DocumentMessage::Escape => {
|
DocumentMessage::Escape => {
|
||||||
if self.node_graph_handler.drag_start.is_some() {
|
if self.node_graph_handler.drag_start.is_some() {
|
||||||
@@ -505,7 +504,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
|||||||
}
|
}
|
||||||
responses.add(NodeGraphMessage::SendGraph);
|
responses.add(NodeGraphMessage::SendGraph);
|
||||||
responses.add(DocumentMessage::PTZUpdate);
|
responses.add(DocumentMessage::PTZUpdate);
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
}
|
}
|
||||||
DocumentMessage::FlipSelectedLayers { flip_axis } => {
|
DocumentMessage::FlipSelectedLayers { flip_axis } => {
|
||||||
let scale = match flip_axis {
|
let scale = match flip_axis {
|
||||||
@@ -568,7 +566,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
|||||||
responses.add(ToolMessage::DeactivateTools);
|
responses.add(ToolMessage::DeactivateTools);
|
||||||
responses.add(OverlaysMessage::Draw); // Clear the overlays
|
responses.add(OverlaysMessage::Draw); // Clear the overlays
|
||||||
responses.add(NavigationMessage::CanvasTiltSet { angle_radians: 0. });
|
responses.add(NavigationMessage::CanvasTiltSet { angle_radians: 0. });
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
responses.add(NodeGraphMessage::UpdateGraphBarRight);
|
responses.add(NodeGraphMessage::UpdateGraphBarRight);
|
||||||
responses.add(NodeGraphMessage::UpdateHints);
|
responses.add(NodeGraphMessage::UpdateHints);
|
||||||
} else {
|
} else {
|
||||||
@@ -1489,10 +1486,8 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
|||||||
|
|
||||||
responses.add(DocumentMessage::RenderRulers);
|
responses.add(DocumentMessage::RenderRulers);
|
||||||
responses.add(DocumentMessage::RenderScrollbars);
|
responses.add(DocumentMessage::RenderScrollbars);
|
||||||
responses.add(NodeGraphMessage::UpdateEdges);
|
|
||||||
responses.add(NodeGraphMessage::UpdateBoxSelection);
|
responses.add(NodeGraphMessage::UpdateBoxSelection);
|
||||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||||
|
|
||||||
responses.add(FrontendMessage::UpdateNodeGraphTransform {
|
responses.add(FrontendMessage::UpdateNodeGraphTransform {
|
||||||
transform: NodeGraphTransform {
|
transform: NodeGraphTransform {
|
||||||
scale: transform.matrix2.x_axis.x,
|
scale: transform.matrix2.x_axis.x,
|
||||||
@@ -1942,9 +1937,6 @@ impl DocumentMessageHandler {
|
|||||||
responses.add(NodeGraphMessage::SelectedNodesUpdated);
|
responses.add(NodeGraphMessage::SelectedNodesUpdated);
|
||||||
responses.add(NodeGraphMessage::ForceRunDocumentGraph);
|
responses.add(NodeGraphMessage::ForceRunDocumentGraph);
|
||||||
|
|
||||||
// TODO: Remove once the footprint is used to load the imports/export distances from the edge
|
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
|
|
||||||
Some(previous_network)
|
Some(previous_network)
|
||||||
}
|
}
|
||||||
pub fn redo_with_history(&mut self, ipp: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) {
|
pub fn redo_with_history(&mut self, ipp: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) {
|
||||||
|
|||||||
@@ -178,7 +178,6 @@ impl MessageHandler<NavigationMessage, NavigationMessageContext<'_>> for Navigat
|
|||||||
NavigationMessage::CanvasPanMouseWheel { use_y_as_x } => {
|
NavigationMessage::CanvasPanMouseWheel { use_y_as_x } => {
|
||||||
let delta = if use_y_as_x { (-ipp.mouse.scroll_delta.y, 0.).into() } else { -ipp.mouse.scroll_delta.as_dvec2() } * VIEWPORT_SCROLL_RATE;
|
let delta = if use_y_as_x { (-ipp.mouse.scroll_delta.y, 0.).into() } else { -ipp.mouse.scroll_delta.as_dvec2() } * VIEWPORT_SCROLL_RATE;
|
||||||
responses.add(NavigationMessage::CanvasPan { delta });
|
responses.add(NavigationMessage::CanvasPan { delta });
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
}
|
}
|
||||||
NavigationMessage::CanvasTiltResetAndZoomTo100Percent => {
|
NavigationMessage::CanvasTiltResetAndZoomTo100Percent => {
|
||||||
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
|
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
|
||||||
@@ -193,7 +192,6 @@ impl MessageHandler<NavigationMessage, NavigationMessageContext<'_>> for Navigat
|
|||||||
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
||||||
}
|
}
|
||||||
responses.add(DocumentMessage::PTZUpdate);
|
responses.add(DocumentMessage::PTZUpdate);
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
}
|
}
|
||||||
NavigationMessage::CanvasTiltSet { angle_radians } => {
|
NavigationMessage::CanvasTiltSet { angle_radians } => {
|
||||||
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
|
let Some(ptz) = get_ptz_mut(document_ptz, network_interface, graph_view_overlay_open, breadcrumb_network_path) else {
|
||||||
@@ -272,7 +270,6 @@ impl MessageHandler<NavigationMessage, NavigationMessageContext<'_>> for Navigat
|
|||||||
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
||||||
}
|
}
|
||||||
responses.add(DocumentMessage::PTZUpdate);
|
responses.add(DocumentMessage::PTZUpdate);
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
}
|
}
|
||||||
NavigationMessage::CanvasFlip => {
|
NavigationMessage::CanvasFlip => {
|
||||||
if graph_view_overlay_open {
|
if graph_view_overlay_open {
|
||||||
@@ -320,7 +317,6 @@ impl MessageHandler<NavigationMessage, NavigationMessageContext<'_>> for Navigat
|
|||||||
} else {
|
} else {
|
||||||
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
||||||
}
|
}
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
// Reset the navigation operation now that it's done
|
// Reset the navigation operation now that it's done
|
||||||
self.navigation_operation = NavigationOperation::None;
|
self.navigation_operation = NavigationOperation::None;
|
||||||
|
|
||||||
@@ -382,7 +378,6 @@ impl MessageHandler<NavigationMessage, NavigationMessageContext<'_>> for Navigat
|
|||||||
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
responses.add(PortfolioMessage::UpdateDocumentWidgets);
|
||||||
}
|
}
|
||||||
responses.add(DocumentMessage::PTZUpdate);
|
responses.add(DocumentMessage::PTZUpdate);
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
}
|
}
|
||||||
// Fully zooms in on the selected
|
// Fully zooms in on the selected
|
||||||
NavigationMessage::FitViewportToSelection => {
|
NavigationMessage::FitViewportToSelection => {
|
||||||
@@ -476,7 +471,6 @@ impl MessageHandler<NavigationMessage, NavigationMessageContext<'_>> for Navigat
|
|||||||
};
|
};
|
||||||
|
|
||||||
responses.add(NavigationMessage::CanvasZoomSet { zoom_factor: ptz.zoom() });
|
responses.add(NavigationMessage::CanvasZoomSet { zoom_factor: ptz.zoom() });
|
||||||
responses.add(NodeGraphMessage::SetGridAlignedEdges);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,9 +139,7 @@ pub enum NodeGraphMessage {
|
|||||||
},
|
},
|
||||||
SendClickTargets,
|
SendClickTargets,
|
||||||
EndSendClickTargets,
|
EndSendClickTargets,
|
||||||
UpdateVisibleNodes,
|
|
||||||
SendGraph,
|
SendGraph,
|
||||||
SetGridAlignedEdges,
|
|
||||||
SetInputValue {
|
SetInputValue {
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
@@ -183,7 +181,6 @@ pub enum NodeGraphMessage {
|
|||||||
TogglePreviewImpl {
|
TogglePreviewImpl {
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
},
|
},
|
||||||
ToggleNativeNodeGraphRender,
|
|
||||||
SetImportExportName {
|
SetImportExportName {
|
||||||
name: String,
|
name: String,
|
||||||
index: ImportOrExport,
|
index: ImportOrExport,
|
||||||
@@ -217,7 +214,6 @@ pub enum NodeGraphMessage {
|
|||||||
SetLockedOrVisibilitySideEffects {
|
SetLockedOrVisibilitySideEffects {
|
||||||
node_ids: Vec<NodeId>,
|
node_ids: Vec<NodeId>,
|
||||||
},
|
},
|
||||||
UpdateEdges,
|
|
||||||
UpdateBoxSelection,
|
UpdateBoxSelection,
|
||||||
UpdateImportsExports,
|
UpdateImportsExports,
|
||||||
UpdateLayerPanel,
|
UpdateLayerPanel,
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ pub struct NodeGraphMessageHandler {
|
|||||||
reordering_export: Option<usize>,
|
reordering_export: Option<usize>,
|
||||||
/// The end index of the moved connector
|
/// The end index of the moved connector
|
||||||
end_index: Option<usize>,
|
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>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
/// 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.
|
||||||
@@ -1590,61 +1588,16 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
click_targets: Some(network_interface.collect_frontend_click_targets(breadcrumb_network_path)),
|
click_targets: Some(network_interface.collect_frontend_click_targets(breadcrumb_network_path)),
|
||||||
}),
|
}),
|
||||||
NodeGraphMessage::EndSendClickTargets => responses.add(FrontendMessage::UpdateClickTargets { click_targets: None }),
|
NodeGraphMessage::EndSendClickTargets => responses.add(FrontendMessage::UpdateClickTargets { click_targets: None }),
|
||||||
NodeGraphMessage::UpdateVisibleNodes => {
|
|
||||||
let Some(network_metadata) = network_interface.network_metadata(breadcrumb_network_path) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let viewport_bbox = ipp.document_bounds();
|
|
||||||
let document_bbox: [DVec2; 2] = viewport_bbox.map(|p| network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(p));
|
|
||||||
|
|
||||||
let mut nodes = Vec::new();
|
|
||||||
for node_id in &self.frontend_nodes {
|
|
||||||
let Some(node_bbox) = network_interface.node_bounding_box(node_id, breadcrumb_network_path) else {
|
|
||||||
log::error!("Could not get bbox for node: {node_id:?}");
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
if node_bbox[1].x >= document_bbox[0].x && node_bbox[0].x <= document_bbox[1].x && node_bbox[1].y >= document_bbox[0].y && node_bbox[0].y <= document_bbox[1].y {
|
|
||||||
nodes.push(*node_id);
|
|
||||||
}
|
|
||||||
for error in &self.node_graph_errors {
|
|
||||||
if error.node_path.contains(node_id) {
|
|
||||||
nodes.push(*node_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
responses.add(FrontendMessage::UpdateVisibleNodes { nodes });
|
|
||||||
}
|
|
||||||
NodeGraphMessage::SendGraph => {
|
NodeGraphMessage::SendGraph => {
|
||||||
responses.add(NodeGraphMessage::UpdateLayerPanel);
|
responses.add(NodeGraphMessage::UpdateLayerPanel);
|
||||||
responses.add(DocumentMessage::DocumentStructureChanged);
|
responses.add(DocumentMessage::DocumentStructureChanged);
|
||||||
responses.add(PropertiesPanelMessage::Refresh);
|
responses.add(PropertiesPanelMessage::Refresh);
|
||||||
responses.add(NodeGraphMessage::UpdateActionButtons);
|
responses.add(NodeGraphMessage::UpdateActionButtons);
|
||||||
|
|
||||||
if !self.should_render_svelte_nodes {
|
responses.add(FrontendMessage::RequestNativeNodeGraphRender);
|
||||||
// Generate and render node graph overlay network
|
|
||||||
} else {
|
|
||||||
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(NodeGraphMessage::UpdateVisibleNodes);
|
|
||||||
|
|
||||||
let layer_widths = network_interface.collect_layer_widths(breadcrumb_network_path);
|
|
||||||
|
|
||||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||||
responses.add(FrontendMessage::UpdateLayerWidths { layer_widths });
|
|
||||||
self.update_node_graph_hints(responses);
|
self.update_node_graph_hints(responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::SetGridAlignedEdges => {
|
|
||||||
if graph_view_overlay_open {
|
|
||||||
network_interface.set_grid_aligned_edges(DVec2::new(ipp.viewport_bounds.bottom_right.x - ipp.viewport_bounds.top_left.x, 0.), breadcrumb_network_path);
|
|
||||||
// Send the new edges to the frontend
|
|
||||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NodeGraphMessage::SetInputValue { node_id, input_index, value } => {
|
NodeGraphMessage::SetInputValue { node_id, input_index, value } => {
|
||||||
let input = NodeInput::value(value, false);
|
let input = NodeInput::value(value, false);
|
||||||
responses.add(NodeGraphMessage::SetInput {
|
responses.add(NodeGraphMessage::SetInput {
|
||||||
@@ -1780,14 +1733,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
NodeGraphMessage::TogglePreviewImpl { node_id } => {
|
NodeGraphMessage::TogglePreviewImpl { node_id } => {
|
||||||
network_interface.toggle_preview(node_id, selection_network_path);
|
network_interface.toggle_preview(node_id, selection_network_path);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::ToggleNativeNodeGraphRender => {
|
|
||||||
self.should_render_svelte_nodes = !self.should_render_svelte_nodes;
|
|
||||||
responses.add(FrontendMessage::UpdateShouldRenderSvelteNodes {
|
|
||||||
should_render_svelte_nodes: self.should_render_svelte_nodes,
|
|
||||||
});
|
|
||||||
responses.add(NodeGraphMessage::SendGraph);
|
|
||||||
responses.add(MenuBarMessage::SendLayout);
|
|
||||||
}
|
|
||||||
NodeGraphMessage::ToggleSelectedLocked => {
|
NodeGraphMessage::ToggleSelectedLocked => {
|
||||||
let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(selection_network_path) else {
|
let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(selection_network_path) else {
|
||||||
log::error!("Could not get selected nodes in NodeGraphMessage::ToggleSelectedLocked");
|
log::error!("Could not get selected nodes in NodeGraphMessage::ToggleSelectedLocked");
|
||||||
@@ -1957,7 +1902,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
// Do not show the add import or add export button in the document network;
|
// Do not show the add import or add export button in the document network;
|
||||||
let add_import_export = !breadcrumb_network_path.is_empty();
|
let add_import_export = !breadcrumb_network_path.is_empty();
|
||||||
|
|
||||||
responses.add(NodeGraphMessage::UpdateVisibleNodes);
|
|
||||||
responses.add(FrontendMessage::UpdateImportsExports {
|
responses.add(FrontendMessage::UpdateImportsExports {
|
||||||
imports,
|
imports,
|
||||||
exports,
|
exports,
|
||||||
@@ -1970,9 +1914,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
NodeGraphMessage::UpdateLayerPanel => {
|
NodeGraphMessage::UpdateLayerPanel => {
|
||||||
Self::update_layer_panel(network_interface, selection_network_path, collapsed, layers_panel_open, responses);
|
Self::update_layer_panel(network_interface, selection_network_path, collapsed, layers_panel_open, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::UpdateEdges => {
|
|
||||||
// Update the import/export UI edges whenever the PTZ changes or the bounding box of all nodes changes
|
|
||||||
}
|
|
||||||
NodeGraphMessage::UpdateNewNodeGraph => {
|
NodeGraphMessage::UpdateNewNodeGraph => {
|
||||||
let Some(selected_nodes) = network_interface.selected_nodes_mut(selection_network_path) else {
|
let Some(selected_nodes) = network_interface.selected_nodes_mut(selection_network_path) else {
|
||||||
log::error!("Could not get selected nodes in NodeGraphMessage::UpdateNewNodeGraph");
|
log::error!("Could not get selected nodes in NodeGraphMessage::UpdateNewNodeGraph");
|
||||||
@@ -2618,7 +2559,6 @@ impl Default for NodeGraphMessageHandler {
|
|||||||
reordering_export: None,
|
reordering_export: None,
|
||||||
reordering_import: None,
|
reordering_import: None,
|
||||||
end_index: None,
|
end_index: None,
|
||||||
frontend_nodes: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,8 +262,6 @@ pub struct FrontendClickTargets {
|
|||||||
pub icon_click_targets: Vec<String>,
|
pub icon_click_targets: Vec<String>,
|
||||||
#[serde(rename = "allNodesBoundingBox")]
|
#[serde(rename = "allNodesBoundingBox")]
|
||||||
pub all_nodes_bounding_box: String,
|
pub all_nodes_bounding_box: String,
|
||||||
#[serde(rename = "importExportsBoundingBox")]
|
|
||||||
pub import_exports_bounding_box: String,
|
|
||||||
#[serde(rename = "modifyImportExport")]
|
#[serde(rename = "modifyImportExport")]
|
||||||
pub modify_import_export: Vec<String>,
|
pub modify_import_export: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier, NodeRelations};
|
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier, NodeRelations};
|
||||||
use super::misc::PTZ;
|
use super::misc::PTZ;
|
||||||
use super::nodes::SelectedNodes;
|
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::consts::GRID_SIZE;
|
||||||
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
|
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::document_node_definitions::{DocumentNodeDefinition, resolve_document_node_type};
|
||||||
use crate::messages::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets};
|
use crate::messages::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets};
|
||||||
@@ -1620,68 +1620,6 @@ impl NodeNetworkInterface {
|
|||||||
network_metadata.transient_metadata.modify_import_export.unload();
|
network_metadata.transient_metadata.modify_import_export.unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rounded_network_edge_distance(&mut self, network_path: &[NodeId]) -> Option<&NetworkEdgeDistance> {
|
|
||||||
let Some(network_metadata) = self.network_metadata(network_path) else {
|
|
||||||
log::error!("Could not get nested network_metadata in rounded_network_edge_distance");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
if !network_metadata.transient_metadata.rounded_network_edge_distance.is_loaded() {
|
|
||||||
self.load_rounded_network_edge_distance(network_path);
|
|
||||||
}
|
|
||||||
let Some(network_metadata) = self.network_metadata(network_path) else {
|
|
||||||
log::error!("Could not get nested network_metadata in rounded_network_edge_distance");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
let TransientMetadata::Loaded(rounded_network_edge_distance) = &network_metadata.transient_metadata.rounded_network_edge_distance else {
|
|
||||||
log::error!("could not load import rounded_network_edge_distance");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
Some(rounded_network_edge_distance)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_rounded_network_edge_distance(&mut self, network_path: &[NodeId]) {
|
|
||||||
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
|
|
||||||
log::error!("Could not get nested network in set_grid_aligned_edges");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
// When setting the edges to be grid aligned, update the pixel offset to ensure the next pan starts from the snapped import/export position
|
|
||||||
let node_graph_to_viewport = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport;
|
|
||||||
// TODO: Eventually replace node graph top right with the footprint when trying to get the network edge distance
|
|
||||||
let node_graph_top_right = network_metadata.persistent_metadata.navigation_metadata.node_graph_top_right;
|
|
||||||
let target_exports_distance = node_graph_to_viewport.inverse().transform_point2(DVec2::new(
|
|
||||||
node_graph_top_right.x - EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP as f64,
|
|
||||||
node_graph_top_right.y + EXPORTS_TO_TOP_EDGE_PIXEL_GAP as f64,
|
|
||||||
));
|
|
||||||
|
|
||||||
let target_imports_distance = node_graph_to_viewport
|
|
||||||
.inverse()
|
|
||||||
.transform_point2(DVec2::new(IMPORTS_TO_LEFT_EDGE_PIXEL_GAP as f64, IMPORTS_TO_TOP_EDGE_PIXEL_GAP as f64));
|
|
||||||
|
|
||||||
let rounded_exports_distance = DVec2::new((target_exports_distance.x / 24. + 0.5).floor() * 24., (target_exports_distance.y / 24. + 0.5).floor() * 24.);
|
|
||||||
let rounded_imports_distance = DVec2::new((target_imports_distance.x / 24. + 0.5).floor() * 24., (target_imports_distance.y / 24. + 0.5).floor() * 24.);
|
|
||||||
|
|
||||||
let rounded_viewport_exports_distance = node_graph_to_viewport.transform_point2(rounded_exports_distance);
|
|
||||||
let rounded_viewport_imports_distance = node_graph_to_viewport.transform_point2(rounded_imports_distance);
|
|
||||||
|
|
||||||
let network_edge_distance = NetworkEdgeDistance {
|
|
||||||
exports_to_edge_distance: rounded_viewport_exports_distance,
|
|
||||||
imports_to_edge_distance: rounded_viewport_imports_distance,
|
|
||||||
};
|
|
||||||
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
|
|
||||||
log::error!("Could not get current network in load_export_ports");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
network_metadata.transient_metadata.rounded_network_edge_distance = TransientMetadata::Loaded(network_edge_distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unload_rounded_network_edge_distance(&mut self, network_path: &[NodeId]) {
|
|
||||||
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
|
|
||||||
log::error!("Could not get nested network_metadata in unload_export_ports");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
network_metadata.transient_metadata.rounded_network_edge_distance.unload();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn owned_nodes(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<&HashSet<NodeId>> {
|
fn owned_nodes(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<&HashSet<NodeId>> {
|
||||||
let layer_node = self.node_metadata(node_id, network_path)?;
|
let layer_node = self.node_metadata(node_id, network_path)?;
|
||||||
let NodeTypePersistentMetadata::Layer(LayerPersistentMetadata { owned_nodes, .. }) = &layer_node.persistent_metadata.node_type_metadata else {
|
let NodeTypePersistentMetadata::Layer(LayerPersistentMetadata { owned_nodes, .. }) = &layer_node.persistent_metadata.node_type_metadata else {
|
||||||
@@ -2299,33 +2237,6 @@ impl NodeNetworkInterface {
|
|||||||
let rect = Subpath::<PointId>::new_rect(bounds[0], bounds[1]);
|
let rect = Subpath::<PointId>::new_rect(bounds[0], bounds[1]);
|
||||||
let all_nodes_bounding_box = rect.to_bezpath().to_svg();
|
let all_nodes_bounding_box = rect.to_bezpath().to_svg();
|
||||||
|
|
||||||
let Some(rounded_network_edge_distance) = self.rounded_network_edge_distance(network_path).cloned() else {
|
|
||||||
log::error!("Could not get rounded_network_edge_distance in collect_frontend_click_targets");
|
|
||||||
return FrontendClickTargets::default();
|
|
||||||
};
|
|
||||||
let Some(network_metadata) = self.network_metadata(network_path) else {
|
|
||||||
log::error!("Could not get nested network_metadata in collect_frontend_click_targets");
|
|
||||||
return FrontendClickTargets::default();
|
|
||||||
};
|
|
||||||
let import_exports_viewport_top_left = rounded_network_edge_distance.imports_to_edge_distance;
|
|
||||||
let import_exports_viewport_bottom_right = rounded_network_edge_distance.exports_to_edge_distance;
|
|
||||||
|
|
||||||
let node_graph_top_left = network_metadata
|
|
||||||
.persistent_metadata
|
|
||||||
.navigation_metadata
|
|
||||||
.node_graph_to_viewport
|
|
||||||
.inverse()
|
|
||||||
.transform_point2(import_exports_viewport_top_left);
|
|
||||||
let node_graph_bottom_right = network_metadata
|
|
||||||
.persistent_metadata
|
|
||||||
.navigation_metadata
|
|
||||||
.node_graph_to_viewport
|
|
||||||
.inverse()
|
|
||||||
.transform_point2(import_exports_viewport_bottom_right);
|
|
||||||
|
|
||||||
let import_exports_target = Subpath::<PointId>::new_rect(node_graph_top_left, node_graph_bottom_right);
|
|
||||||
let import_exports_bounding_box = import_exports_target.to_bezpath().to_svg();
|
|
||||||
|
|
||||||
let mut modify_import_export = Vec::new();
|
let mut modify_import_export = Vec::new();
|
||||||
if let Some(modify_import_export_click_targets) = self.modify_import_export(network_path) {
|
if let Some(modify_import_export_click_targets) = self.modify_import_export(network_path) {
|
||||||
for click_target in modify_import_export_click_targets
|
for click_target in modify_import_export_click_targets
|
||||||
@@ -2344,7 +2255,6 @@ impl NodeNetworkInterface {
|
|||||||
connector_click_targets,
|
connector_click_targets,
|
||||||
icon_click_targets,
|
icon_click_targets,
|
||||||
all_nodes_bounding_box,
|
all_nodes_bounding_box,
|
||||||
import_exports_bounding_box,
|
|
||||||
modify_import_export,
|
modify_import_export,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2591,26 +2501,6 @@ impl NodeNetworkInterface {
|
|||||||
bounding_box_subpath.bounding_box_with_transform(network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport)
|
bounding_box_subpath.bounding_box_with_transform(network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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();
|
|
||||||
};
|
|
||||||
let nodes = network_metadata
|
|
||||||
.persistent_metadata
|
|
||||||
.node_metadata
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(node_id, _)| if self.is_layer(node_id, network_path) { Some(*node_id) } else { None })
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let layer_widths = nodes
|
|
||||||
.iter()
|
|
||||||
.filter_map(|node_id| self.layer_width(node_id, network_path).map(|layer_width| (*node_id, layer_width)))
|
|
||||||
.collect::<HashMap<NodeId, u32>>();
|
|
||||||
|
|
||||||
layer_widths
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option<Vector> {
|
pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option<Vector> {
|
||||||
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, self);
|
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, self);
|
||||||
|
|
||||||
@@ -2785,18 +2675,6 @@ impl NodeNetworkInterface {
|
|||||||
self.unload_modify_import_export(network_path);
|
self.unload_modify_import_export(network_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should be run whenever the pan ends, a zoom occurs, or the network is opened
|
|
||||||
pub fn set_grid_aligned_edges(&mut self, node_graph_top_right: DVec2, network_path: &[NodeId]) {
|
|
||||||
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
|
|
||||||
log::error!("Could not get nested network_metadata in set_grid_aligned_edges");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
network_metadata.persistent_metadata.navigation_metadata.node_graph_top_right = node_graph_top_right;
|
|
||||||
self.unload_rounded_network_edge_distance(network_path);
|
|
||||||
self.unload_import_export_ports(network_path);
|
|
||||||
self.unload_modify_import_export(network_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vector_modify(&mut self, node_id: &NodeId, modification_type: VectorModificationType) {
|
pub fn vector_modify(&mut self, node_id: &NodeId, modification_type: VectorModificationType) {
|
||||||
let Some(node) = self.network_mut(&[]).unwrap().nodes.get_mut(node_id) else {
|
let Some(node) = self.network_mut(&[]).unwrap().nodes.get_mut(node_id) else {
|
||||||
log::error!("Could not get node in vector_modification");
|
log::error!("Could not get node in vector_modification");
|
||||||
@@ -5581,8 +5459,6 @@ pub struct NodeNetworkTransientMetadata {
|
|||||||
pub import_export_ports: TransientMetadata<Ports>,
|
pub import_export_ports: TransientMetadata<Ports>,
|
||||||
/// Click targets for adding, removing, and moving import/export ports
|
/// Click targets for adding, removing, and moving import/export ports
|
||||||
pub modify_import_export: TransientMetadata<ModifyImportExportClickTarget>,
|
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>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
+13
-5
@@ -90,15 +90,23 @@ impl NodeNetworkInterface {
|
|||||||
|
|
||||||
let position = FrontendXY { x: position.x, y: position.y };
|
let position = FrontendXY { x: position.x, y: position.y };
|
||||||
|
|
||||||
let inputs = (0..self.number_of_inputs(&node_id, network_path))
|
let primary_input = self.frontend_input_from_connector(&InputConnector::node(node_id, 0), network_path);
|
||||||
.map(|input_index| self.frontend_input_from_connector(&InputConnector::node(node_id, input_index), network_path))
|
let secondary_inputs = (1..self.number_of_inputs(&node_id, network_path))
|
||||||
|
.filter_map(|input_index| self.frontend_input_from_connector(&InputConnector::node(node_id, input_index), network_path))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let outputs = (0..self.number_of_outputs(&node_id, network_path))
|
let primary_output = self.frontend_output_from_connector(&OutputConnector::node(node_id, 0), network_path);
|
||||||
.map(|output_index| self.frontend_output_from_connector(&OutputConnector::node(node_id, output_index), network_path))
|
let secondary_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();
|
.collect();
|
||||||
|
|
||||||
let node = Some(FrontendNode { position, inputs, outputs });
|
let node = Some(FrontendNode {
|
||||||
|
position,
|
||||||
|
primary_input,
|
||||||
|
primary_output,
|
||||||
|
secondary_inputs,
|
||||||
|
secondary_outputs,
|
||||||
|
});
|
||||||
|
|
||||||
FrontendNodeOrLayer { node, layer: None }
|
FrontendNodeOrLayer { node, layer: None }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,8 +54,19 @@ pub fn build_vector_wire(output_position: DVec2, input_position: DVec2, vertical
|
|||||||
let horizontal_curve = horizontal_curve_amount * curve_length;
|
let horizontal_curve = horizontal_curve_amount * curve_length;
|
||||||
let vertical_curve = vertical_curve_amount * curve_length;
|
let vertical_curve = vertical_curve_amount * curve_length;
|
||||||
|
|
||||||
|
let wire_start = if vertical_in && vertical_out { output_position + DVec2::new(0., -4.) } else { output_position };
|
||||||
|
let wire_end = if vertical_in && vertical_in {
|
||||||
|
DVec2::new(input_position.x, input_position.y) + DVec2::new(0., 4.)
|
||||||
|
} else {
|
||||||
|
DVec2::new(input_position.x, input_position.y)
|
||||||
|
};
|
||||||
|
|
||||||
|
if vertical_in && vertical_in && wire_end.y + 5. > wire_start.y {
|
||||||
|
return BezPath::new();
|
||||||
|
}
|
||||||
|
|
||||||
let locations = [
|
let locations = [
|
||||||
output_position,
|
wire_start,
|
||||||
DVec2::new(
|
DVec2::new(
|
||||||
if vertical_out { output_position.x } else { output_position.x + horizontal_curve },
|
if vertical_out { output_position.x } else { output_position.x + horizontal_curve },
|
||||||
if vertical_out { output_position.y - vertical_curve } else { output_position.y },
|
if vertical_out { output_position.y - vertical_curve } else { output_position.y },
|
||||||
@@ -64,7 +75,7 @@ pub fn build_vector_wire(output_position: DVec2, input_position: DVec2, vertical
|
|||||||
if vertical_in { input_position.x } else { input_position.x - horizontal_curve },
|
if vertical_in { input_position.x } else { input_position.x - horizontal_curve },
|
||||||
if vertical_in { input_position.y + vertical_curve } else { input_position.y },
|
if vertical_in { input_position.y + vertical_curve } else { input_position.y },
|
||||||
),
|
),
|
||||||
DVec2::new(input_position.x, input_position.y),
|
wire_end,
|
||||||
];
|
];
|
||||||
|
|
||||||
let smoothing = 0.5;
|
let smoothing = 0.5;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ pub struct MenuBarMessageHandler {
|
|||||||
pub has_selection_history: (bool, bool),
|
pub has_selection_history: (bool, bool),
|
||||||
pub message_logging_verbosity: MessageLoggingVerbosity,
|
pub message_logging_verbosity: MessageLoggingVerbosity,
|
||||||
pub reset_node_definitions_on_open: bool,
|
pub reset_node_definitions_on_open: bool,
|
||||||
pub should_render_svelte_nodes: bool,
|
|
||||||
pub make_path_editable_is_allowed: bool,
|
pub make_path_editable_is_allowed: bool,
|
||||||
pub data_panel_open: bool,
|
pub data_panel_open: bool,
|
||||||
pub layers_panel_open: bool,
|
pub layers_panel_open: bool,
|
||||||
@@ -49,7 +48,6 @@ impl LayoutHolder for MenuBarMessageHandler {
|
|||||||
let message_logging_verbosity_names = self.message_logging_verbosity == MessageLoggingVerbosity::Names;
|
let message_logging_verbosity_names = self.message_logging_verbosity == MessageLoggingVerbosity::Names;
|
||||||
let message_logging_verbosity_contents = self.message_logging_verbosity == MessageLoggingVerbosity::Contents;
|
let message_logging_verbosity_contents = self.message_logging_verbosity == MessageLoggingVerbosity::Contents;
|
||||||
let reset_node_definitions_on_open = self.reset_node_definitions_on_open;
|
let reset_node_definitions_on_open = self.reset_node_definitions_on_open;
|
||||||
let should_render_svelte_nodes = self.should_render_svelte_nodes;
|
|
||||||
let make_path_editable_is_allowed = self.make_path_editable_is_allowed;
|
let make_path_editable_is_allowed = self.make_path_editable_is_allowed;
|
||||||
|
|
||||||
let menu_bar_entries = vec![
|
let menu_bar_entries = vec![
|
||||||
@@ -698,12 +696,6 @@ impl LayoutHolder for MenuBarMessageHandler {
|
|||||||
action: MenuBarEntry::create_action(|_| PortfolioMessage::ToggleResetNodesToDefinitionsOnOpen.into()),
|
action: MenuBarEntry::create_action(|_| PortfolioMessage::ToggleResetNodesToDefinitionsOnOpen.into()),
|
||||||
..MenuBarEntry::default()
|
..MenuBarEntry::default()
|
||||||
}],
|
}],
|
||||||
vec![MenuBarEntry {
|
|
||||||
label: "HTML Node Graph Render".into(),
|
|
||||||
icon: Some(if should_render_svelte_nodes { "CheckboxChecked" } else { "CheckboxUnchecked" }.into()),
|
|
||||||
action: MenuBarEntry::create_action(|_| NodeGraphMessage::ToggleNativeNodeGraphRender.into()),
|
|
||||||
..MenuBarEntry::default()
|
|
||||||
}],
|
|
||||||
vec![
|
vec![
|
||||||
MenuBarEntry {
|
MenuBarEntry {
|
||||||
label: "Print Trace Logs".into(),
|
label: "Print Trace Logs".into(),
|
||||||
|
|||||||
@@ -587,7 +587,6 @@
|
|||||||
thumbPosition={scrollbarPos.x}
|
thumbPosition={scrollbarPos.x}
|
||||||
on:trackShift={({ detail }) => editor.handle.panCanvasByFraction(detail, 0)}
|
on:trackShift={({ detail }) => editor.handle.panCanvasByFraction(detail, 0)}
|
||||||
on:thumbPosition={({ detail }) => panCanvasX(detail)}
|
on:thumbPosition={({ detail }) => panCanvasX(detail)}
|
||||||
on:thumbDragEnd={() => editor.handle.setGridAlignedEdges()}
|
|
||||||
on:thumbDragStart={() => editor.handle.panCanvasAbortPrepare(true)}
|
on:thumbDragStart={() => editor.handle.panCanvasAbortPrepare(true)}
|
||||||
on:thumbDragAbort={() => editor.handle.panCanvasAbort(true)}
|
on:thumbDragAbort={() => editor.handle.panCanvasAbort(true)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -617,7 +617,6 @@
|
|||||||
<path class="visibility" d={pathString} />
|
<path class="visibility" d={pathString} />
|
||||||
{/each}
|
{/each}
|
||||||
<path class="all-nodes-bounding-box" d={$nodeGraph.clickTargets.allNodesBoundingBox} />
|
<path class="all-nodes-bounding-box" d={$nodeGraph.clickTargets.allNodesBoundingBox} />
|
||||||
<path class="all-nodes-bounding-box" d={$nodeGraph.clickTargets.importExportsBoundingBox} />
|
|
||||||
{#each $nodeGraph.clickTargets.modifyImportExport as pathString}
|
{#each $nodeGraph.clickTargets.modifyImportExport as pathString}
|
||||||
<path class="modify-import-export" d={pathString} />
|
<path class="modify-import-export" d={pathString} />
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ export class FrontendClickTargets {
|
|||||||
readonly connectorClickTargets!: string[];
|
readonly connectorClickTargets!: string[];
|
||||||
readonly iconClickTargets!: string[];
|
readonly iconClickTargets!: string[];
|
||||||
readonly allNodesBoundingBox!: string;
|
readonly allNodesBoundingBox!: string;
|
||||||
readonly importExportsBoundingBox!: string;
|
|
||||||
readonly modifyImportExport!: string[];
|
readonly modifyImportExport!: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,30 +105,10 @@ export class UpdateLayerWidths extends JsMessage {
|
|||||||
readonly layerWidths!: Map<bigint, number>;
|
readonly layerWidths!: Map<bigint, number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UpdateNodeGraphSvelteRender extends JsMessage {
|
|
||||||
readonly nodesToRender!: FrontendNodeToRender[];
|
|
||||||
|
|
||||||
readonly open!: boolean;
|
|
||||||
|
|
||||||
readonly opacity!: number;
|
|
||||||
|
|
||||||
readonly inSelectedNetwork!: boolean;
|
|
||||||
|
|
||||||
readonly previewedNode!: bigint | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UpdateShouldRenderSvelteNodes extends JsMessage {
|
|
||||||
readonly shouldRenderSvelteNodes!: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UpdateNativeNodeGraphSVG extends JsMessage {
|
export class UpdateNativeNodeGraphSVG extends JsMessage {
|
||||||
readonly svgString!: string;
|
readonly svgString!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UpdateVisibleNodes extends JsMessage {
|
|
||||||
readonly nodes!: bigint[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UpdateNodeGraphTransform extends JsMessage {
|
export class UpdateNodeGraphTransform extends JsMessage {
|
||||||
readonly transform!: NodeGraphTransform;
|
readonly transform!: NodeGraphTransform;
|
||||||
}
|
}
|
||||||
@@ -1762,9 +1741,9 @@ export const messageMakers: Record<string, MessageMaker> = {
|
|||||||
UpdateMenuBarLayout,
|
UpdateMenuBarLayout,
|
||||||
UpdateMouseCursor,
|
UpdateMouseCursor,
|
||||||
UpdateNodeGraphControlBarLayout,
|
UpdateNodeGraphControlBarLayout,
|
||||||
UpdateNodeGraphRender,
|
UpdateNativeNodeGraphSVG,
|
||||||
UpdateNodeGraphSelectionBox,
|
|
||||||
UpdateNodeGraphTransform,
|
UpdateNodeGraphTransform,
|
||||||
|
UpdateNodeGraphSelectionBox,
|
||||||
UpdateNodeThumbnail,
|
UpdateNodeThumbnail,
|
||||||
UpdateOpenDocumentsList,
|
UpdateOpenDocumentsList,
|
||||||
UpdatePlatform,
|
UpdatePlatform,
|
||||||
@@ -1776,7 +1755,6 @@ export const messageMakers: Record<string, MessageMaker> = {
|
|||||||
UpdateToolOptionsLayout,
|
UpdateToolOptionsLayout,
|
||||||
UpdateToolShelfLayout,
|
UpdateToolShelfLayout,
|
||||||
UpdateViewportHolePunch,
|
UpdateViewportHolePunch,
|
||||||
UpdateVisibleNodes,
|
|
||||||
UpdateWirePathInProgress,
|
UpdateWirePathInProgress,
|
||||||
UpdateWorkingColorsLayout,
|
UpdateWorkingColorsLayout,
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
@@ -15,14 +15,11 @@ import {
|
|||||||
UpdateExportReorderIndex,
|
UpdateExportReorderIndex,
|
||||||
UpdateImportsExports,
|
UpdateImportsExports,
|
||||||
UpdateLayerWidths,
|
UpdateLayerWidths,
|
||||||
UpdateNodeGraphSvelteRender,
|
|
||||||
UpdateShouldRenderSvelteNodes,
|
|
||||||
UpdateNativeNodeGraphSVG,
|
UpdateNativeNodeGraphSVG,
|
||||||
UpdateVisibleNodes,
|
|
||||||
UpdateNodeGraphTransform,
|
|
||||||
UpdateNodeThumbnail,
|
UpdateNodeThumbnail,
|
||||||
UpdateWirePathInProgress,
|
UpdateWirePathInProgress,
|
||||||
UpdateNodeGraphSelectionBox,
|
UpdateNodeGraphSelectionBox,
|
||||||
|
UpdateNodeGraphTransform,
|
||||||
} from "@graphite/messages";
|
} from "@graphite/messages";
|
||||||
|
|
||||||
export function createNodeGraphState(editor: Editor) {
|
export function createNodeGraphState(editor: Editor) {
|
||||||
@@ -46,11 +43,6 @@ export function createNodeGraphState(editor: Editor) {
|
|||||||
inSelectedNetwork: true,
|
inSelectedNetwork: true,
|
||||||
previewedNode: undefined as bigint | undefined,
|
previewedNode: undefined as bigint | undefined,
|
||||||
|
|
||||||
// TODO: Remove these fields
|
|
||||||
visibleNodes: new Set<bigint>(),
|
|
||||||
layerWidths: new Map<bigint, number>(),
|
|
||||||
shouldRenderSvelteNodes: false,
|
|
||||||
|
|
||||||
// Data that will be passed in the context
|
// Data that will be passed in the context
|
||||||
thumbnails: new Map<bigint, string>(),
|
thumbnails: new Map<bigint, string>(),
|
||||||
transform: { scale: 1, x: 0, y: 0 },
|
transform: { scale: 1, x: 0, y: 0 },
|
||||||
@@ -107,42 +99,12 @@ export function createNodeGraphState(editor: Editor) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.subscriptions.subscribeJsMessage(UpdateLayerWidths, (updateLayerWidths) => {
|
|
||||||
update((state) => {
|
|
||||||
state.layerWidths = updateLayerWidths.layerWidths;
|
|
||||||
return state;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphSvelteRender, (updateNodeGraphSvelteRender) => {
|
|
||||||
update((state) => {
|
|
||||||
state.nodesToRender.clear();
|
|
||||||
updateNodeGraphSvelteRender.nodesToRender.forEach((node) => {
|
|
||||||
state.nodesToRender.set(node.metadata.nodeId, node);
|
|
||||||
});
|
|
||||||
state.opacity = updateNodeGraphSvelteRender.opacity;
|
|
||||||
state.inSelectedNetwork = updateNodeGraphSvelteRender.inSelectedNetwork;
|
|
||||||
state.previewedNode = updateNodeGraphSvelteRender.previewedNode;
|
|
||||||
return state;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
editor.subscriptions.subscribeJsMessage(UpdateShouldRenderSvelteNodes, (UpdateShouldRenderSvelteNodes) => {
|
|
||||||
update((state) => {
|
|
||||||
state.shouldRenderSvelteNodes = UpdateShouldRenderSvelteNodes.shouldRenderSvelteNodes;
|
|
||||||
return state;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
editor.subscriptions.subscribeJsMessage(UpdateNativeNodeGraphSVG, (updateNativeNodeGraphRender) => {
|
editor.subscriptions.subscribeJsMessage(UpdateNativeNodeGraphSVG, (updateNativeNodeGraphRender) => {
|
||||||
update((state) => {
|
update((state) => {
|
||||||
state.nativeNodeGraphSVGString = updateNativeNodeGraphRender.svgString;
|
state.nativeNodeGraphSVGString = updateNativeNodeGraphRender.svgString;
|
||||||
return state;
|
return state;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
editor.subscriptions.subscribeJsMessage(UpdateVisibleNodes, (updateVisibleNodes) => {
|
|
||||||
update((state) => {
|
|
||||||
state.visibleNodes = new Set<bigint>(updateVisibleNodes.nodes);
|
|
||||||
return state;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphTransform, (updateNodeGraphTransform) => {
|
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphTransform, (updateNodeGraphTransform) => {
|
||||||
update((state) => {
|
update((state) => {
|
||||||
state.transform = updateNodeGraphTransform.transform;
|
state.transform = updateNodeGraphTransform.transform;
|
||||||
@@ -155,12 +117,6 @@ export function createNodeGraphState(editor: Editor) {
|
|||||||
return state;
|
return state;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
editor.subscriptions.subscribeJsMessage(UpdateWirePathInProgress, (updateWirePathInProgress) => {
|
|
||||||
update((state) => {
|
|
||||||
state.wirePathInProgress = updateWirePathInProgress.wirePathInProgress;
|
|
||||||
return state;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
|
|||||||
@@ -785,13 +785,6 @@ impl EditorHandle {
|
|||||||
self.dispatch(message);
|
self.dispatch(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Snaps the import/export edges to a grid space when the scroll bar is released
|
|
||||||
#[wasm_bindgen(js_name = setGridAlignedEdges)]
|
|
||||||
pub fn set_grid_aligned_edges(&self) {
|
|
||||||
let message = NodeGraphMessage::SetGridAlignedEdges;
|
|
||||||
self.dispatch(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Merge the selected nodes into a subnetwork
|
/// Merge the selected nodes into a subnetwork
|
||||||
#[wasm_bindgen(js_name = mergeSelectedNodes)]
|
#[wasm_bindgen(js_name = mergeSelectedNodes)]
|
||||||
pub fn merge_nodes(&self) {
|
pub fn merge_nodes(&self) {
|
||||||
|
|||||||
@@ -21,12 +21,14 @@ pub mod ui_context;
|
|||||||
#[node_macro::node(skip_impl)]
|
#[node_macro::node(skip_impl)]
|
||||||
pub fn generate_nodes(_: impl Ctx, mut node_graph_overlay_data: NodeGraphOverlayData) -> Table<Graphic> {
|
pub fn generate_nodes(_: impl Ctx, mut node_graph_overlay_data: NodeGraphOverlayData) -> Table<Graphic> {
|
||||||
let mut nodes_and_wires = Table::new();
|
let mut nodes_and_wires = Table::new();
|
||||||
let layers = draw_layers(&node_graph_overlay_data.nodes_to_render);
|
let (layers, side_ports) = draw_layers(&node_graph_overlay_data.nodes_to_render);
|
||||||
nodes_and_wires.extend(layers);
|
nodes_and_wires.extend(layers);
|
||||||
|
|
||||||
let wires = draw_wires(&mut node_graph_overlay_data.nodes_to_render);
|
let wires = draw_wires(&mut node_graph_overlay_data.nodes_to_render);
|
||||||
nodes_and_wires.extend(wires);
|
nodes_and_wires.extend(wires);
|
||||||
|
|
||||||
|
nodes_and_wires.extend(side_ports);
|
||||||
|
|
||||||
let nodes = draw_nodes(&node_graph_overlay_data.nodes_to_render);
|
let nodes = draw_nodes(&node_graph_overlay_data.nodes_to_render);
|
||||||
nodes_and_wires.extend(nodes);
|
nodes_and_wires.extend(nodes);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphene_core_shaders::color::{AlphaMut, Color};
|
use graphene_core_shaders::color::{AlphaMut, Color};
|
||||||
use kurbo::{BezPath, Rect, RoundedRect, Shape};
|
use kurbo::{BezPath, Circle, Rect, RoundedRect, Shape};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Graphic,
|
Graphic,
|
||||||
@@ -26,9 +26,9 @@ pub fn draw_nodes(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
let x = frontend_node.position.x as f64 * GRID_SIZE;
|
let x = frontend_node.position.x as f64 * GRID_SIZE;
|
||||||
let y = frontend_node.position.y as f64 * GRID_SIZE + GRID_SIZE / 2.;
|
let y = frontend_node.position.y as f64 * GRID_SIZE + GRID_SIZE / 2.;
|
||||||
let node_width = GRID_SIZE * 5.0;
|
let node_width = GRID_SIZE * 5.0;
|
||||||
let number_of_exposed_inputs = frontend_node.inputs.iter().skip(1).filter(|x| x.is_some()).count();
|
let number_of_secondary_inputs = frontend_node.secondary_inputs.len();
|
||||||
let number_of_exposed_outputs = frontend_node.outputs.iter().skip(1).filter(|x| x.is_some()).count();
|
let number_of_secondary_outputs = frontend_node.secondary_outputs.len();
|
||||||
let number_of_rows = 1 + number_of_exposed_inputs.max(number_of_exposed_outputs);
|
let number_of_rows = 1 + number_of_secondary_inputs.max(number_of_secondary_outputs);
|
||||||
let node_height = number_of_rows as f64 * GRID_SIZE;
|
let node_height = number_of_rows as f64 * GRID_SIZE;
|
||||||
|
|
||||||
let node_rect = RoundedRect::new(x, y, x + node_width, y + node_height, 2.);
|
let node_rect = RoundedRect::new(x, y, x + node_width, y + node_height, 2.);
|
||||||
@@ -49,7 +49,7 @@ pub fn draw_nodes(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
bg_vector.style.fill = crate::vector::style::Fill::Solid(node_color.clone());
|
bg_vector.style.fill = crate::vector::style::Fill::Solid(node_color.clone());
|
||||||
bg_table.push(TableRow::new_from_element(bg_vector));
|
bg_table.push(TableRow::new_from_element(bg_vector));
|
||||||
// Make primary input brighter
|
// Make primary input brighter
|
||||||
if number_of_exposed_inputs == 0 {
|
if number_of_secondary_inputs == 0 {
|
||||||
// Draw the first row with rounded bottom corners
|
// Draw the first row with rounded bottom corners
|
||||||
bg_table.push(TableRow::new_from_element(node_first_row(x, y, false)));
|
bg_table.push(TableRow::new_from_element(node_first_row(x, y, false)));
|
||||||
} else {
|
} else {
|
||||||
@@ -62,7 +62,7 @@ pub fn draw_nodes(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
let mut border_mask_path = BezPath::new();
|
let mut border_mask_path = BezPath::new();
|
||||||
border_mask_path.move_to((-2., -2.));
|
border_mask_path.move_to((-2., -2.));
|
||||||
border_mask_path.line_to((node_width + 2., -2.));
|
border_mask_path.line_to((node_width + 2., -2.));
|
||||||
if frontend_node.outputs[0].is_some() {
|
if frontend_node.primary_output.is_some() {
|
||||||
border_mask_path.line_to((node_width + 2., 4.));
|
border_mask_path.line_to((node_width + 2., 4.));
|
||||||
border_mask_path.line_to((node_width - 2., 4.));
|
border_mask_path.line_to((node_width - 2., 4.));
|
||||||
border_mask_path.line_to((node_width - 2., 20.));
|
border_mask_path.line_to((node_width - 2., 20.));
|
||||||
@@ -70,7 +70,7 @@ pub fn draw_nodes(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
border_mask_path.line_to((node_width + 2., 20.));
|
border_mask_path.line_to((node_width + 2., 20.));
|
||||||
for row in 1..number_of_rows {
|
for row in 1..number_of_rows {
|
||||||
border_mask_path.line_to((node_width + 2., row as f64 * GRID_SIZE + 4.));
|
border_mask_path.line_to((node_width + 2., row as f64 * GRID_SIZE + 4.));
|
||||||
if frontend_node.outputs.get(row).is_some_and(|output| output.is_some()) {
|
if row <= number_of_secondary_outputs {
|
||||||
border_mask_path.line_to((node_width - 2., row as f64 * GRID_SIZE + 4.));
|
border_mask_path.line_to((node_width - 2., row as f64 * GRID_SIZE + 4.));
|
||||||
border_mask_path.line_to((node_width - 2., row as f64 * GRID_SIZE + 20.));
|
border_mask_path.line_to((node_width - 2., row as f64 * GRID_SIZE + 20.));
|
||||||
border_mask_path.line_to((node_width + 2., row as f64 * GRID_SIZE + 20.));
|
border_mask_path.line_to((node_width + 2., row as f64 * GRID_SIZE + 20.));
|
||||||
@@ -80,13 +80,13 @@ pub fn draw_nodes(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
border_mask_path.line_to((-2., number_of_rows as f64 * GRID_SIZE + 2.));
|
border_mask_path.line_to((-2., number_of_rows as f64 * GRID_SIZE + 2.));
|
||||||
for row in (1..number_of_rows).rev() {
|
for row in (1..number_of_rows).rev() {
|
||||||
border_mask_path.line_to((-2., row as f64 * GRID_SIZE + 20.));
|
border_mask_path.line_to((-2., row as f64 * GRID_SIZE + 20.));
|
||||||
if frontend_node.inputs.iter().skip(1).filter(|input| input.is_some()).nth(row - 1).is_some_and(|input| input.is_some()) {
|
if row <= number_of_secondary_inputs {
|
||||||
border_mask_path.line_to((2., row as f64 * GRID_SIZE + 20.));
|
border_mask_path.line_to((2., row as f64 * GRID_SIZE + 20.));
|
||||||
border_mask_path.line_to((2., row as f64 * GRID_SIZE + 4.));
|
border_mask_path.line_to((2., row as f64 * GRID_SIZE + 4.));
|
||||||
border_mask_path.line_to((2., row as f64 * GRID_SIZE + 4.));
|
border_mask_path.line_to((2., row as f64 * GRID_SIZE + 4.));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if frontend_node.inputs[0].is_some() {
|
if frontend_node.primary_input.is_some() {
|
||||||
border_mask_path.line_to((-2., 20.));
|
border_mask_path.line_to((-2., 20.));
|
||||||
border_mask_path.line_to((2., 20.));
|
border_mask_path.line_to((2., 20.));
|
||||||
border_mask_path.line_to((2., 4.));
|
border_mask_path.line_to((2., 4.));
|
||||||
@@ -105,7 +105,8 @@ pub fn draw_nodes(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
// Border table is implemented as a clip mask
|
// Border table is implemented as a clip mask
|
||||||
let mut border_table = Table::new();
|
let mut border_table = Table::new();
|
||||||
let mut border_vector = Vector::from_bezpath(node_bez_path);
|
let mut border_vector = Vector::from_bezpath(node_bez_path);
|
||||||
let primary_output_color = frontend_node.outputs[0]
|
let primary_output_color = frontend_node
|
||||||
|
.primary_output
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|primary_output| primary_output.data_type.data_color_dim())
|
.map(|primary_output| primary_output.data_type.data_color_dim())
|
||||||
.unwrap_or(FrontendGraphDataType::General.data_color_dim());
|
.unwrap_or(FrontendGraphDataType::General.data_color_dim());
|
||||||
@@ -132,15 +133,16 @@ pub fn draw_nodes(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
for text_row in node_text.iter_mut() {
|
for text_row in node_text.iter_mut() {
|
||||||
*text_row.transform = DAffine2::from_translation(DVec2::new(x + 8., y + 3.));
|
*text_row.transform = DAffine2::from_translation(DVec2::new(x + 8., y + 3.));
|
||||||
}
|
}
|
||||||
for (row, input) in frontend_node.inputs.iter().enumerate().skip(1) {
|
|
||||||
if let Some(input) = input {
|
for row in 1..=number_of_rows {
|
||||||
|
if let Some(input) = frontend_node.secondary_inputs.get(row - 1) {
|
||||||
let font_blob = Some(text::load_font(SOURCE_SANS_FONT_DATA));
|
let font_blob = Some(text::load_font(SOURCE_SANS_FONT_DATA));
|
||||||
let mut input_row_text = crate::text::to_path(&input.name, font_blob, typesetting, false);
|
let mut input_row_text = crate::text::to_path(&input.name, font_blob, typesetting, false);
|
||||||
for text_row in input_row_text.iter_mut() {
|
for text_row in input_row_text.iter_mut() {
|
||||||
*text_row.transform = DAffine2::from_translation(DVec2::new(x + 8., y + 24. * row as f64 + 3.));
|
*text_row.transform = DAffine2::from_translation(DVec2::new(x + 8., y + 24. * row as f64 + 3.));
|
||||||
}
|
}
|
||||||
node_text.extend(input_row_text);
|
node_text.extend(input_row_text);
|
||||||
} else if let Some(Some(output)) = frontend_node.outputs.get(row) {
|
} else if let Some(output) = frontend_node.secondary_outputs.get(row - 1) {
|
||||||
let font_blob = Some(text::load_font(SOURCE_SANS_FONT_DATA));
|
let font_blob = Some(text::load_font(SOURCE_SANS_FONT_DATA));
|
||||||
let mut output_row_text = crate::text::to_path(&output.name, font_blob, typesetting, false);
|
let mut output_row_text = crate::text::to_path(&output.name, font_blob, typesetting, false);
|
||||||
// Find width to right align text
|
// Find width to right align text
|
||||||
@@ -176,14 +178,41 @@ pub fn draw_nodes(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
text_area_row.alpha_blending.clip = true;
|
text_area_row.alpha_blending.clip = true;
|
||||||
let text_area_table = Table::new_from_row(text_area_row);
|
let text_area_table = Table::new_from_row(text_area_row);
|
||||||
node_table.push(TableRow::new_from_element(Graphic::Vector(text_area_table)));
|
node_table.push(TableRow::new_from_element(Graphic::Vector(text_area_table)));
|
||||||
|
|
||||||
|
// Input and output ports
|
||||||
|
let mut ports_table = Table::new();
|
||||||
|
if let Some(primary_input) = &frontend_node.primary_input {
|
||||||
|
let mut row = port_row(&primary_input.data_type);
|
||||||
|
row.transform = DAffine2::from_translation(DVec2::new(0., 12.));
|
||||||
|
ports_table.push(row);
|
||||||
|
}
|
||||||
|
for (index, secondary_input) in frontend_node.secondary_inputs.iter().enumerate() {
|
||||||
|
let mut row = port_row(&secondary_input.data_type);
|
||||||
|
row.transform = DAffine2::from_translation(DVec2::new(0., 12. + GRID_SIZE * (index + 1) as f64));
|
||||||
|
ports_table.push(row);
|
||||||
|
}
|
||||||
|
if let Some(primary_output) = &frontend_node.primary_output {
|
||||||
|
let mut row = port_row(&primary_output.data_type);
|
||||||
|
row.transform = DAffine2::from_translation(DVec2::new(5. * GRID_SIZE, 12.));
|
||||||
|
ports_table.push(row);
|
||||||
|
}
|
||||||
|
for (index, secondary_output) in frontend_node.secondary_outputs.iter().enumerate() {
|
||||||
|
let mut row = port_row(&secondary_output.data_type);
|
||||||
|
row.transform = DAffine2::from_translation(DVec2::new(5. * GRID_SIZE, 12. + GRID_SIZE * (index + 1) as f64));
|
||||||
|
ports_table.push(row);
|
||||||
|
}
|
||||||
|
let mut graphic_ports_row = TableRow::new_from_element(Graphic::Vector(ports_table));
|
||||||
|
graphic_ports_row.transform = DAffine2::from_translation(DVec2::new(x - 3., y - 4.));
|
||||||
|
node_table.push(graphic_ports_row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node_table
|
node_table
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_layers(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
pub fn draw_layers(nodes: &Vec<FrontendNodeToRender>) -> (Table<Graphic>, Table<Graphic>) {
|
||||||
let mut layer_table = Table::new();
|
let mut layer_table = Table::new();
|
||||||
|
let mut side_ports = Table::new();
|
||||||
for node_to_render in nodes {
|
for node_to_render in nodes {
|
||||||
if let Some(frontend_layer) = node_to_render.node_or_layer.layer.as_ref() {
|
if let Some(frontend_layer) = node_to_render.node_or_layer.layer.as_ref() {
|
||||||
// The layer position is the top left of the thumbnail
|
// The layer position is the top left of the thumbnail
|
||||||
@@ -219,12 +248,12 @@ pub fn draw_layers(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
|
|
||||||
// Text starts at thumbnail + left padding
|
// Text starts at thumbnail + left padding
|
||||||
let text_start = 12. + 8.;
|
let text_start = 12. + 8.;
|
||||||
let right_text_edge = text_start + text_width;
|
let right_text_edge = 8. + text_width;
|
||||||
let rounded_text_edge = (right_text_edge as f64 / 24.).ceil() * 24.;
|
let rounded_text_edge = (right_text_edge as f64 / 24.).ceil() * 24.;
|
||||||
|
|
||||||
let rounded_layer_width_pixels = rounded_text_edge + 24.;
|
let rounded_layer_width_pixels = rounded_text_edge + 24.;
|
||||||
// Subtract the left thumbnail
|
// add the left thumbnail gap
|
||||||
let layer_right_edge_width = rounded_layer_width_pixels - 12.;
|
let layer_right_edge_width = rounded_layer_width_pixels + 12.;
|
||||||
|
|
||||||
let right_layer_width = layer_right_edge_width.max(4.5 * GRID_SIZE);
|
let right_layer_width = layer_right_edge_width.max(4.5 * GRID_SIZE);
|
||||||
let thumbnail_width = 3. * GRID_SIZE;
|
let thumbnail_width = 3. * GRID_SIZE;
|
||||||
@@ -305,10 +334,84 @@ pub fn draw_layers(nodes: &Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
|||||||
}
|
}
|
||||||
let top_layer = text_table;
|
let top_layer = text_table;
|
||||||
layer_table.push(TableRow::new_from_element(Graphic::Vector(top_layer)));
|
layer_table.push(TableRow::new_from_element(Graphic::Vector(top_layer)));
|
||||||
|
|
||||||
|
// Ports
|
||||||
|
let mut ports_table = Table::new();
|
||||||
|
if let Some(side_input) = &frontend_layer.side_input {
|
||||||
|
let mut port = port_row(&side_input.data_type);
|
||||||
|
port.transform = DAffine2::from_translation(DVec2::new(layer_position.x - 15., layer_position.y + GRID_SIZE - 4.));
|
||||||
|
ports_table.push(port);
|
||||||
|
}
|
||||||
|
let top_port = BezPath::from_svg("M0,6.953l2.521,-1.694a2.649,2.649,0,0,1,2.959,0l2.52,1.694v5.047h-8z").unwrap();
|
||||||
|
let mut vector = Vector::from_bezpath(top_port);
|
||||||
|
vector.style.fill = Fill::Solid(Color::from_rgba8_no_srgb(frontend_layer.output.data_type.data_color()).unwrap());
|
||||||
|
let mut side_port = TableRow::new_from_element(vector);
|
||||||
|
side_port.transform = DAffine2::from_translation(DVec2::new(frontend_layer.position.x as f64 * 24. + GRID_SIZE * 2. - 4., layer_position.y - 12.));
|
||||||
|
side_ports.push(side_port);
|
||||||
|
if frontend_layer.primary_output_connected_to_layer {
|
||||||
|
let top_wire_cap = BezPath::from_svg("M0,-3.5h8v8l-2.521,-1.681a2.666,2.666,0,0,0,-2.959,0l-2.52,1.681z").unwrap();
|
||||||
|
let mut vector = Vector::from_bezpath(top_wire_cap);
|
||||||
|
vector.style.fill = Fill::Solid(Color::from_rgba8_no_srgb(frontend_layer.output.data_type.data_color_dim()).unwrap());
|
||||||
|
let mut vector_row = TableRow::new_from_element(vector);
|
||||||
|
vector_row.transform = DAffine2::from_translation(DVec2::new(frontend_layer.position.x as f64 * 24. + GRID_SIZE * 2. - 4., layer_position.y - 12.));
|
||||||
|
ports_table.push(vector_row);
|
||||||
|
}
|
||||||
|
let bottom_port = BezPath::from_svg("M0,0H8V8L5.479,6.319a2.666,2.666,0,0,0-2.959,0L0,8Z").unwrap();
|
||||||
|
let mut vector = Vector::from_bezpath(bottom_port);
|
||||||
|
vector.style.fill = Fill::Solid(Color::from_rgba8_no_srgb(frontend_layer.bottom_input.data_type.data_color()).unwrap());
|
||||||
|
let mut vector_row = TableRow::new_from_element(vector);
|
||||||
|
vector_row.transform = DAffine2::from_translation(DVec2::new(frontend_layer.position.x as f64 * 24. + GRID_SIZE * 2. - 4., layer_position.y + 2. * GRID_SIZE));
|
||||||
|
ports_table.push(vector_row);
|
||||||
|
if frontend_layer.primary_input_connected_to_layer {
|
||||||
|
let bottom_port_cap = BezPath::from_svg("M0,10.95l2.52,-1.69c0.89,-0.6,2.06,-0.6,2.96,0l2.52,1.69v5.05h-8v-5.05z").unwrap();
|
||||||
|
let mut vector = Vector::from_bezpath(bottom_port_cap);
|
||||||
|
vector.style.fill = Fill::Solid(Color::from_rgba8_no_srgb(frontend_layer.bottom_input.data_type.data_color_dim()).unwrap());
|
||||||
|
let mut vector_row = TableRow::new_from_element(vector);
|
||||||
|
vector_row.transform = DAffine2::from_translation(DVec2::new(frontend_layer.position.x as f64 * 24. + GRID_SIZE * 2. - 4., layer_position.y + 2. * GRID_SIZE));
|
||||||
|
ports_table.push(vector_row);
|
||||||
|
}
|
||||||
|
layer_table.push(TableRow::new_from_element(Graphic::Vector(ports_table)));
|
||||||
|
|
||||||
|
// Eye and grip icon
|
||||||
|
let mut icons_table = Table::new();
|
||||||
|
let icon_svg = if node_to_render.metadata.visible {
|
||||||
|
BezPath::from_svg("M8,3C3,3,0,8,0,8s3,5,8,5s8-5,8-5S13,3,8,3z M8,12c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4S10.2,12,8,12z").unwrap()
|
||||||
|
} else {
|
||||||
|
BezPath::from_svg("M8,4c3.5,0,5.9,2.8,6.8,4c-0.9,1.2-3.3,4-6.8,4S2.1,9.2,1.2,8C2.1,6.8,4.5,4,8,4 M8,3C3,3,0,8,0,8s3,5,8,5s8-5,8-5S13,3,8,3L8,3z").unwrap()
|
||||||
|
};
|
||||||
|
let mut icon_vector = Vector::from_bezpath(icon_svg);
|
||||||
|
icon_vector.style.fill = Fill::Solid(Color::WHITE);
|
||||||
|
let mut icon_row = TableRow::new_from_element(icon_vector);
|
||||||
|
icon_row.transform = DAffine2::from_translation(layer_position + DVec2::new(thumbnail_width + right_layer_width - 8., 16.));
|
||||||
|
icons_table.push(icon_row);
|
||||||
|
|
||||||
|
if node_to_render.metadata.selected {
|
||||||
|
let mut grip_path = BezPath::new();
|
||||||
|
let circle = Circle::new((0.5, 1.5), 0.5);
|
||||||
|
grip_path.extend(circle.to_path(BEZ_PATH_TOLERANCE));
|
||||||
|
let circle = Circle::new((0.5, 4.5), 0.5);
|
||||||
|
grip_path.extend(circle.to_path(BEZ_PATH_TOLERANCE));
|
||||||
|
let circle = Circle::new((0.5, 7.5), 0.5);
|
||||||
|
grip_path.extend(circle.to_path(BEZ_PATH_TOLERANCE));
|
||||||
|
let circle = Circle::new((3.5, 1.5), 0.5);
|
||||||
|
grip_path.extend(circle.to_path(BEZ_PATH_TOLERANCE));
|
||||||
|
let circle = Circle::new((3.5, 4.5), 0.5);
|
||||||
|
grip_path.extend(circle.to_path(BEZ_PATH_TOLERANCE));
|
||||||
|
let circle = Circle::new((3.5, 7.5), 0.5);
|
||||||
|
grip_path.extend(circle.to_path(BEZ_PATH_TOLERANCE));
|
||||||
|
let mut grip_vector = Vector::from_bezpath(grip_path);
|
||||||
|
grip_vector.style.fill = Fill::Solid(Color::from_rgba8_no_srgb(COLOR_E_NEARWHITE).unwrap());
|
||||||
|
let mut grip_row = TableRow::new_from_element(grip_vector);
|
||||||
|
grip_row.transform = DAffine2::from_translation(layer_position + DVec2::new(thumbnail_width + right_layer_width + 6. - GRID_SIZE, 19.5));
|
||||||
|
icons_table.push(grip_row);
|
||||||
|
}
|
||||||
|
layer_table.push(TableRow::new_from_element(Graphic::Vector(icons_table)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layer_table
|
let mut ports_table = Table::new();
|
||||||
|
ports_table.push(TableRow::new_from_element(Graphic::Vector(side_ports)));
|
||||||
|
(layer_table, ports_table)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_first_row(x0: f64, y0: f64, rounded_bottom: bool) -> Vector {
|
fn node_first_row(x0: f64, y0: f64, rounded_bottom: bool) -> Vector {
|
||||||
@@ -352,10 +455,13 @@ fn node_first_row(x0: f64, y0: f64, rounded_bottom: bool) -> Vector {
|
|||||||
vector
|
vector
|
||||||
}
|
}
|
||||||
|
|
||||||
fn port() -> BezPath {
|
fn port_row(data_type: &FrontendGraphDataType) -> TableRow<Vector> {
|
||||||
BezPath::from_svg("M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z").unwrap_or_else(|e| {
|
let path = BezPath::from_svg("M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z").unwrap_or_else(|e| {
|
||||||
panic!("Could not parse port svg from string: {}", e);
|
panic!("Could not parse port svg from string: {}", e);
|
||||||
})
|
});
|
||||||
|
let mut vector = Vector::from_bezpath(path);
|
||||||
|
vector.style.fill = Fill::Solid(Color::from_rgba8_no_srgb(data_type.data_color()).unwrap());
|
||||||
|
TableRow::new_from_element(vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_wires(nodes: &mut Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
pub fn draw_wires(nodes: &mut Vec<FrontendNodeToRender>) -> Table<Graphic> {
|
||||||
|
|||||||
@@ -75,8 +75,10 @@ pub struct FrontendNodeMetadata {
|
|||||||
pub struct FrontendNode {
|
pub struct FrontendNode {
|
||||||
// pub position: FrontendNodePosition,
|
// pub position: FrontendNodePosition,
|
||||||
pub position: FrontendXY,
|
pub position: FrontendXY,
|
||||||
pub inputs: Vec<Option<FrontendGraphInput>>,
|
pub primary_output: Option<FrontendGraphOutput>,
|
||||||
pub outputs: Vec<Option<FrontendGraphOutput>>,
|
pub primary_input: Option<FrontendGraphInput>,
|
||||||
|
pub secondary_inputs: Vec<FrontendGraphInput>,
|
||||||
|
pub secondary_outputs: Vec<FrontendGraphOutput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)]
|
#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||||
|
|||||||
Reference in New Issue
Block a user