Begin transferring network metadata

This commit is contained in:
Adam
2024-09-03 15:45:45 -07:00
parent 91ee7b9ff0
commit bc62fd2dea
16 changed files with 354 additions and 289 deletions
-2
View File
@@ -8,8 +8,6 @@ pub const IMPORTS_TO_LEFT_EDGE_PIXEL_GAP: u32 = 120;
// Viewport // Viewport
pub const VIEWPORT_ZOOM_WHEEL_RATE: f64 = (1. / 600.) * 3.; pub const VIEWPORT_ZOOM_WHEEL_RATE: f64 = (1. / 600.) * 3.;
pub const VIEWPORT_ZOOM_MOUSE_RATE: f64 = 1. / 400.; pub const VIEWPORT_ZOOM_MOUSE_RATE: f64 = 1. / 400.;
pub const VIEWPORT_ZOOM_SCALE_MIN: f64 = 0.000_000_1;
pub const VIEWPORT_ZOOM_SCALE_MAX: f64 = 10_000.;
pub const VIEWPORT_ZOOM_MIN_FRACTION_COVER: f64 = 0.01; pub const VIEWPORT_ZOOM_MIN_FRACTION_COVER: f64 = 0.01;
pub const VIEWPORT_ZOOM_LEVELS: [f64; 74] = [ pub const VIEWPORT_ZOOM_LEVELS: [f64; 74] = [
0.0001, 0.000125, 0.00016, 0.0002, 0.00025, 0.00032, 0.0004, 0.0005, 0.00064, 0.0008, 0.001, 0.0016, 0.002, 0.0025, 0.0032, 0.004, 0.005, 0.0064, 0.008, 0.01, 0.01125, 0.015, 0.02, 0.025, 0.03, 0.0001, 0.000125, 0.00016, 0.0002, 0.00025, 0.00032, 0.0004, 0.0005, 0.00064, 0.0008, 0.001, 0.0016, 0.002, 0.0025, 0.0032, 0.004, 0.005, 0.0064, 0.008, 0.01, 0.01125, 0.015, 0.02, 0.025, 0.03,
@@ -2,7 +2,7 @@ use super::node_graph::utility_types::Transform;
use super::utility_types::clipboards::Clipboard; use super::utility_types::clipboards::Clipboard;
use super::utility_types::error::EditorError; use super::utility_types::error::EditorError;
use super::utility_types::misc::{SnappingOptions, SnappingState, GET_SNAP_BOX_FUNCTIONS, GET_SNAP_GEOMETRY_FUNCTIONS}; use super::utility_types::misc::{SnappingOptions, SnappingState, GET_SNAP_BOX_FUNCTIONS, GET_SNAP_GEOMETRY_FUNCTIONS};
use super::utility_types::network_interface::{NodeNetworkInterface, TransactionStatus}; use super::utility_types::network_interface::{NodeNetworkInterface, NodeNetworkPersistentMetadata, TransactionStatus};
use super::utility_types::nodes::{CollapsedLayers, SelectedNodes}; use super::utility_types::nodes::{CollapsedLayers, SelectedNodes};
use crate::application::{generate_uuid, GRAPHITE_GIT_COMMIT_HASH}; use crate::application::{generate_uuid, GRAPHITE_GIT_COMMIT_HASH};
use crate::consts::{ASYMPTOTIC_EFFECT, DEFAULT_DOCUMENT_NAME, FILE_SAVE_SUFFIX, SCALE_EFFECT, SCROLLBAR_SPACING, VIEWPORT_ROTATE_SNAP_INTERVAL}; use crate::consts::{ASYMPTOTIC_EFFECT, DEFAULT_DOCUMENT_NAME, FILE_SAVE_SUFFIX, SCALE_EFFECT, SCROLLBAR_SPACING, VIEWPORT_ROTATE_SNAP_INTERVAL};
@@ -13,7 +13,7 @@ use crate::messages::portfolio::document::node_graph::NodeGraphHandlerData;
use crate::messages::portfolio::document::overlays::grid_overlays::{grid_overlay, overlay_options}; use crate::messages::portfolio::document::overlays::grid_overlays::{grid_overlay, overlay_options};
use crate::messages::portfolio::document::properties_panel::utility_types::PropertiesPanelMessageHandlerData; use crate::messages::portfolio::document::properties_panel::utility_types::PropertiesPanelMessageHandlerData;
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, DocumentMode, FlipAxis, PTZ}; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, DocumentMode, FlipAxis};
use crate::messages::portfolio::document::utility_types::nodes::RawBuffer; use crate::messages::portfolio::document::utility_types::nodes::RawBuffer;
use crate::messages::portfolio::utility_types::PersistentData; use crate::messages::portfolio::utility_types::PersistentData;
use crate::messages::prelude::*; use crate::messages::prelude::*;
@@ -24,7 +24,7 @@ use crate::messages::tool::utility_types::ToolType;
use crate::node_graph_executor::NodeGraphExecutor; use crate::node_graph_executor::NodeGraphExecutor;
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeNetwork, OldNodeNetwork}; use graph_craft::document::{NodeId, NodeNetwork, OldNodeNetwork, PTZ};
use graphene_core::raster::BlendMode; use graphene_core::raster::BlendMode;
use graphene_core::raster::ImageFrame; use graphene_core::raster::ImageFrame;
use graphene_core::vector::style::ViewMode; use graphene_core::vector::style::ViewMode;
@@ -779,10 +779,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
} }
DocumentMessage::RenderRulers => { DocumentMessage::RenderRulers => {
let current_ptz = if self.graph_view_overlay_open { let current_ptz = if self.graph_view_overlay_open {
let Some(network_metadata) = self.network_interface.network_metadata(&self.breadcrumb_network_path) else { self.network_interface.navigation_metadata(&self.breadcrumb_network_path)
return;
};
&network_metadata.persistent_metadata.navigation_metadata.node_graph_ptz
} else { } else {
&self.document_ptz &self.document_ptz
}; };
@@ -1112,7 +1109,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
let transform = self let transform = self
.navigation_handler .navigation_handler
.calculate_offset_transform(ipp.viewport_bounds.center(), &network_metadata.persistent_metadata.navigation_metadata.node_graph_ptz); .calculate_offset_transform(ipp.viewport_bounds.center(), &self.network_interface.navigation_metadata(&self.breadcrumb_network_path).node_graph_ptz);
self.network_interface.set_transform(transform, &self.breadcrumb_network_path); self.network_interface.set_transform(transform, &self.breadcrumb_network_path);
let imports = self.network_interface.frontend_imports(&self.breadcrumb_network_path).unwrap_or_default(); let imports = self.network_interface.frontend_imports(&self.breadcrumb_network_path).unwrap_or_default();
let exports = self.network_interface.frontend_exports(&self.breadcrumb_network_path).unwrap_or_default(); let exports = self.network_interface.frontend_exports(&self.breadcrumb_network_path).unwrap_or_default();
@@ -1981,5 +1978,6 @@ impl DocumentMessageHandler {
fn default_document_network_interface() -> NodeNetworkInterface { fn default_document_network_interface() -> NodeNetworkInterface {
let mut network_interface = NodeNetworkInterface::default(); let mut network_interface = NodeNetworkInterface::default();
network_interface.add_export(TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY), -1, "".to_string(), &[]); network_interface.add_export(TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY), -1, "".to_string(), &[]);
network_interface.insert_network_metadata(&[], NodeNetworkPersistentMetadata::default());
network_interface network_interface
} }
@@ -1,11 +1,11 @@
use super::transform_utils; use super::transform_utils;
use super::utility_types::ModifyInputsContext; use super::utility_types::ModifyInputsContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeNetworkInterface}; use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use crate::messages::portfolio::document::utility_types::nodes::CollapsedLayers; use crate::messages::portfolio::document::utility_types::nodes::CollapsedLayers;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graph_craft::document::{generate_uuid, NodeId, NodeInput}; use graph_craft::document::{generate_uuid, NodeId, NodeInput, InputConnector};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::text::Font; use graphene_core::text::Font;
use graphene_core::vector::style::{Fill, Gradient, GradientStops, GradientType, LineCap, LineJoin, Stroke}; use graphene_core::vector::style::{Fill, Gradient, GradientStops, GradientType, LineCap, LineJoin, Stroke};
@@ -1,7 +1,7 @@
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeNetworkInterface}; use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput}; use graph_craft::document::{value::TaggedValue, InputConnector, NodeId, NodeInput};
use graphene_core::vector::PointId; use graphene_core::vector::PointId;
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
@@ -1,12 +1,12 @@
use super::transform_utils; use super::transform_utils;
use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type; use crate::messages::portfolio::document::node_graph::document_node_definitions::resolve_document_node_type;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{self, InputConnector, NodeNetworkInterface, OutputConnector}; use crate::messages::portfolio::document::utility_types::network_interface::{self, NodeNetworkInterface};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{generate_uuid, NodeId, NodeInput}; use graph_craft::document::{generate_uuid, InputConnector, NodeId, NodeInput, OutputConnector};
use graphene_core::raster::{BlendMode, ImageFrame}; use graphene_core::raster::{BlendMode, ImageFrame};
use graphene_core::text::Font; use graphene_core::text::Font;
use graphene_core::vector::brush_stroke::BrushStroke; use graphene_core::vector::brush_stroke::BrushStroke;
@@ -1,17 +1,16 @@
use crate::consts::{ use crate::consts::{
VIEWPORT_ROTATE_SNAP_INTERVAL, VIEWPORT_SCROLL_RATE, VIEWPORT_ZOOM_LEVELS, VIEWPORT_ZOOM_MIN_FRACTION_COVER, VIEWPORT_ZOOM_MOUSE_RATE, VIEWPORT_ZOOM_SCALE_MAX, VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ROTATE_SNAP_INTERVAL, VIEWPORT_SCROLL_RATE, VIEWPORT_ZOOM_LEVELS, VIEWPORT_ZOOM_MIN_FRACTION_COVER, VIEWPORT_ZOOM_MOUSE_RATE, VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR,
VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR, VIEWPORT_ZOOM_WHEEL_RATE, VIEWPORT_ZOOM_WHEEL_RATE,
}; };
use crate::messages::frontend::utility_types::MouseCursorIcon; use crate::messages::frontend::utility_types::MouseCursorIcon;
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup, MouseMotion}; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup, MouseMotion};
use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition; use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition;
use crate::messages::portfolio::document::navigation::utility_types::NavigationOperation; use crate::messages::portfolio::document::navigation::utility_types::NavigationOperation;
use crate::messages::portfolio::document::utility_types::misc::PTZ;
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface; use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
use graph_craft::document::NodeId; use graph_craft::document::{NodeId, PTZ};
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
@@ -46,8 +45,7 @@ impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for Navigation
if !graph_view_overlay_open { if !graph_view_overlay_open {
Some(document_ptz) Some(document_ptz)
} else { } else {
let network_metadata = network_interface.network_metadata(breadcrumb_network_path)?; Some(network_interface.navigation_metadata(breadcrumb_network_path).node_graph_ptz)
Some(&network_metadata.persistent_metadata.navigation_metadata.node_graph_ptz)
} }
} }
@@ -249,7 +247,7 @@ impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for Navigation
log::error!("Could not get mutable PTZ in CanvasZoomSet"); log::error!("Could not get mutable PTZ in CanvasZoomSet");
return; return;
}; };
let zoom = zoom_factor.clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX); let zoom = zoom_factor.clamp(graphene_std::consts::VIEWPORT_ZOOM_SCALE_MIN, graphene_std::consts::VIEWPORT_ZOOM_SCALE_MAX);
let zoom = zoom * Self::clamp_zoom(zoom, document_bounds, old_zoom, ipp); let zoom = zoom * Self::clamp_zoom(zoom, document_bounds, old_zoom, ipp);
ptz.set_zoom(zoom); ptz.set_zoom(zoom);
responses.add(PortfolioMessage::UpdateDocumentWidgets); responses.add(PortfolioMessage::UpdateDocumentWidgets);
@@ -1,11 +1,11 @@
use super::utility_types::Direction; use super::utility_types::Direction;
use crate::messages::input_mapper::utility_types::input_keyboard::Key; use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeTemplate, OutputConnector}; use crate::messages::portfolio::document::utility_types::network_interface::NodeTemplate;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{InputConnector, NodeId, NodeInput, OutputConnector};
use graph_craft::proto::GraphErrors; use graph_craft::proto::GraphErrors;
use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypesDelta; use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypesDelta;
@@ -6,12 +6,12 @@ use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::node_graph::document_node_definitions::NodePropertiesContext; use crate::messages::portfolio::document::node_graph::document_node_definitions::NodePropertiesContext;
use crate::messages::portfolio::document::node_graph::utility_types::{ContextMenuData, Direction, FrontendGraphDataType}; use crate::messages::portfolio::document::node_graph::utility_types::{ContextMenuData, Direction, FrontendGraphDataType};
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::{self, InputConnector, NodeNetworkInterface, NodeTemplate, OutputConnector, Previewing}; use crate::messages::portfolio::document::utility_types::network_interface::{self, NodeNetworkInterface, NodeTemplate};
use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, LayerPanelEntry}; use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, LayerPanelEntry};
use crate::messages::prelude::*; use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::auto_panning::AutoPanning; use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput}; use graph_craft::document::{DocumentNodeImplementation, InputConnector, NodeId, NodeInput, OutputConnector, Previewing};
use graph_craft::proto::GraphErrors; use graph_craft::proto::GraphErrors;
use graphene_core::*; use graphene_core::*;
use renderer::{ClickTarget, Quad}; use renderer::{ClickTarget, Quad};
@@ -158,13 +158,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::ShiftNodePosition { node_id, x, y }); responses.add(NodeGraphMessage::ShiftNodePosition { node_id, x, y });
// Only auto connect to the dragged wire if the node is being added to the currently opened network // Only auto connect to the dragged wire if the node is being added to the currently opened network
if let Some(output_connector_position) = self.wire_in_progress_from_connector { if let Some(output_connector_position) = self.wire_in_progress_from_connector {
let Some(network_metadata) = network_interface.network_metadata(selection_network_path) else { let output_connector_position_viewport = network_interface
log::error!("Could not get network metadata in CreateNodeFromContextMenu"); .navigation_metadata(selection_network_path)
return;
};
let output_connector_position_viewport = network_metadata
.persistent_metadata
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.transform_point2(output_connector_position); .transform_point2(output_connector_position);
let Some(output_connector) = &network_interface.output_connector_from_click(output_connector_position_viewport, breadcrumb_network_path) else { let Some(output_connector) = &network_interface.output_connector_from_click(output_connector_position_viewport, breadcrumb_network_path) else {
@@ -339,14 +334,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
log::error!("Selection network path does not match breadcrumb network path in PointerDown"); log::error!("Selection network path does not match breadcrumb network path in PointerDown");
return; return;
} }
let Some(network_metadata) = network_interface.network_metadata(selection_network_path) else {
log::error!("Could not get network metadata in PointerDown");
return;
};
let click = ipp.mouse.position; let click = ipp.mouse.position;
let node_graph_point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click); let node_graph_point = network_interface.navigation_metadata(selection_network_path).node_graph_to_viewport.inverse().transform_point2(click);
if network_interface if network_interface
.layer_click_target_from_click(click, network_interface::LayerClickTargetTypes::Grip, selection_network_path) .layer_click_target_from_click(click, network_interface::LayerClickTargetTypes::Grip, selection_network_path)
@@ -358,7 +349,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let clicked_id = network_interface.node_from_click(click, selection_network_path); let clicked_id = network_interface.node_from_click(click, selection_network_path);
let clicked_input = network_interface.input_connector_from_click(click, selection_network_path); let clicked_input = network_interface.input_connector_from_click(click, selection_network_path);
let clicked_output = network_interface.output_connector_from_click(click, selection_network_path); let clicked_output = network_interface.output_connector_from_click(click, selection_network_path);
let network_metadata = network_interface.network_metadata(selection_network_path).unwrap();
// Create the add node popup on right click, then exit // Create the add node popup on right click, then exit
if right_click { if right_click {
@@ -402,11 +392,11 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let node_graph_shift = if matches!(context_menu_data, ContextMenuData::CreateNode) { let node_graph_shift = if matches!(context_menu_data, ContextMenuData::CreateNode) {
let appear_right_of_mouse = if click.x > ipp.viewport_bounds.size().x - 180. { -180. } else { 0. }; let appear_right_of_mouse = if click.x > ipp.viewport_bounds.size().x - 180. { -180. } else { 0. };
let appear_above_mouse = if click.y > ipp.viewport_bounds.size().y - 200. { -200. } else { 0. }; let appear_above_mouse = if click.y > ipp.viewport_bounds.size().y - 200. { -200. } else { 0. };
DVec2::new(appear_right_of_mouse, appear_above_mouse) / network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.matrix2.x_axis.x DVec2::new(appear_right_of_mouse, appear_above_mouse) / network_interface.navigation_metadata(selection_network_path).node_graph_to_viewport.matrix2.x_axis.x
} else { } else {
let appear_right_of_mouse = if click.x > ipp.viewport_bounds.size().x - 173. { -173. } else { 0. }; let appear_right_of_mouse = if click.x > ipp.viewport_bounds.size().x - 173. { -173. } else { 0. };
let appear_above_mouse = if click.y > ipp.viewport_bounds.size().y - 34. { -34. } else { 0. }; let appear_above_mouse = if click.y > ipp.viewport_bounds.size().y - 34. { -34. } else { 0. };
DVec2::new(appear_right_of_mouse, appear_above_mouse) / network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.matrix2.x_axis.x DVec2::new(appear_right_of_mouse, appear_above_mouse) / network_interface.navigation_metadata(selection_network_path).node_graph_to_viewport.matrix2.x_axis.x
}; };
let context_menu_coordinates = ((node_graph_point.x + node_graph_shift.x) as i32, (node_graph_point.y + node_graph_shift.y) as i32); let context_menu_coordinates = ((node_graph_point.x + node_graph_shift.x) as i32, (node_graph_point.y + node_graph_shift.y) as i32);
@@ -430,9 +420,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
// If the user is clicking on the create nodes list or context menu, break here // If the user is clicking on the create nodes list or context menu, break here
if let Some(context_menu) = &self.context_menu { if let Some(context_menu) = &self.context_menu {
let context_menu_viewport = network_metadata let context_menu_viewport = network_interface
.persistent_metadata .navigation_metadata(selection_network_path)
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.transform_point2(DVec2::new(context_menu.context_menu_coordinates.0 as f64, context_menu.context_menu_coordinates.1 as f64)); .transform_point2(DVec2::new(context_menu.context_menu_coordinates.0 as f64, context_menu.context_menu_coordinates.1 as f64));
let (width, height) = if matches!(context_menu.context_menu_data, ContextMenuData::ToggleLayer { .. }) { let (width, height) = if matches!(context_menu.context_menu_data, ContextMenuData::ToggleLayer { .. }) {
@@ -576,18 +565,14 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
log::error!("Selection network path does not match breadcrumb network path in PointerMove"); log::error!("Selection network path does not match breadcrumb network path in PointerMove");
return; return;
} }
let Some(network_metadata) = network_interface.network_metadata(selection_network_path) else {
return;
};
// Auto-panning // Auto-panning
let messages = [NodeGraphMessage::PointerOutsideViewport { shift }.into(), NodeGraphMessage::PointerMove { shift }.into()]; let messages = [NodeGraphMessage::PointerOutsideViewport { shift }.into(), NodeGraphMessage::PointerMove { shift }.into()];
self.auto_panning.setup_by_mouse_position(ipp, &messages, responses); self.auto_panning.setup_by_mouse_position(ipp, &messages, responses);
let viewport_location = ipp.mouse.position; let viewport_location = ipp.mouse.position;
let point = network_metadata let point = network_interface
.persistent_metadata .navigation_metadata(selection_network_path)
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.inverse() .inverse()
.transform_point2(viewport_location); .transform_point2(viewport_location);
@@ -628,12 +613,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if let (Some(wire_in_progress_from_connector), Some(wire_in_progress_to_connector)) = (self.wire_in_progress_from_connector, self.wire_in_progress_to_connector) { if let (Some(wire_in_progress_from_connector), Some(wire_in_progress_to_connector)) = (self.wire_in_progress_from_connector, self.wire_in_progress_to_connector) {
// If performance is a concern this can be stored as a field in the wire_in_progress_from/to_connector struct, and updated when snapping to an output // If performance is a concern this can be stored as a field in the wire_in_progress_from/to_connector struct, and updated when snapping to an output
let Some(network_metadata) = network_interface.network_metadata(selection_network_path) else { let from_connector_viewport = network_interface
return; .navigation_metadata(selection_network_path)
};
let from_connector_viewport = network_metadata
.persistent_metadata
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.transform_point2(wire_in_progress_from_connector); .transform_point2(wire_in_progress_from_connector);
let from_connector_is_layer = network_interface let from_connector_is_layer = network_interface
@@ -747,10 +728,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
log::error!("Could not get selected nodes in PointerUp"); log::error!("Could not get selected nodes in PointerUp");
return; return;
}; };
let Some(network_metadata) = network_interface.network_metadata(selection_network_path) else {
warn!("No network_metadata");
return;
};
responses.add(DocumentMessage::EndTransaction); responses.add(DocumentMessage::EndTransaction);
@@ -764,16 +741,15 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_selected_nodes }); responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_selected_nodes });
self.deselect_on_pointer_up = None; self.deselect_on_pointer_up = None;
} }
let point = network_metadata let point = network_interface
.persistent_metadata .navigation_metadata(selection_network_path)
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.inverse() .inverse()
.transform_point2(ipp.mouse.position); .transform_point2(ipp.mouse.position);
// Disconnect if the wire was previously connected to an input // Disconnect if the wire was previously connected to an input
if let (Some(wire_in_progress_from_connector), Some(wire_in_progress_to_connector)) = (self.wire_in_progress_from_connector, self.wire_in_progress_to_connector) { if let (Some(wire_in_progress_from_connector), Some(wire_in_progress_to_connector)) = (self.wire_in_progress_from_connector, self.wire_in_progress_to_connector) {
// Check if dragged connector is reconnected to another input // Check if dragged connector is reconnected to another input
let node_graph_to_viewport = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport; let node_graph_to_viewport = network_interface.navigation_metadata(selection_network_path).node_graph_to_viewport;
let from_connector_viewport = node_graph_to_viewport.transform_point2(wire_in_progress_from_connector); let from_connector_viewport = node_graph_to_viewport.transform_point2(wire_in_progress_from_connector);
let to_connector_viewport = node_graph_to_viewport.transform_point2(wire_in_progress_to_connector); let to_connector_viewport = node_graph_to_viewport.transform_point2(wire_in_progress_to_connector);
let output_connector = network_interface.output_connector_from_click(from_connector_viewport, selection_network_path); let output_connector = network_interface.output_connector_from_click(from_connector_viewport, selection_network_path);
@@ -800,7 +776,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let appear_right_of_mouse = if ipp.mouse.position.x > ipp.viewport_bounds.size().x - 173. { -173. } else { 0. }; let appear_right_of_mouse = if ipp.mouse.position.x > ipp.viewport_bounds.size().x - 173. { -173. } else { 0. };
let appear_above_mouse = if ipp.mouse.position.y > ipp.viewport_bounds.size().y - 34. { -34. } else { 0. }; let appear_above_mouse = if ipp.mouse.position.y > ipp.viewport_bounds.size().y - 34. { -34. } else { 0. };
let node_graph_shift = DVec2::new(appear_right_of_mouse, appear_above_mouse) / network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.matrix2.x_axis.x; let node_graph_shift =
DVec2::new(appear_right_of_mouse, appear_above_mouse) / network_interface.navigation_metadata(selection_network_path).node_graph_to_viewport.matrix2.x_axis.x;
self.context_menu = Some(ContextMenuInformation { self.context_menu = Some(ContextMenuInformation {
context_menu_coordinates: ((point.x + node_graph_shift.x) as i32, (point.y + node_graph_shift.y) as i32), context_menu_coordinates: ((point.x + node_graph_shift.x) as i32, (point.y + node_graph_shift.y) as i32),
@@ -1283,7 +1260,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
return; return;
}; };
let box_selection_start_viewport = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.transform_point2(box_selection_start); let box_selection_start_viewport = network_interface
.navigation_metadata(selection_network_path)
.node_graph_to_viewport
.transform_point2(box_selection_start);
let box_selection = Some(BoxSelection { let box_selection = Some(BoxSelection {
start_x: box_selection_start_viewport.x.max(0.) as u32, start_x: box_selection_start_viewport.x.max(0.) as u32,
@@ -1291,9 +1271,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
end_x: ipp.mouse.position.x.max(0.) as u32, end_x: ipp.mouse.position.x.max(0.) as u32,
end_y: ipp.mouse.position.y.max(0.) as u32, end_y: ipp.mouse.position.y.max(0.) as u32,
}); });
let box_selection_end_graph = network_metadata let box_selection_end_graph = network_interface
.persistent_metadata .navigation_metadata(selection_network_path)
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.inverse() .inverse()
.transform_point2(ipp.mouse.position); .transform_point2(ipp.mouse.position);
@@ -1,9 +1,7 @@
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::NodeId; use graph_craft::document::{NodeId, InputConnector, OutputConnector};
use graphene_core::Type; use graphene_core::Type;
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, OutputConnector};
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, specta::Type)] #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum FrontendGraphDataType { pub enum FrontendGraphDataType {
#[default] #[default]
@@ -1,5 +1,6 @@
use crate::consts::COLOR_OVERLAY_GRAY; use crate::consts::COLOR_OVERLAY_GRAY;
use graph_craft::document::PTZ;
use graphene_core::raster::Color; use graphene_core::raster::Color;
use glam::DVec2; use glam::DVec2;
@@ -440,27 +441,3 @@ impl fmt::Display for SnappingOptions {
} }
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(default)]
pub struct PTZ {
pub pan: DVec2,
pub tilt: f64,
zoom: f64,
}
impl Default for PTZ {
fn default() -> Self {
Self { pan: DVec2::ZERO, tilt: 0., zoom: 1. }
}
}
impl PTZ {
pub fn zoom(&self) -> f64 {
self.zoom
}
pub fn set_zoom(&mut self, zoom: f64) {
self.zoom = zoom.clamp(crate::consts::VIEWPORT_ZOOM_SCALE_MIN, crate::consts::VIEWPORT_ZOOM_SCALE_MAX)
}
}
@@ -1,5 +1,4 @@
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier, NodeRelations}; use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier, NodeRelations};
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::{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::graph_operation::utility_types::ModifyInputsContext;
@@ -8,6 +7,7 @@ use crate::messages::tool::common_functionality::graph_modification_utils;
use bezier_rs::Subpath; use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, OldDocumentNodeImplementation, OldNodeNetwork}; use graph_craft::document::{value::TaggedValue, DocumentNode, DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork, OldDocumentNodeImplementation, OldNodeNetwork};
use graph_craft::document::{InputConnector, NavigationMetadata, OutputConnector, Previewing, RootNode, PTZ};
use graph_craft::{concrete, Type}; use graph_craft::{concrete, Type};
use graphene_std::renderer::{ClickTarget, Quad}; use graphene_std::renderer::{ClickTarget, Quad};
use graphene_std::vector::{PointId, VectorData, VectorModificationType}; use graphene_std::vector::{PointId, VectorData, VectorModificationType};
@@ -998,12 +998,16 @@ impl NodeNetworkInterface {
upstream_nodes_below_layer upstream_nodes_below_layer
} }
pub fn previewing(&self, network_path: &[NodeId]) -> Previewing { pub fn previewing(&self, network_path: &[NodeId]) -> Option<&Previewing> {
let Some(network_metadata) = self.network_metadata(network_path) else { let Some(tagged_value) = self.metadata_value(&network_path, Metadata::Previewing) else {
log::error!("Could not get nested network_metadata in previewing"); log::error!("Could not get tagged value in previewing");
return Previewing::No; return None;
}; };
network_metadata.persistent_metadata.previewing let TaggedValue::Previewing(previewing) = tagged_value else {
log::error!("Tagged value should be Previewing in previewing");
return None;
};
Some(previewing)
} }
/// Returns the root node (the node that the solid line is connect to), or None if no nodes are connected to the output /// Returns the root node (the node that the solid line is connect to), or None if no nodes are connected to the output
@@ -1012,11 +1016,8 @@ impl NodeNetworkInterface {
log::error!("Could not get network in root_node"); log::error!("Could not get network in root_node");
return None; return None;
}; };
let Some(network_metadata) = self.network_metadata(network_path) else { let previewing = self.previewing(network_path);
log::error!("Could not get nested network_metadata in root_node"); match &previewing {
return None;
};
match &network_metadata.persistent_metadata.previewing {
Previewing::Yes { root_node_to_restore } => *root_node_to_restore, Previewing::Yes { root_node_to_restore } => *root_node_to_restore,
Previewing::No => network.exports.first().and_then(|export| { Previewing::No => network.exports.first().and_then(|export| {
if let NodeInput::Node { node_id, output_index, .. } = export { if let NodeInput::Node { node_id, output_index, .. } = export {
@@ -1031,23 +1032,35 @@ impl NodeNetworkInterface {
} }
} }
pub fn navigation_metadata(&self, network_path: &[NodeId]) -> Option<&NavigationMetadata> {
let Some(tagged_value) = self.metadata_value(&network_path, Metadata::NavigationMetadata) else {
log::error!("Could not get tagged value in navigation_metadata");
return None;
};
let TaggedValue::NavigationMetadata(navigation_metadata) = tagged_value else {
log::error!("Tagged value should be Previewing in previewing");
return None;
};
Some(navigation_metadata)
}
pub fn reference(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<String> { pub fn reference(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<String> {
self.node_metadata(node_id, network_path) self.node_metadata(node_id, network_path)
.and_then(|node_metadata| node_metadata.persistent_metadata.reference.as_ref().map(|reference| reference.to_string())) .and_then(|node_metadata| node_metadata.persistent_metadata.reference.as_ref().map(|reference| reference.to_string()))
} }
pub fn display_name(&self, node_id: &NodeId, network_path: &[NodeId]) -> String { pub fn display_name(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<&String> {
let mut node_id_path = network_path.to_vec(); let mut node_id_path = network_path.to_vec();
node_id_path.push(*node_id); node_id_path.push(*node_id);
let Some(tagged_value, ..) = self.metadata_value(&node_id_path, Metadata::DisplayName) else { let Some(tagged_value) = self.metadata_value(&node_id_path, Metadata::DisplayName) else {
log::error!("Could not get tagged value in display_name"); log::error!("Could not get tagged value in display_name");
return "".to_string(); return None;
}; };
let TaggedValue::String(display_name) = tagged_value else { let TaggedValue::String(display_name) = tagged_value else {
log::error!("Tagged value should be String in display_name"); log::error!("Tagged value should be String in display_name");
return "".to_string(); return None;
}; };
display_name.clone() Some(display_name)
} }
pub fn frontend_display_name(&self, node_id: &NodeId, network_path: &[NodeId]) -> String { pub fn frontend_display_name(&self, node_id: &NodeId, network_path: &[NodeId]) -> String {
@@ -1842,9 +1855,8 @@ impl NodeNetworkInterface {
let mut import_export_ports = Ports::new(); let mut import_export_ports = Ports::new();
let viewport_top_right = network_metadata let viewport_top_right = self
.persistent_metadata .navigation_metadata(network_path)
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.inverse() .inverse()
.transform_point2(rounded_network_edge_distance.exports_to_edge_distance); .transform_point2(rounded_network_edge_distance.exports_to_edge_distance);
@@ -1864,9 +1876,8 @@ impl NodeNetworkInterface {
import_export_ports.insert_input_port_at_center(input_index, export_top_right + DVec2::new(0., input_index as f64 * 24.)); import_export_ports.insert_input_port_at_center(input_index, export_top_right + DVec2::new(0., input_index as f64 * 24.));
} }
let viewport_top_left = network_metadata let viewport_top_left = self
.persistent_metadata .navigation_metadata(network_path)
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.inverse() .inverse()
.transform_point2(rounded_network_edge_distance.imports_to_edge_distance); .transform_point2(rounded_network_edge_distance.imports_to_edge_distance);
@@ -2541,15 +2552,13 @@ impl NodeNetworkInterface {
let import_exports_viewport_top_left = rounded_network_edge_distance.imports_to_edge_distance; 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 import_exports_viewport_bottom_right = rounded_network_edge_distance.exports_to_edge_distance;
let node_graph_top_left = network_metadata let node_graph_top_left = self
.persistent_metadata .navigation_metadata(network_path)
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.inverse() .inverse()
.transform_point2(import_exports_viewport_top_left); .transform_point2(import_exports_viewport_top_left);
let node_graph_bottom_right = network_metadata let node_graph_bottom_right = self
.persistent_metadata .navigation_metadata(network_path)
.navigation_metadata
.node_graph_to_viewport .node_graph_to_viewport
.inverse() .inverse()
.transform_point2(import_exports_viewport_bottom_right); .transform_point2(import_exports_viewport_bottom_right);
@@ -2597,22 +2606,18 @@ impl NodeNetworkInterface {
log::error!("Could not get nested network_metadata in node_graph_ptz_mut"); log::error!("Could not get nested network_metadata in node_graph_ptz_mut");
return None; return None;
}; };
Some(&mut network_metadata.persistent_metadata.navigation_metadata.node_graph_ptz) Some(&mut self.navigation_metadata(network_path).node_graph_ptz)
} }
// TODO: Optimize getting click target intersections from click by using a spacial data structure like a quadtree instead of linear search // TODO: Optimize getting click target intersections from click by using a spacial data structure like a quadtree instead of linear search
/// Click target getter methods /// Click target getter methods
pub fn node_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<NodeId> { pub fn node_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<NodeId> {
let Some(network_metadata) = self.network_metadata(network_path) else {
log::error!("Could not get nested network_metadata in node_from_click");
return None;
};
let Some(network) = self.network(network_path) else { let Some(network) = self.network(network_path) else {
log::error!("Could not get nested network in node_from_click"); log::error!("Could not get nested network in node_from_click");
return None; return None;
}; };
let point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click); let point = self.navigation_metadata(network_path).node_graph_to_viewport.inverse().transform_point2(click);
let nodes = network.nodes.keys().copied().collect::<Vec<_>>(); let nodes = network.nodes.keys().copied().collect::<Vec<_>>();
let clicked_nodes = nodes let clicked_nodes = nodes
.iter() .iter()
@@ -2649,7 +2654,7 @@ impl NodeNetworkInterface {
return None; return None;
}; };
let point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click); let point = self.navigation_metadata(network_path).node_graph_to_viewport.inverse().transform_point2(click);
let node_ids: Vec<_> = network.nodes.keys().copied().collect(); let node_ids: Vec<_> = network.nodes.keys().copied().collect();
node_ids node_ids
@@ -2670,16 +2675,12 @@ impl NodeNetworkInterface {
} }
pub fn input_connector_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<InputConnector> { pub fn input_connector_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<InputConnector> {
let Some(network_metadata) = self.network_metadata(network_path) else {
log::error!("Could not get nested network_metadata in input_connector_from_click");
return None;
};
let Some(network) = self.network(network_path) else { let Some(network) = self.network(network_path) else {
log::error!("Could not get nested network in input_connector_from_click"); log::error!("Could not get nested network in input_connector_from_click");
return None; return None;
}; };
let point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click); let point = self.navigation_metadata(network_path).node_graph_to_viewport.inverse().transform_point2(click);
network network
.nodes .nodes
.keys() .keys()
@@ -2703,16 +2704,12 @@ impl NodeNetworkInterface {
} }
pub fn output_connector_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<OutputConnector> { pub fn output_connector_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<OutputConnector> {
let Some(network_metadata) = self.network_metadata(network_path) else {
log::error!("Could not get nested network_metadata in output_connector_from_click");
return None;
};
let Some(network) = self.network(network_path) else { let Some(network) = self.network(network_path) else {
log::error!("Could not get nested network in output_connector_from_click"); log::error!("Could not get nested network in output_connector_from_click");
return None; return None;
}; };
let point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click); let point = self.navigation_metadata(network_path).node_graph_to_viewport.inverse().transform_point2(click);
let nodes = network.nodes.keys().copied().collect::<Vec<_>>(); let nodes = network.nodes.keys().copied().collect::<Vec<_>>();
nodes nodes
.iter() .iter()
@@ -2773,15 +2770,11 @@ impl NodeNetworkInterface {
/// Get the combined bounding box of the click targets of the selected nodes in the node graph in viewport space /// Get the combined bounding box of the click targets of the selected nodes in the node graph in viewport space
pub fn selected_nodes_bounding_box_viewport(&mut self, network_path: &[NodeId]) -> Option<[DVec2; 2]> { pub fn selected_nodes_bounding_box_viewport(&mut self, network_path: &[NodeId]) -> Option<[DVec2; 2]> {
// Always get the bounding box for nodes in the currently viewed network // Always get the bounding box for nodes in the currently viewed network
let Some(network_metadata) = self.network_metadata(network_path) else {
log::error!("Could not get nested network_metadata in selected_nodes_bounding_box_viewport");
return None;
};
let Some(selected_nodes) = self.selected_nodes(network_path) else { let Some(selected_nodes) = self.selected_nodes(network_path) else {
log::error!("Could not get selected nodes in selected_nodes_bounding_box_viewport"); log::error!("Could not get selected nodes in selected_nodes_bounding_box_viewport");
return None; return None;
}; };
let node_graph_to_viewport = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport; let node_graph_to_viewport = self.navigation_metadata(network_path).node_graph_to_viewport;
selected_nodes selected_nodes
.selected_nodes() .selected_nodes()
.cloned() .cloned()
@@ -2797,13 +2790,8 @@ impl NodeNetworkInterface {
/// Gets the bounding box in viewport coordinates for each node in the node graph /// Gets the bounding box in viewport coordinates for each node in the node graph
pub fn graph_bounds_viewport_space(&mut self, network_path: &[NodeId]) -> Option<[DVec2; 2]> { pub fn graph_bounds_viewport_space(&mut self, network_path: &[NodeId]) -> Option<[DVec2; 2]> {
let bounds = *self.all_nodes_bounding_box(network_path)?; let bounds = *self.all_nodes_bounding_box(network_path)?;
let Some(network_metadata) = self.network_metadata(network_path) else {
log::error!("Could not get nested network_metadata in graph_bounds_viewport_space");
return None;
};
let bounding_box_subpath = bezier_rs::Subpath::<PointId>::new_rect(bounds[0], bounds[1]); let bounding_box_subpath = bezier_rs::Subpath::<PointId>::new_rect(bounds[0], bounds[1]);
bounding_box_subpath.bounding_box_with_transform(network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport) bounding_box_subpath.bounding_box_with_transform(self.navigation_metadata(network_path).node_graph_to_viewport)
} }
pub fn collect_layer_widths(&mut self, network_path: &[NodeId]) -> (HashMap<NodeId, u32>, HashMap<NodeId, u32>) { pub fn collect_layer_widths(&mut self, network_path: &[NodeId]) -> (HashMap<NodeId, u32>, HashMap<NodeId, u32>) {
@@ -2943,27 +2931,26 @@ impl NodeNetworkInterface {
pub fn copy_all_navigation_metadata(&mut self, other_interface: &NodeNetworkInterface) { pub fn copy_all_navigation_metadata(&mut self, other_interface: &NodeNetworkInterface) {
let mut stack = vec![vec![]]; let mut stack = vec![vec![]];
while let Some(path) = stack.pop() { while let Some(path) = stack.pop() {
let Some(self_network_metadata) = self.network_metadata_mut(&path) else { let Some(self_network_metadata) = self.network_metadata(&path) else {
continue; continue;
}; };
if let Some(other_network_metadata) = other_interface.network_metadata(&path) {
self_network_metadata.persistent_metadata.navigation_metadata = other_network_metadata.persistent_metadata.navigation_metadata.clone();
}
stack.extend(self_network_metadata.persistent_metadata.node_metadata.keys().map(|node_id| { stack.extend(self_network_metadata.persistent_metadata.node_metadata.keys().map(|node_id| {
let mut current_path = path.clone(); let mut current_path = path.clone();
current_path.push(*node_id); current_path.push(*node_id);
current_path current_path
})); }));
if let Some(other_network_metadata) = other_interface.network_metadata(&path) {
let Some(navigation_metadata) = self.navigation_metadata_mut(&path) else {
log::error!("Could not get nested navigation_metadata in copy_all_navigation_metadata");
continue;
};
*navigation_metadata = other_network_metadata.persistent_metadata.navigation_metadata.clone();
};
} }
} }
pub fn set_transform(&mut self, transform: DAffine2, network_path: &[NodeId]) { pub fn set_transform(&mut self, transform: DAffine2, network_path: &[NodeId]) {
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.navigation_metadata(network_path).node_graph_to_viewport = transform;
log::error!("Could not get nested network in set_transform");
return;
};
network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport = transform;
self.unload_import_export_ports(network_path); self.unload_import_export_ports(network_path);
} }
@@ -3468,8 +3455,27 @@ impl NodeNetworkInterface {
node_path.push(node_id); node_path.push(node_id);
let display_name_node_id = Self::metadata_node_id(&node_path, Metadata::DisplayName); let display_name_node_id = Self::metadata_node_id(&node_path, Metadata::DisplayName);
self.insert_node_metadata(display_name_node_id, TaggedValue::String(persistent_metadata.display_name)); self.insert_node_metadata(display_name_node_id, TaggedValue::String(persistent_metadata.display_name));
// TODO: Add the rest of the node metadata nodes
if let Some(nested_network) = persistent_metadata.network_metadata {
self.insert_network_metadata(&node_path, nested_network.persistent_metadata);
}
} }
/// Adds nodes for the network metadata. Should always be called when creating a new NodeNetwork
pub fn insert_network_metadata(&mut self, network_path: &[NodeId], persistent_metadata: NodeNetworkPersistentMetadata) {
let previewing_node_id = Self::metadata_node_id(network_path, Metadata::Previewing);
let navigation_metadata_id = Self::metadata_node_id(network_path, Metadata::NavigationMetadata);
self.insert_node_metadata(previewing_node_id, TaggedValue::Previewing(persistent_metadata.previewing));
self.insert_node_metadata(navigation_metadata_id, TaggedValue::NavigationMetadata(persistent_metadata.navigation_metadata));
// TODO: Add the rest of the network metadata nodes
for (node_id, node_metadata) in persistent_metadata.node_metadata {
self.insert_all_node_metadata(node_id, network_path, node_metadata.persistent_metadata);
}
}
/// Adds a node for the metadata. TODO: Consider calling this if a metadata node cannot be found.
fn insert_node_metadata(&mut self, metadata_node_id: NodeId, tagged_value: TaggedValue) { fn insert_node_metadata(&mut self, metadata_node_id: NodeId, tagged_value: TaggedValue) {
let network = self.network_mut(&[]).unwrap(); let network = self.network_mut(&[]).unwrap();
log::debug!("Inserting metadata node with id {metadata_node_id}"); log::debug!("Inserting metadata node with id {metadata_node_id}");
@@ -3667,15 +3673,11 @@ impl NodeNetworkInterface {
pub fn start_previewing_without_restore(&mut self, network_path: &[NodeId]) { pub fn start_previewing_without_restore(&mut self, network_path: &[NodeId]) {
// Some logic will have to be performed to prevent the graph positions from being completely changed when the export changes to some previewed node // Some logic will have to be performed to prevent the graph positions from being completely changed when the export changes to some previewed node
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_previewing(network_path, Previewing::Yes { root_node_to_restore: None });
log::error!("Could not get nested network_metadata in start_previewing_without_restore");
return;
};
network_metadata.persistent_metadata.previewing = Previewing::Yes { root_node_to_restore: None };
} }
fn stop_previewing(&mut self, network_path: &[NodeId]) { fn stop_previewing(&mut self, network_path: &[NodeId]) {
if let Previewing::Yes { if let Some(Previewing::Yes) {
root_node_to_restore: Some(root_node_to_restore), root_node_to_restore: Some(root_node_to_restore),
} = self.previewing(network_path) } = self.previewing(network_path)
{ {
@@ -3685,11 +3687,57 @@ impl NodeNetworkInterface {
network_path, network_path,
); );
} }
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_previewing(network_path, Previewing::No);
log::error!("Could not get nested network_metadata in stop_previewing"); }
fn set_previewing(&mut self, network_path: &[NodeId], previewing: Previewing) {
let network = self.network_mut(&[]).unwrap();
let previewing_node_id = Self::metadata_node_id(&network_path, Metadata::Previewing);
let Some(previewing_node) = network.nodes.get_mut(&previewing_node_id) else {
log::error!("Could not get display name node with id {previewing_node_id} in set_previewing");
return; return;
}; };
network_metadata.persistent_metadata.previewing = Previewing::No;
let Some(previewing_input) = previewing_node.inputs.get_mut(0) else {
log::error!("Could not get display name input in set_previewing");
return;
};
let Some(TaggedValue::Previewing(current_previewing)) = previewing_input.as_value() else {
log::error!("Could not get current display name in set_previewing");
return;
};
if *current_previewing == previewing {
return;
}
*previewing_input = NodeInput::value(TaggedValue::Previewing(previewing), false);
}
fn navigation_metadata_mut(&mut self, network_path: &[NodeId]) -> Option<&mut NavigationMetadata> {
let network = self.network_mut(&[]).unwrap();
let navigation_metadata_id = Self::metadata_node_id(&network_path, Metadata::NavigationMetadata);
let Some(navigation_metadata_node) = network.nodes.get_mut(&navigation_metadata_id) else {
log::error!("Could not get navigation metadata node with id {navigation_metadata_id} in set_navigation_metadata");
return None;
};
let Some(navigation_metadata_input) = navigation_metadata_node.inputs.get_mut(0) else {
log::error!("Could not get navigation metadata input in set_navigation_metadata");
return None;
};
let Some(TaggedValue::NavigationMetadata(current_navigation_metadata)) = navigation_metadata_input.as_value_mut().as_deref_mut() else {
log::error!("Could not get current navigation metadata in set_navigation_metadata");
return None;
};
Some(current_navigation_metadata)
} }
/// Sets the root node only if a node is being previewed /// Sets the root node only if a node is being previewed
@@ -3709,7 +3757,7 @@ impl NodeNetworkInterface {
// } // }
pub fn set_display_name(&mut self, node_id: &NodeId, display_name: String, network_path: &[NodeId]) { pub fn set_display_name(&mut self, node_id: &NodeId, display_name: String, network_path: &[NodeId]) {
let network = self.network_mut(network_path).unwrap(); let network = self.network_mut(&[]).unwrap();
let mut node_path = network_path.to_vec(); let mut node_path = network_path.to_vec();
node_path.push(*node_id); node_path.push(*node_id);
@@ -3911,7 +3959,7 @@ impl NodeNetworkInterface {
// The export is clicked // The export is clicked
if *node_id == toggle_id { if *node_id == toggle_id {
// If the current export is clicked and is being previewed end the preview and set either export back to root node or disconnect // If the current export is clicked and is being previewed end the preview and set either export back to root node or disconnect
if let Previewing::Yes { root_node_to_restore } = self.previewing(network_path) { if let Some(Previewing::Yes { root_node_to_restore }) = self.previewing(network_path) {
new_export = root_node_to_restore.map(|root_node| root_node.to_connector()); new_export = root_node_to_restore.map(|root_node| root_node.to_connector());
new_previewing_state = Previewing::No; new_previewing_state = Previewing::No;
} }
@@ -3930,7 +3978,7 @@ impl NodeNetworkInterface {
new_export = Some(OutputConnector::node(toggle_id, 0)); new_export = Some(OutputConnector::node(toggle_id, 0));
// There is currently a dashed line being drawn // There is currently a dashed line being drawn
if let Previewing::Yes { root_node_to_restore } = self.previewing(network_path) { if let Some(Previewing::Yes { root_node_to_restore }) = self.previewing(network_path) {
// There is also a solid line being drawn // There is also a solid line being drawn
if let Some(root_node_to_restore) = root_node_to_restore { if let Some(root_node_to_restore) = root_node_to_restore {
// If the node with the solid line is clicked, then start previewing that node without restore // If the node with the solid line is clicked, then start previewing that node without restore
@@ -3940,7 +3988,7 @@ impl NodeNetworkInterface {
} else { } else {
// Root node to restore does not change // Root node to restore does not change
new_previewing_state = Previewing::Yes { new_previewing_state = Previewing::Yes {
root_node_to_restore: Some(root_node_to_restore), root_node_to_restore: Some(*root_node_to_restore),
}; };
} }
} }
@@ -3976,10 +4024,7 @@ impl NodeNetworkInterface {
self.disconnect_input(&InputConnector::Export(0), network_path); self.disconnect_input(&InputConnector::Export(0), network_path);
} }
} }
let Some(network_metadata) = self.network_metadata_mut(network_path) else { self.set_previewing(network_path, new_previewing_state);
return;
};
network_metadata.persistent_metadata.previewing = new_previewing_state;
} }
/// Sets the position of a node to an absolute position /// Sets the position of a node to an absolute position
@@ -4932,86 +4977,6 @@ impl<'a> Iterator for FlowIter<'a> {
} }
} }
/// Represents an input connector with index based on the [`DocumentNode::inputs`] index, not the visible input index
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum InputConnector {
#[serde(rename = "node")]
Node {
#[serde(rename = "nodeId")]
node_id: NodeId,
#[serde(rename = "inputIndex")]
input_index: usize,
},
#[serde(rename = "export")]
Export(usize),
}
impl Default for InputConnector {
fn default() -> Self {
InputConnector::Export(0)
}
}
impl InputConnector {
pub fn node(node_id: NodeId, input_index: usize) -> Self {
InputConnector::Node { node_id, input_index }
}
pub fn input_index(&self) -> usize {
match self {
InputConnector::Node { input_index, .. } => *input_index,
InputConnector::Export(input_index) => *input_index,
}
}
pub fn node_id(&self) -> Option<NodeId> {
match self {
InputConnector::Node { node_id, .. } => Some(*node_id),
_ => None,
}
}
}
/// Represents an output connector
#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum OutputConnector {
#[serde(rename = "node")]
Node {
#[serde(rename = "nodeId")]
node_id: NodeId,
#[serde(rename = "outputIndex")]
output_index: usize,
},
#[serde(rename = "import")]
Import(usize),
}
impl Default for OutputConnector {
fn default() -> Self {
OutputConnector::Import(0)
}
}
impl OutputConnector {
pub fn node(node_id: NodeId, output_index: usize) -> Self {
OutputConnector::Node { node_id, output_index }
}
pub fn index(&self) -> usize {
match self {
OutputConnector::Node { output_index, .. } => *output_index,
OutputConnector::Import(output_index) => *output_index,
}
}
pub fn node_id(&self) -> Option<NodeId> {
match self {
OutputConnector::Node { node_id, .. } => Some(*node_id),
_ => None,
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Ports { pub struct Ports {
input_ports: Vec<(usize, ClickTarget)>, input_ports: Vec<(usize, ClickTarget)>,
@@ -5097,30 +5062,6 @@ impl Ports {
} }
} }
#[derive(PartialEq, Debug, Clone, Copy, Hash, Default, serde::Serialize, serde::Deserialize)]
pub struct RootNode {
pub node_id: NodeId,
pub output_index: usize,
}
impl RootNode {
pub fn to_connector(&self) -> OutputConnector {
OutputConnector::Node {
node_id: self.node_id,
output_index: self.output_index,
}
}
}
#[derive(PartialEq, Debug, Clone, Copy, Hash, Default, serde::Serialize, serde::Deserialize)]
pub enum Previewing {
/// If there is a node to restore the connection to the export for, then it is stored in the option.
/// Otherwise, nothing gets restored and the primary export is disconnected.
Yes { root_node_to_restore: Option<RootNode> },
#[default]
No,
}
/// All fields in NetworkMetadata should automatically be updated by using the network interface API. If a field is none then it should be calculated based on the network state. /// All fields in NetworkMetadata should automatically be updated by using the network interface API. If a field is none then it should be calculated based on the network state.
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)] #[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct NodeNetworkMetadata { pub struct NodeNetworkMetadata {
@@ -1,5 +1,5 @@
use super::document::utility_types::document_metadata::LayerNodeIdentifier; use super::document::utility_types::document_metadata::LayerNodeIdentifier;
use super::document::utility_types::network_interface::{self, InputConnector, OutputConnector}; use super::document::utility_types::network_interface;
use super::utility_types::{PanelType, PersistentData}; use super::utility_types::{PanelType, PersistentData};
use crate::application::generate_uuid; use crate::application::generate_uuid;
use crate::consts::DEFAULT_DOCUMENT_NAME; use crate::consts::DEFAULT_DOCUMENT_NAME;
@@ -13,7 +13,7 @@ use crate::messages::tool::utility_types::{HintData, HintGroup};
use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor}; use crate::node_graph_executor::{ExportConfig, NodeGraphExecutor};
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{InputConnector, NodeId, NodeInput, OutputConnector};
use graphene_core::text::Font; use graphene_core::text::Font;
use graphene_std::vector::style::{Fill, FillType, Gradient}; use graphene_std::vector::style::{Fill, FillType, Gradient};
use interpreted_executor::dynamic_executor::IntrospectError; use interpreted_executor::dynamic_executor::IntrospectError;
@@ -5,12 +5,11 @@ use crate::application::generate_uuid;
use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn; use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::InputConnector;
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils::{self, is_layer_fed_by_node_of_name}; use crate::messages::tool::common_functionality::graph_modification_utils::{self, is_layer_fed_by_node_of_name};
use graph_craft::document::value::TaggedValue; use graph_craft::document::value::TaggedValue;
use graph_craft::document::{NodeId, NodeInput}; use graph_craft::document::{InputConnector, NodeId, NodeInput};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::text::{load_face, Font, FontCache}; use graphene_core::text::{load_face, Font, FontCache};
use graphene_core::vector::style::Fill; use graphene_core::vector::style::Fill;
+4
View File
@@ -7,3 +7,7 @@ pub const LAYER_OUTLINE_STROKE_WEIGHT: f64 = 1.;
// Fonts // Fonts
pub const DEFAULT_FONT_FAMILY: &str = "Cabin"; pub const DEFAULT_FONT_FAMILY: &str = "Cabin";
pub const DEFAULT_FONT_STYLE: &str = "Normal (400)"; pub const DEFAULT_FONT_STYLE: &str = "Normal (400)";
// Zoom
pub const VIEWPORT_ZOOM_SCALE_MIN: f64 = 0.000_000_1;
pub const VIEWPORT_ZOOM_SCALE_MAX: f64 = 10_000.;
+157 -1
View File
@@ -6,7 +6,7 @@ use graphene_core::memo::MemoHashGuard;
pub use graphene_core::uuid::generate_uuid; pub use graphene_core::uuid::generate_uuid;
use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type}; use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type};
use glam::IVec2; use glam::{DAffine2, DVec2, IVec2};
use log::Metadata; use log::Metadata;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
@@ -1356,6 +1356,162 @@ impl<'a> Iterator for RecursiveNodeIter<'a> {
} }
} }
#[derive(PartialEq, Debug, Clone, Copy, Hash, Default, serde::Serialize, serde::Deserialize, DynAny)]
pub enum Previewing {
/// If there is a node to restore the connection to the export for, then it is stored in the option.
/// Otherwise, nothing gets restored and the primary export is disconnected.
Yes { root_node_to_restore: Option<RootNode> },
#[default]
No,
}
#[derive(PartialEq, Debug, Clone, Copy, Hash, Default, serde::Serialize, serde::Deserialize, DynAny)]
pub struct RootNode {
pub node_id: NodeId,
pub output_index: usize,
}
impl RootNode {
pub fn to_connector(&self) -> OutputConnector {
OutputConnector::Node {
node_id: self.node_id,
output_index: self.output_index,
}
}
}
/// Represents an input connector with index based on the [`DocumentNode::inputs`] index, not the visible input index
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum InputConnector {
#[serde(rename = "node")]
Node {
#[serde(rename = "nodeId")]
node_id: NodeId,
#[serde(rename = "inputIndex")]
input_index: usize,
},
#[serde(rename = "export")]
Export(usize),
}
impl Default for InputConnector {
fn default() -> Self {
InputConnector::Export(0)
}
}
impl InputConnector {
pub fn node(node_id: NodeId, input_index: usize) -> Self {
InputConnector::Node { node_id, input_index }
}
pub fn input_index(&self) -> usize {
match self {
InputConnector::Node { input_index, .. } => *input_index,
InputConnector::Export(input_index) => *input_index,
}
}
pub fn node_id(&self) -> Option<NodeId> {
match self {
InputConnector::Node { node_id, .. } => Some(*node_id),
_ => None,
}
}
}
/// Represents an output connector
#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum OutputConnector {
#[serde(rename = "node")]
Node {
#[serde(rename = "nodeId")]
node_id: NodeId,
#[serde(rename = "outputIndex")]
output_index: usize,
},
#[serde(rename = "import")]
Import(usize),
}
impl Default for OutputConnector {
fn default() -> Self {
OutputConnector::Import(0)
}
}
impl OutputConnector {
pub fn node(node_id: NodeId, output_index: usize) -> Self {
OutputConnector::Node { node_id, output_index }
}
pub fn index(&self) -> usize {
match self {
OutputConnector::Node { output_index, .. } => *output_index,
OutputConnector::Import(output_index) => *output_index,
}
}
pub fn node_id(&self) -> Option<NodeId> {
match self {
OutputConnector::Node { node_id, .. } => Some(*node_id),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, DynAny)]
pub struct NavigationMetadata {
/// The current pan, and zoom state of the viewport's view of the node graph.
/// Ensure `DocumentMessage::UpdateDocumentTransform` is called when the pan, zoom, or transform changes.
pub node_graph_ptz: PTZ,
// TODO: Remove and replace with calculate_offset_transform from the node_graph_ptz. This will be difficult since it requires both the navigation message handler and the IPP
/// Transform from node graph space to viewport space.
pub node_graph_to_viewport: DAffine2,
/// The viewport pixel distance distance between the left edge of the node graph and the exports. Rounded to nearest grid space when the panning ends.
#[serde(skip)]
pub exports_to_edge_distance: DVec2,
/// The viewport pixel distance between the left edge of the node graph and the imports. Rounded to nearest grid space when the panning ends.
#[serde(skip)]
pub imports_to_edge_distance: DVec2,
}
impl Default for NavigationMetadata {
fn default() -> NavigationMetadata {
//Default PTZ and transform
NavigationMetadata {
node_graph_ptz: PTZ::default(),
node_graph_to_viewport: DAffine2::IDENTITY,
exports_to_edge_distance: DVec2::ZERO,
imports_to_edge_distance: DVec2::ZERO,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize, DynAny)]
#[serde(default)]
pub struct PTZ {
pub pan: DVec2,
pub tilt: f64,
zoom: f64,
}
impl Default for PTZ {
fn default() -> Self {
Self { pan: DVec2::ZERO, tilt: 0., zoom: 1. }
}
}
impl PTZ {
pub fn zoom(&self) -> f64 {
self.zoom
}
pub fn set_zoom(&mut self, zoom: f64) {
self.zoom = zoom.clamp(graphene_core::consts::VIEWPORT_ZOOM_SCALE_MIN, graphene_core::consts::VIEWPORT_ZOOM_SCALE_MAX)
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@@ -178,6 +178,8 @@ tagged_value! {
CentroidType(graphene_core::vector::misc::CentroidType), CentroidType(graphene_core::vector::misc::CentroidType),
BooleanOperation(graphene_core::vector::misc::BooleanOperation), BooleanOperation(graphene_core::vector::misc::BooleanOperation),
FontCache(Arc<graphene_core::text::FontCache>), FontCache(Arc<graphene_core::text::FontCache>),
Previewing(crate::document::Previewing),
NavigationMetadata(crate::document::NavigationMetadata)
} }
impl TaggedValue { impl TaggedValue {
@@ -297,4 +299,19 @@ mod fake_hash {
self.1.hash(state) self.1.hash(state)
} }
} }
impl FakeHash for crate::document::PTZ {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.pan.hash(state);
self.tilt.hash(state);
self.zoom.hash(state);
}
}
impl FakeHash for crate::document::NavigationMetadata {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.node_graph_ptz.hash(state);
self.node_graph_to_viewport.hash(state);
self.exports_to_edge_distance.hash(state);
self.imports_to_edge_distance.hash(state);
}
}
} }