Begin transferring network metadata

This commit is contained in:
Adam
2024-09-03 13:39:21 -07:00
parent 91ee7b9ff0
commit bc62fd2dea
16 changed files with 354 additions and 289 deletions

View File

@@ -8,8 +8,6 @@ pub const IMPORTS_TO_LEFT_EDGE_PIXEL_GAP: u32 = 120;
// Viewport
pub const VIEWPORT_ZOOM_WHEEL_RATE: f64 = (1. / 600.) * 3.;
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_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,

View File

@@ -2,7 +2,7 @@ use super::node_graph::utility_types::Transform;
use super::utility_types::clipboards::Clipboard;
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::network_interface::{NodeNetworkInterface, TransactionStatus};
use super::utility_types::network_interface::{NodeNetworkInterface, NodeNetworkPersistentMetadata, TransactionStatus};
use super::utility_types::nodes::{CollapsedLayers, SelectedNodes};
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};
@@ -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::properties_panel::utility_types::PropertiesPanelMessageHandlerData;
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::utility_types::PersistentData;
use crate::messages::prelude::*;
@@ -24,7 +24,7 @@ use crate::messages::tool::utility_types::ToolType;
use crate::node_graph_executor::NodeGraphExecutor;
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::ImageFrame;
use graphene_core::vector::style::ViewMode;
@@ -779,10 +779,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
}
DocumentMessage::RenderRulers => {
let current_ptz = if self.graph_view_overlay_open {
let Some(network_metadata) = self.network_interface.network_metadata(&self.breadcrumb_network_path) else {
return;
};
&network_metadata.persistent_metadata.navigation_metadata.node_graph_ptz
self.network_interface.navigation_metadata(&self.breadcrumb_network_path)
} else {
&self.document_ptz
};
@@ -1112,7 +1109,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
let transform = self
.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);
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();
@@ -1981,5 +1978,6 @@ impl DocumentMessageHandler {
fn default_document_network_interface() -> NodeNetworkInterface {
let mut network_interface = NodeNetworkInterface::default();
network_interface.add_export(TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY), -1, "".to_string(), &[]);
network_interface.insert_network_metadata(&[], NodeNetworkPersistentMetadata::default());
network_interface
}

View File

@@ -1,11 +1,11 @@
use super::transform_utils;
use super::utility_types::ModifyInputsContext;
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::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::text::Font;
use graphene_core::vector::style::{Fill, Gradient, GradientStops, GradientType, LineCap, LineJoin, Stroke};

View File

@@ -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 graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graph_craft::document::{value::TaggedValue, InputConnector, NodeId, NodeInput};
use graphene_core::vector::PointId;
use glam::{DAffine2, DVec2};

View File

@@ -1,12 +1,12 @@
use super::transform_utils;
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::network_interface::{self, InputConnector, NodeNetworkInterface, OutputConnector};
use crate::messages::portfolio::document::utility_types::network_interface::{self, NodeNetworkInterface};
use crate::messages::prelude::*;
use bezier_rs::Subpath;
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::text::Font;
use graphene_core::vector::brush_stroke::BrushStroke;

View File

@@ -1,17 +1,16 @@
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_ZOOM_TO_FIT_PADDING_SCALE_FACTOR, VIEWPORT_ZOOM_WHEEL_RATE,
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_WHEEL_RATE,
};
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_mouse::ViewportPosition;
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::prelude::*;
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
use graph_craft::document::NodeId;
use graph_craft::document::{NodeId, PTZ};
use glam::{DAffine2, DVec2};
@@ -46,8 +45,7 @@ impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for Navigation
if !graph_view_overlay_open {
Some(document_ptz)
} else {
let network_metadata = network_interface.network_metadata(breadcrumb_network_path)?;
Some(&network_metadata.persistent_metadata.navigation_metadata.node_graph_ptz)
Some(network_interface.navigation_metadata(breadcrumb_network_path).node_graph_ptz)
}
}
@@ -249,7 +247,7 @@ impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for Navigation
log::error!("Could not get mutable PTZ in CanvasZoomSet");
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);
ptz.set_zoom(zoom);
responses.add(PortfolioMessage::UpdateDocumentWidgets);

View File

@@ -1,11 +1,11 @@
use super::utility_types::Direction;
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::network_interface::{InputConnector, NodeTemplate, OutputConnector};
use crate::messages::portfolio::document::utility_types::network_interface::NodeTemplate;
use crate::messages::prelude::*;
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 interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypesDelta;

View File

@@ -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::utility_types::{ContextMenuData, Direction, FrontendGraphDataType};
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::prelude::*;
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 graphene_core::*;
use renderer::{ClickTarget, Quad};
@@ -158,13 +158,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
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
if let Some(output_connector_position) = self.wire_in_progress_from_connector {
let Some(network_metadata) = network_interface.network_metadata(selection_network_path) else {
log::error!("Could not get network metadata in CreateNodeFromContextMenu");
return;
};
let output_connector_position_viewport = network_metadata
.persistent_metadata
.navigation_metadata
let output_connector_position_viewport = network_interface
.navigation_metadata(selection_network_path)
.node_graph_to_viewport
.transform_point2(output_connector_position);
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");
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 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
.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_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 network_metadata = network_interface.network_metadata(selection_network_path).unwrap();
// Create the add node popup on right click, then exit
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 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. };
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 {
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. };
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);
@@ -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 let Some(context_menu) = &self.context_menu {
let context_menu_viewport = network_metadata
.persistent_metadata
.navigation_metadata
let context_menu_viewport = network_interface
.navigation_metadata(selection_network_path)
.node_graph_to_viewport
.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 { .. }) {
@@ -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");
return;
}
let Some(network_metadata) = network_interface.network_metadata(selection_network_path) else {
return;
};
// Auto-panning
let messages = [NodeGraphMessage::PointerOutsideViewport { shift }.into(), NodeGraphMessage::PointerMove { shift }.into()];
self.auto_panning.setup_by_mouse_position(ipp, &messages, responses);
let viewport_location = ipp.mouse.position;
let point = network_metadata
.persistent_metadata
.navigation_metadata
let point = network_interface
.navigation_metadata(selection_network_path)
.node_graph_to_viewport
.inverse()
.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 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 {
return;
};
let from_connector_viewport = network_metadata
.persistent_metadata
.navigation_metadata
let from_connector_viewport = network_interface
.navigation_metadata(selection_network_path)
.node_graph_to_viewport
.transform_point2(wire_in_progress_from_connector);
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");
return;
};
let Some(network_metadata) = network_interface.network_metadata(selection_network_path) else {
warn!("No network_metadata");
return;
};
responses.add(DocumentMessage::EndTransaction);
@@ -764,16 +741,15 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_selected_nodes });
self.deselect_on_pointer_up = None;
}
let point = network_metadata
.persistent_metadata
.navigation_metadata
let point = network_interface
.navigation_metadata(selection_network_path)
.node_graph_to_viewport
.inverse()
.transform_point2(ipp.mouse.position);
// 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) {
// 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 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);
@@ -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_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 {
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;
};
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 {
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_y: ipp.mouse.position.y.max(0.) as u32,
});
let box_selection_end_graph = network_metadata
.persistent_metadata
.navigation_metadata
let box_selection_end_graph = network_interface
.navigation_metadata(selection_network_path)
.node_graph_to_viewport
.inverse()
.transform_point2(ipp.mouse.position);

View File

@@ -1,9 +1,7 @@
use graph_craft::document::value::TaggedValue;
use graph_craft::document::NodeId;
use graph_craft::document::{NodeId, InputConnector, OutputConnector};
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)]
pub enum FrontendGraphDataType {
#[default]

View File

@@ -1,5 +1,6 @@
use crate::consts::COLOR_OVERLAY_GRAY;
use graph_craft::document::PTZ;
use graphene_core::raster::Color;
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)
}
}

View File

@@ -1,5 +1,4 @@
use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier, NodeRelations};
use super::misc::PTZ;
use super::nodes::SelectedNodes;
use crate::consts::{EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP, EXPORTS_TO_TOP_EDGE_PIXEL_GAP, GRID_SIZE, IMPORTS_TO_LEFT_EDGE_PIXEL_GAP, IMPORTS_TO_TOP_EDGE_PIXEL_GAP};
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext;
@@ -8,6 +7,7 @@ use crate::messages::tool::common_functionality::graph_modification_utils;
use bezier_rs::Subpath;
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 graphene_std::renderer::{ClickTarget, Quad};
use graphene_std::vector::{PointId, VectorData, VectorModificationType};
@@ -998,12 +998,16 @@ impl NodeNetworkInterface {
upstream_nodes_below_layer
}
pub fn previewing(&self, network_path: &[NodeId]) -> Previewing {
let Some(network_metadata) = self.network_metadata(network_path) else {
log::error!("Could not get nested network_metadata in previewing");
return Previewing::No;
pub fn previewing(&self, network_path: &[NodeId]) -> Option<&Previewing> {
let Some(tagged_value) = self.metadata_value(&network_path, Metadata::Previewing) else {
log::error!("Could not get tagged value in previewing");
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
@@ -1012,11 +1016,8 @@ impl NodeNetworkInterface {
log::error!("Could not get network in root_node");
return None;
};
let Some(network_metadata) = self.network_metadata(network_path) else {
log::error!("Could not get nested network_metadata in root_node");
return None;
};
match &network_metadata.persistent_metadata.previewing {
let previewing = self.previewing(network_path);
match &previewing {
Previewing::Yes { root_node_to_restore } => *root_node_to_restore,
Previewing::No => network.exports.first().and_then(|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> {
self.node_metadata(node_id, network_path)
.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();
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");
return "".to_string();
return None;
};
let TaggedValue::String(display_name) = tagged_value else {
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 {
@@ -1842,9 +1855,8 @@ impl NodeNetworkInterface {
let mut import_export_ports = Ports::new();
let viewport_top_right = network_metadata
.persistent_metadata
.navigation_metadata
let viewport_top_right = self
.navigation_metadata(network_path)
.node_graph_to_viewport
.inverse()
.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.));
}
let viewport_top_left = network_metadata
.persistent_metadata
.navigation_metadata
let viewport_top_left = self
.navigation_metadata(network_path)
.node_graph_to_viewport
.inverse()
.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_bottom_right = rounded_network_edge_distance.exports_to_edge_distance;
let node_graph_top_left = network_metadata
.persistent_metadata
.navigation_metadata
let node_graph_top_left = self
.navigation_metadata(network_path)
.node_graph_to_viewport
.inverse()
.transform_point2(import_exports_viewport_top_left);
let node_graph_bottom_right = network_metadata
.persistent_metadata
.navigation_metadata
let node_graph_bottom_right = self
.navigation_metadata(network_path)
.node_graph_to_viewport
.inverse()
.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");
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
/// Click target getter methods
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 {
log::error!("Could not get nested network in node_from_click");
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 clicked_nodes = nodes
.iter()
@@ -2649,7 +2654,7 @@ impl NodeNetworkInterface {
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();
node_ids
@@ -2670,16 +2675,12 @@ impl NodeNetworkInterface {
}
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 {
log::error!("Could not get nested network in input_connector_from_click");
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
.nodes
.keys()
@@ -2703,16 +2704,12 @@ impl NodeNetworkInterface {
}
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 {
log::error!("Could not get nested network in output_connector_from_click");
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<_>>();
nodes
.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
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
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 {
log::error!("Could not get selected nodes in selected_nodes_bounding_box_viewport");
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()
.cloned()
@@ -2797,13 +2790,8 @@ impl NodeNetworkInterface {
/// 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]> {
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]);
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>) {
@@ -2943,27 +2931,26 @@ impl NodeNetworkInterface {
pub fn copy_all_navigation_metadata(&mut self, other_interface: &NodeNetworkInterface) {
let mut stack = vec![vec![]];
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;
};
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| {
let mut current_path = path.clone();
current_path.push(*node_id);
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]) {
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
log::error!("Could not get nested network in set_transform");
return;
};
network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport = transform;
self.navigation_metadata(network_path).node_graph_to_viewport = transform;
self.unload_import_export_ports(network_path);
}
@@ -3468,8 +3455,27 @@ impl NodeNetworkInterface {
node_path.push(node_id);
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));
// 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) {
let network = self.network_mut(&[]).unwrap();
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]) {
// 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 {
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 };
self.set_previewing(network_path, Previewing::Yes { root_node_to_restore: None });
}
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),
} = self.previewing(network_path)
{
@@ -3685,11 +3687,57 @@ impl NodeNetworkInterface {
network_path,
);
}
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
log::error!("Could not get nested network_metadata in stop_previewing");
self.set_previewing(network_path, Previewing::No);
}
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;
};
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
@@ -3709,7 +3757,7 @@ impl NodeNetworkInterface {
// }
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();
node_path.push(*node_id);
@@ -3911,7 +3959,7 @@ impl NodeNetworkInterface {
// The export is clicked
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 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_previewing_state = Previewing::No;
}
@@ -3930,7 +3978,7 @@ impl NodeNetworkInterface {
new_export = Some(OutputConnector::node(toggle_id, 0));
// 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
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
@@ -3940,7 +3988,7 @@ impl NodeNetworkInterface {
} else {
// Root node to restore does not change
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);
}
}
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
return;
};
network_metadata.persistent_metadata.previewing = new_previewing_state;
self.set_previewing(network_path, new_previewing_state);
}
/// 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)]
pub struct Ports {
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.
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct NodeNetworkMetadata {

View File

@@ -1,5 +1,5 @@
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 crate::application::generate_uuid;
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 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_std::vector::style::{Fill, FillType, Gradient};
use interpreted_executor::dynamic_executor::IntrospectError;

View File

@@ -5,12 +5,11 @@ use crate::application::generate_uuid;
use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn;
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::network_interface::InputConnector;
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 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::text::{load_face, Font, FontCache};
use graphene_core::vector::style::Fill;

View File

@@ -7,3 +7,7 @@ pub const LAYER_OUTLINE_STROKE_WEIGHT: f64 = 1.;
// Fonts
pub const DEFAULT_FONT_FAMILY: &str = "Cabin";
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.;

View File

@@ -6,7 +6,7 @@ use graphene_core::memo::MemoHashGuard;
pub use graphene_core::uuid::generate_uuid;
use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type};
use glam::IVec2;
use glam::{DAffine2, DVec2, IVec2};
use log::Metadata;
use rustc_hash::FxHashMap;
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)]
mod test {
use super::*;

View File

@@ -178,6 +178,8 @@ tagged_value! {
CentroidType(graphene_core::vector::misc::CentroidType),
BooleanOperation(graphene_core::vector::misc::BooleanOperation),
FontCache(Arc<graphene_core::text::FontCache>),
Previewing(crate::document::Previewing),
NavigationMetadata(crate::document::NavigationMetadata)
}
impl TaggedValue {
@@ -297,4 +299,19 @@ mod fake_hash {
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);
}
}
}