diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index a3b4a713..68c55cab 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -306,8 +306,8 @@ mod test { }); let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone(); - let layers_before_copy = document_before_copy.document_metadata.all_layers().collect::>(); - let layers_after_copy = document_after_copy.document_metadata.all_layers().collect::>(); + let layers_before_copy = document_before_copy.metadata.all_layers().collect::>(); + let layers_after_copy = document_after_copy.metadata.all_layers().collect::>(); assert_eq!(layers_before_copy.len(), 3); assert_eq!(layers_after_copy.len(), 4); @@ -329,7 +329,7 @@ mod test { let mut editor = create_editor_with_three_layers(); let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone(); - let shape_id = document_before_copy.document_metadata.all_layers().nth(1).unwrap(); + let shape_id = document_before_copy.metadata.all_layers().nth(1).unwrap(); editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![shape_id.to_node()] }); editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::Internal }); @@ -341,8 +341,8 @@ mod test { let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone(); - let layers_before_copy = document_before_copy.document_metadata.all_layers().collect::>(); - let layers_after_copy = document_after_copy.document_metadata.all_layers().collect::>(); + let layers_before_copy = document_before_copy.metadata.all_layers().collect::>(); + let layers_after_copy = document_after_copy.metadata.all_layers().collect::>(); assert_eq!(layers_before_copy.len(), 3); assert_eq!(layers_after_copy.len(), 4); @@ -384,8 +384,8 @@ mod test { let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone(); - let layers_before_copy = document_before_copy.document_metadata.all_layers().collect::>(); - let layers_after_copy = document_after_copy.document_metadata.all_layers().collect::>(); + let layers_before_copy = document_before_copy.metadata.all_layers().collect::>(); + let layers_after_copy = document_after_copy.metadata.all_layers().collect::>(); let [original_folder, original_freehand, original_line, original_ellipse, original_polygon, original_rect] = layers_before_copy[..] else { panic!("Layers before incorrect"); }; @@ -413,7 +413,7 @@ mod test { let mut editor = create_editor_with_three_layers(); let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone(); - let mut layers = document_before_copy.document_metadata.all_layers(); + let mut layers = document_before_copy.metadata.all_layers(); let rect_id = layers.next().expect("rectangle"); let shape_id = layers.next().expect("shape"); let ellipse_id = layers.next().expect("ellipse"); @@ -437,8 +437,8 @@ mod test { let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone(); - let layers_before_copy = document_before_copy.document_metadata.all_layers().collect::>(); - let layers_after_copy = document_after_copy.document_metadata.all_layers().collect::>(); + let layers_before_copy = document_before_copy.metadata.all_layers().collect::>(); + let layers_after_copy = document_after_copy.metadata.all_layers().collect::>(); assert_eq!(layers_before_copy.len(), 3); assert_eq!(layers_after_copy.len(), 6); diff --git a/editor/src/messages/dialog/dialog_message_handler.rs b/editor/src/messages/dialog/dialog_message_handler.rs index 1ea50858..a495dbee 100644 --- a/editor/src/messages/dialog/dialog_message_handler.rs +++ b/editor/src/messages/dialog/dialog_message_handler.rs @@ -75,7 +75,7 @@ impl MessageHandler> for DialogMessageHandler { if let Some(document) = portfolio.active_document() { let mut index = 0; let artboards = document - .document_metadata + .metadata .all_layers() .filter(|&layer| is_layer_fed_by_node_of_name(layer, &document.network, "Artboard")) .map(|layer| { @@ -92,7 +92,7 @@ impl MessageHandler> for DialogMessageHandler { self.export_dialog = ExportDialogMessageHandler { scale_factor: 1., artboards, - has_selection: document.metadata().selected_layers().next().is_some(), + has_selection: document.selected_nodes.selected_layers(document.metadata()).next().is_some(), ..Default::default() }; self.export_dialog.send_dialog_to_frontend(responses); diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index 8448e462..5353b0f1 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -1,7 +1,7 @@ use super::utility_types::{FrontendDocumentDetails, MouseCursorIcon}; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::node_graph::{FrontendNode, FrontendNodeLink, FrontendNodeType}; -use crate::messages::portfolio::document::utility_types::layer_panel::{JsRawBuffer, LayerPanelEntry, RawBuffer}; +use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer}; use crate::messages::prelude::*; use crate::messages::tool::utility_types::HintData; diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 029262b4..b3d821f0 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -1,15 +1,16 @@ use super::utility_types::error::EditorError; use super::utility_types::misc::{SnappingOptions, SnappingState}; +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}; use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::layout::utility_types::widget_prelude::*; -use crate::messages::portfolio::document::node_graph::NodeGraphHandlerData; +use crate::messages::portfolio::document::node_graph::{GraphOperationHandlerData, NodeGraphHandlerData}; use crate::messages::portfolio::document::properties_panel::utility_types::PropertiesPanelMessageHandlerData; use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; use crate::messages::portfolio::document::utility_types::document_metadata::{is_artboard, DocumentMetadata, LayerNodeIdentifier}; -use crate::messages::portfolio::document::utility_types::layer_panel::RawBuffer; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, DocumentMode, FlipAxis, PTZ}; +use crate::messages::portfolio::document::utility_types::nodes::RawBuffer; use crate::messages::portfolio::utility_types::PersistentData; use crate::messages::prelude::*; use crate::messages::tool::common_functionality::graph_modification_utils::{get_blend_mode, get_opacity}; @@ -48,6 +49,10 @@ pub struct DocumentMessageHandler { // ============================================ #[serde(default = "default_network")] pub network: NodeNetwork, + #[serde(default = "default_selected_nodes")] + pub selected_nodes: SelectedNodes, + #[serde(default = "default_collapsed")] + pub collapsed: CollapsedLayers, #[serde(default = "default_name")] pub name: String, #[serde(default = "default_commit_hash")] @@ -62,8 +67,6 @@ pub struct DocumentMessageHandler { overlays_visible: bool, #[serde(default = "default_rulers_visible")] pub rulers_visible: bool, - #[serde(default = "default_collapsed")] - pub collapsed: Vec, // ============================================= // Fields omitted from the saved document format // ============================================= @@ -85,7 +88,7 @@ pub struct DocumentMessageHandler { #[serde(skip)] layer_range_selection_reference: Option, #[serde(skip)] - pub document_metadata: DocumentMetadata, + pub metadata: DocumentMetadata, } impl Default for DocumentMessageHandler { @@ -102,6 +105,8 @@ impl Default for DocumentMessageHandler { // Fields that are saved in the document format // ============================================ network: root_network(), + selected_nodes: SelectedNodes::default(), + collapsed: CollapsedLayers::default(), name: DEFAULT_DOCUMENT_NAME.to_string(), commit_hash: GRAPHITE_GIT_COMMIT_HASH.to_string(), navigation: PTZ::default(), @@ -109,7 +114,6 @@ impl Default for DocumentMessageHandler { view_mode: ViewMode::default(), overlays_visible: true, rulers_visible: true, - collapsed: Vec::new(), // ============================================= // Fields omitted from the saved document format // ============================================= @@ -121,7 +125,7 @@ impl Default for DocumentMessageHandler { graph_view_overlay_open: false, snapping_state: SnappingState::default(), layer_range_selection_reference: None, - document_metadata: Default::default(), + metadata: Default::default(), } } } @@ -131,6 +135,14 @@ fn default_network() -> NodeNetwork { DocumentMessageHandler::default().network } #[inline(always)] +fn default_selected_nodes() -> SelectedNodes { + DocumentMessageHandler::default().selected_nodes +} +#[inline(always)] +fn default_collapsed() -> CollapsedLayers { + DocumentMessageHandler::default().collapsed +} +#[inline(always)] fn default_name() -> String { DocumentMessageHandler::default().name } @@ -158,10 +170,6 @@ fn default_overlays_visible() -> bool { fn default_rulers_visible() -> bool { DocumentMessageHandler::default().rulers_visible } -#[inline(always)] -fn default_collapsed() -> Vec { - DocumentMessageHandler::default().collapsed -} fn root_network() -> NodeNetwork { { @@ -245,13 +253,7 @@ impl MessageHandler> for DocumentMessageHand self.navigation_handler.process_message( message, responses, - ( - &self.document_metadata, - document_bounds, - ipp, - self.selected_visible_layers_bounding_box_viewport(), - &mut self.navigation, - ), + (&self.metadata, document_bounds, ipp, self.selected_visible_layers_bounding_box_viewport(), &mut self.navigation), ); } #[remain::unsorted] @@ -265,7 +267,8 @@ impl MessageHandler> for DocumentMessageHand executor, document_name: self.name.as_str(), document_network: &self.network, - document_metadata: &mut self.document_metadata, + document_metadata: &mut self.metadata, + selected_nodes: &self.selected_nodes, }; self.properties_panel_message_handler .process_message(message, responses, (persistent_data, properties_panel_message_handler_data)); @@ -277,7 +280,8 @@ impl MessageHandler> for DocumentMessageHand responses, NodeGraphHandlerData { document_network: &mut self.network, - document_metadata: &mut self.document_metadata, + document_metadata: &mut self.metadata, + selected_nodes: &mut self.selected_nodes, document_id, document_name: self.name.as_str(), collapsed: &mut self.collapsed, @@ -287,7 +291,17 @@ impl MessageHandler> for DocumentMessageHand ); } #[remain::unsorted] - GraphOperation(message) => GraphOperationMessageHandler.process_message(message, responses, (&mut self.network, &mut self.document_metadata, &mut self.collapsed, &mut self.node_graph_handler)), + GraphOperation(message) => GraphOperationMessageHandler.process_message( + message, + responses, + GraphOperationHandlerData { + document_network: &mut self.network, + document_metadata: &mut self.metadata, + selected_nodes: &mut self.selected_nodes, + collapsed: &mut self.collapsed, + node_graph: &mut self.node_graph_handler, + }, + ), // Messages AbortTransaction => { @@ -312,7 +326,7 @@ impl MessageHandler> for DocumentMessageHand AlignAggregate::Max => combined_box[1], AlignAggregate::Center => (combined_box[0] + combined_box[1]) / 2., }; - for layer in self.metadata().selected_layers() { + for layer in self.selected_nodes.selected_layers(self.metadata()) { let Some(bbox) = self.metadata().bounding_box_viewport(layer) else { continue; }; @@ -366,7 +380,7 @@ impl MessageHandler> for DocumentMessageHand self.backup(responses); responses.add_front(BroadcastEvent::SelectionChanged); - for path in self.metadata().shallowest_unique_layers(self.metadata().selected_layers()) { + for path in self.metadata().shallowest_unique_layers(self.selected_nodes.selected_layers(self.metadata())) { responses.add_front(DocumentMessage::DeleteLayer { id: path.last().unwrap().to_node() }); } @@ -381,7 +395,7 @@ impl MessageHandler> for DocumentMessageHand DocumentStructureChanged => { self.update_layers_panel_options_bar_widgets(responses); - self.document_metadata.load_structure(&self.network); + self.metadata.load_structure(&self.network, &mut self.selected_nodes); let data_buffer: RawBuffer = self.serialize_root(); responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer }); } @@ -402,7 +416,7 @@ impl MessageHandler> for DocumentMessageHand if let Some([min, max]) = self.selected_visible_layers_bounding_box_viewport() { let center = (max + min) / 2.; let bbox_trans = DAffine2::from_translation(-center); - for layer in self.metadata().selected_layers() { + for layer in self.selected_nodes.selected_layers(self.metadata()) { responses.add(GraphOperationMessage::TransformChange { layer, transform: DAffine2::from_scale(scale), @@ -426,7 +440,10 @@ impl MessageHandler> for DocumentMessageHand } GroupSelectedLayers => { // TODO: Add code that changes the insert index of the new folder based on the selected layer - let parent = self.metadata().deepest_common_ancestor(self.metadata().selected_layers(), true).unwrap_or(LayerNodeIdentifier::ROOT); + let parent = self + .metadata() + .deepest_common_ancestor(self.selected_nodes.selected_layers(self.metadata()), true) + .unwrap_or(LayerNodeIdentifier::ROOT); let folder_id = NodeId(generate_uuid()); @@ -467,7 +484,7 @@ impl MessageHandler> for DocumentMessageHand } } MoveSelectedLayersTo { parent, insert_index } => { - let selected_layers = self.metadata().selected_layers().collect::>(); + let selected_layers = self.selected_nodes.selected_layers(self.metadata()).collect::>(); // Disallow trying to insert into self if selected_layers.iter().any(|&layer| parent.ancestors(self.metadata()).any(|ancestor| ancestor == layer)) { @@ -495,7 +512,7 @@ impl MessageHandler> for DocumentMessageHand let opposite_corner = ipp.keyboard.key(resize_opposite_corner); let delta = DVec2::new(delta_x, delta_y); - for layer in self.metadata().selected_layers() { + for layer in self.selected_nodes.selected_layers(self.metadata()) { // Nudge translation if !ipp.keyboard.key(resize) { responses.add(GraphOperationMessage::TransformChange { @@ -506,7 +523,7 @@ impl MessageHandler> for DocumentMessageHand }); } // Nudge resize - else if let Some([existing_top_left, existing_bottom_right]) = self.document_metadata.bounding_box_document(layer) { + else if let Some([existing_top_left, existing_bottom_right]) = self.metadata.bounding_box_document(layer) { let size = existing_bottom_right - existing_top_left; let new_size = size + if opposite_corner { -delta } else { delta }; let enlargement_factor = new_size / size; @@ -636,8 +653,10 @@ impl MessageHandler> for DocumentMessageHand }) } SelectAllLayers => { - let all = self.metadata().all_layers_except_artboards().map(|layer| layer.to_node()).collect(); - responses.add(NodeGraphMessage::SelectedNodesSet { nodes: all }); + let metadata = self.metadata(); + let all_layers_except_artboards = metadata.all_layers().filter(move |&layer| !metadata.is_artboard(layer)); + let nodes = all_layers_except_artboards.map(|layer| layer.to_node()).collect(); + responses.add(NodeGraphMessage::SelectedNodesSet { nodes: nodes }); } SelectedLayersLower => { responses.add(DocumentMessage::SelectedLayersReorder { relative_index_offset: 1 }); @@ -674,7 +693,7 @@ impl MessageHandler> for DocumentMessageHand } else { if ctrl { // Toggle selection when holding ctrl - if self.metadata().selected_layers_contains(layer) { + if self.selected_nodes.selected_layers_contains(layer, self.metadata()) { responses.add_front(NodeGraphMessage::SelectedNodesRemove { nodes: vec![id] }); } else { responses.add_front(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] }); @@ -700,7 +719,7 @@ impl MessageHandler> for DocumentMessageHand } SetBlendModeForSelectedLayers { blend_mode } => { self.backup(responses); - for layer in self.metadata().selected_layers_except_artboards() { + for layer in self.selected_nodes.selected_layers_except_artboards(self.metadata()) { responses.add(GraphOperationMessage::BlendModeSet { layer, blend_mode }); } } @@ -708,7 +727,7 @@ impl MessageHandler> for DocumentMessageHand self.backup(responses); let opacity = opacity.clamp(0., 1.) as f32; - for layer in self.metadata().selected_layers_except_artboards() { + for layer in self.selected_nodes.selected_layers_except_artboards(self.metadata()) { responses.add(GraphOperationMessage::OpacitySet { layer, opacity }); } } @@ -742,10 +761,10 @@ impl MessageHandler> for DocumentMessageHand StartTransaction => self.backup(responses), ToggleLayerExpansion { id } => { let layer = LayerNodeIdentifier::new(id, self.network()); - if self.collapsed.contains(&layer) { - self.collapsed.retain(|&collapsed_layer| collapsed_layer != layer); + if self.collapsed.0.contains(&layer) { + self.collapsed.0.retain(|&collapsed_layer| collapsed_layer != layer); } else { - self.collapsed.push(layer); + self.collapsed.0.push(layer); } responses.add(NodeGraphMessage::RunDocumentGraph); } @@ -761,7 +780,7 @@ impl MessageHandler> for DocumentMessageHand UngroupSelectedLayers => { responses.add(DocumentMessage::StartTransaction); - let folder_paths = self.metadata().folders_sorted_by_most_nested(self.metadata().selected_layers()); + let folder_paths = self.metadata().folders_sorted_by_most_nested(self.selected_nodes.selected_layers(self.metadata())); for folder in folder_paths { // Select all the children of the folder @@ -784,7 +803,7 @@ impl MessageHandler> for DocumentMessageHand responses.add(DocumentMessage::CommitTransaction); } UpdateDocumentTransform { transform } => { - self.document_metadata.document_to_viewport = transform; + self.metadata.document_to_viewport = transform; responses.add(DocumentMessage::RenderRulers); responses.add(DocumentMessage::RenderScrollbars); responses.add(NodeGraphMessage::RunDocumentGraph); @@ -810,44 +829,28 @@ impl MessageHandler> for DocumentMessageHand } impl DocumentMessageHandler { - pub fn layer_visible(&self, layer: LayerNodeIdentifier) -> bool { - !layer.ancestors(&self.document_metadata).any(|layer| self.network.disabled.contains(&layer.to_node())) - } - - pub fn selected_visible_layers(&self) -> impl Iterator + '_ { - self.document_metadata.selected_layers().filter(|&layer| self.layer_visible(layer)) - } - /// Runs an intersection test with all layers and a viewport space quad pub fn intersect_quad<'a>(&'a self, viewport_quad: graphene_core::renderer::Quad, network: &'a NodeNetwork) -> impl Iterator + 'a { - let document_quad = self.document_metadata.document_to_viewport.inverse() * viewport_quad; - self.document_metadata + let document_quad = self.metadata.document_to_viewport.inverse() * viewport_quad; + self.metadata .root() - .decendants(&self.document_metadata) - .filter(|&layer| self.layer_visible(layer)) + .decendants(&self.metadata) + .filter(|&layer| self.selected_nodes.layer_visible(layer, &self.network(), &self.metadata())) .filter(|&layer| !is_artboard(layer, network)) - .filter_map(|layer| self.document_metadata.click_target(layer).map(|targets| (layer, targets))) - .filter(move |(layer, target)| { - target - .iter() - .any(move |target| target.intersect_rectangle(document_quad, self.document_metadata.transform_to_document(*layer))) - }) + .filter_map(|layer| self.metadata.click_target(layer).map(|targets| (layer, targets))) + .filter(move |(layer, target)| target.iter().any(move |target| target.intersect_rectangle(document_quad, self.metadata.transform_to_document(*layer)))) .map(|(layer, _)| layer) } /// Find all of the layers that were clicked on from a viewport space location pub fn click_xray(&self, viewport_location: DVec2) -> impl Iterator + '_ { - let point = self.document_metadata.document_to_viewport.inverse().transform_point2(viewport_location); - self.document_metadata + let point = self.metadata.document_to_viewport.inverse().transform_point2(viewport_location); + self.metadata .root() - .decendants(&self.document_metadata) - .filter(|&layer| self.layer_visible(layer)) - .filter_map(|layer| self.document_metadata.click_target(layer).map(|targets| (layer, targets))) - .filter(move |(layer, target)| { - target - .iter() - .any(|target: &ClickTarget| target.intersect_point(point, self.document_metadata.transform_to_document(*layer))) - }) + .decendants(&self.metadata) + .filter(|&layer| self.selected_nodes.layer_visible(layer, &self.network(), &self.metadata())) + .filter_map(|layer| self.metadata.click_target(layer).map(|targets| (layer, targets))) + .filter(move |(layer, target)| target.iter().any(|target: &ClickTarget| target.intersect_point(point, self.metadata.transform_to_document(*layer)))) .map(|(layer, _)| layer) } @@ -858,8 +861,9 @@ impl DocumentMessageHandler { /// Get the combined bounding box of the click targets of the selected visible layers in viewport space pub fn selected_visible_layers_bounding_box_viewport(&self) -> Option<[DVec2; 2]> { - self.selected_visible_layers() - .filter_map(|layer| self.document_metadata.bounding_box_viewport(layer)) + self.selected_nodes + .selected_visible_layers(&self.network(), &self.metadata()) + .filter_map(|layer| self.metadata.bounding_box_viewport(layer)) .reduce(graphene_core::renderer::Quad::combine_bounds) } @@ -868,7 +872,7 @@ impl DocumentMessageHandler { } pub fn metadata(&self) -> &DocumentMetadata { - &self.document_metadata + &self.metadata } pub fn serialize_document(&self) -> String { @@ -884,7 +888,7 @@ impl DocumentMessageHandler { pub fn with_name(name: String, ipp: &InputPreprocessorMessageHandler, responses: &mut VecDeque) -> Self { let mut document = Self { name, ..Self::default() }; let transform = document.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.size() / 2., DVec2::ZERO, 0., 1.); - document.document_metadata.document_to_viewport = transform; + document.metadata.document_to_viewport = transform; responses.add(DocumentMessage::UpdateDocumentTransform { transform }); document @@ -909,7 +913,7 @@ impl DocumentMessageHandler { for layer_node in folder.children(self.metadata()) { data_section.push(layer_node.to_node().0); space += 1; - if layer_node.has_children(self.metadata()) && !self.collapsed.contains(&layer_node) { + if layer_node.has_children(self.metadata()) && !self.collapsed.0.contains(&layer_node) { path.push(layer_node); // TODO: Skip if folder is not expanded. @@ -1066,7 +1070,7 @@ impl DocumentMessageHandler { pub fn new_layer_parent(&self) -> LayerNodeIdentifier { self.metadata() - .deepest_common_ancestor(self.metadata().selected_layers(), false) + .deepest_common_ancestor(self.selected_nodes.selected_layers(self.metadata()), false) .unwrap_or_else(|| self.metadata().active_artboard()) } @@ -1278,7 +1282,7 @@ impl DocumentMessageHandler { pub fn update_layers_panel_options_bar_widgets(&self, responses: &mut VecDeque) { // Get an iterator over the selected layers (excluding artboards which don't have an opacity or blend mode). - let selected_layers_except_artboards = self.metadata().selected_layers_except_artboards(); + let selected_layers_except_artboards = self.selected_nodes.selected_layers_except_artboards(self.metadata()); // Look up the current opacity and blend mode of the selected layers (if any), and split the iterator into the first tuple and the rest. let mut opacity_and_blend_mode = selected_layers_except_artboards.map(|layer| (get_opacity(layer, &self.network).unwrap_or(100.), get_blend_mode(layer, &self.network).unwrap_or_default())); @@ -1372,7 +1376,7 @@ impl DocumentMessageHandler { pub fn selected_layers_reorder(&mut self, relative_index_offset: isize, responses: &mut VecDeque) { self.backup(responses); - let mut selected_layers = self.metadata().selected_layers(); + let mut selected_layers = self.selected_nodes.selected_layers(self.metadata()); let first_or_last_selected_layer = match relative_index_offset.signum() { -1 => selected_layers.next(), @@ -1429,7 +1433,7 @@ impl DocumentMessageHandler { common.extend(escape); } - if self.metadata().selected_layers().next().is_some() { + if self.selected_nodes.selected_layers(self.metadata()).next().is_some() { let select = actions!(DocumentMessageDiscriminant; DeleteSelectedLayers, DuplicateSelectedLayers, diff --git a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs index 0a2e1ed8..0bf6d156 100644 --- a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs +++ b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs @@ -54,7 +54,7 @@ impl MessageHandler, & &mut self, message: NavigationMessage, responses: &mut VecDeque, - (document_metadata, document_bounds, ipp, selection_bounds, ptz): (&DocumentMetadata, Option<[DVec2; 2]>, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>, &mut PTZ), + (metadata, document_bounds, ipp, selection_bounds, ptz): (&DocumentMetadata, Option<[DVec2; 2]>, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>, &mut PTZ), ) { use NavigationMessage::*; @@ -73,8 +73,8 @@ impl MessageHandler, & bounds: [pos1, pos2], prevent_zoom_past_100, } => { - let v1 = document_metadata.document_to_viewport.inverse().transform_point2(DVec2::ZERO); - let v2 = document_metadata.document_to_viewport.inverse().transform_point2(ipp.viewport_bounds.size()); + let v1 = metadata.document_to_viewport.inverse().transform_point2(DVec2::ZERO); + let v2 = metadata.document_to_viewport.inverse().transform_point2(ipp.viewport_bounds.size()); let center = v1.lerp(v2, 0.5) - pos1.lerp(pos2, 0.5); let size = (pos2 - pos1) / (v2 - v1); @@ -96,7 +96,7 @@ impl MessageHandler, & } FitViewportToSelection => { if let Some(bounds) = selection_bounds { - let transform = document_metadata.document_to_viewport.inverse(); + let transform = metadata.document_to_viewport.inverse(); responses.add(FitViewportToBounds { bounds: [transform.transform_point2(bounds[0]), transform.transform_point2(bounds[1])], prevent_zoom_past_100: false, @@ -257,7 +257,7 @@ impl MessageHandler, & responses.add(TransformCanvasEnd { abort_transform }); } TranslateCanvas { delta } => { - let transformed_delta = document_metadata.document_to_viewport.inverse().transform_vector2(delta); + let transformed_delta = metadata.document_to_viewport.inverse().transform_vector2(delta); ptz.pan += transformed_delta; responses.add(BroadcastEvent::CanvasTransformed); @@ -275,7 +275,7 @@ impl MessageHandler, & self.transform_operation = TransformOperation::Pan { pre_commit_pan: ptz.pan }; } TranslateCanvasByViewportFraction { delta } => { - let transformed_delta = document_metadata.document_to_viewport.inverse().transform_vector2(delta * ipp.viewport_bounds.size()); + let transformed_delta = metadata.document_to_viewport.inverse().transform_vector2(delta * ipp.viewport_bounds.size()); ptz.pan += transformed_delta; responses.add(BroadcastEvent::DocumentIsDirty); diff --git a/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler.rs index f81c71af..71c57b68 100644 --- a/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler.rs @@ -1,5 +1,6 @@ use super::{resolve_document_node_type, VectorDataModification}; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; +use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, SelectedNodes}; use crate::messages::prelude::*; use bezier_rs::Subpath; @@ -509,7 +510,7 @@ impl<'a> ModifyInputsContext<'a> { }); } - fn delete_layer(&mut self, id: NodeId) { + fn delete_layer(&mut self, id: NodeId, selected_nodes: &mut SelectedNodes) { let Some(node) = self.document_network.nodes.get(&id) else { warn!("Deleting layer node that does not exist"); return; @@ -558,20 +559,31 @@ impl<'a> ModifyInputsContext<'a> { } } - self.document_metadata.retain_selected_nodes(|id| !delete_nodes.contains(id)); + selected_nodes.retain_selected_nodes(|id| !delete_nodes.contains(id)); self.responses.add(BroadcastEvent::SelectionChanged); self.responses.add(NodeGraphMessage::RunDocumentGraph); } } -impl MessageHandler, &mut NodeGraphMessageHandler)> for GraphOperationMessageHandler { - fn process_message( - &mut self, - message: GraphOperationMessage, - responses: &mut VecDeque, - (document_network, document_metadata, collapsed, node_graph): (&mut NodeNetwork, &mut DocumentMetadata, &mut Vec, &mut NodeGraphMessageHandler), - ) { +pub struct GraphOperationHandlerData<'a> { + pub document_network: &'a mut NodeNetwork, + pub document_metadata: &'a mut DocumentMetadata, + pub selected_nodes: &'a mut SelectedNodes, + pub collapsed: &'a mut CollapsedLayers, + pub node_graph: &'a mut NodeGraphMessageHandler, +} + +impl MessageHandler> for GraphOperationMessageHandler { + fn process_message(&mut self, message: GraphOperationMessage, responses: &mut VecDeque, data: GraphOperationHandlerData) { + let GraphOperationHandlerData { + document_network, + document_metadata, + selected_nodes, + collapsed, + node_graph, + } = data; + match message { GraphOperationMessage::FillSet { layer, fill } => { if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { @@ -645,7 +657,7 @@ impl MessageHandler { let mut modify_inputs = ModifyInputsContext::new(document_network, document_metadata, node_graph, responses); if let Some(layer) = modify_inputs.create_layer_with_insert_index(id, insert_index, parent) { modify_inputs.insert_vector_data(subpaths, layer); } - load_network_structure(document_network, document_metadata, collapsed); + load_network_structure(document_network, document_metadata, selected_nodes, collapsed); } GraphOperationMessage::NewTextLayer { id, @@ -719,7 +731,7 @@ impl MessageHandler { if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(id, document_network, document_metadata, node_graph, responses) { @@ -728,18 +740,18 @@ impl MessageHandler { let mut modify_inputs = ModifyInputsContext::new(document_network, document_metadata, node_graph, responses); - modify_inputs.delete_layer(id); - load_network_structure(document_network, document_metadata, collapsed); + modify_inputs.delete_layer(id, selected_nodes); + load_network_structure(document_network, document_metadata, selected_nodes, collapsed); } GraphOperationMessage::ClearArtboards => { let mut modify_inputs = ModifyInputsContext::new(document_network, document_metadata, node_graph, responses); let layer_nodes = modify_inputs.document_network.nodes.iter().filter(|(_, node)| node.is_layer()).map(|(id, _)| *id).collect::>(); for layer in layer_nodes { if modify_inputs.document_network.upstream_flow_back_from_nodes(vec![layer], true).any(|(node, _id)| node.is_artboard()) { - modify_inputs.delete_layer(layer); + modify_inputs.delete_layer(layer, selected_nodes); } } - load_network_structure(document_network, document_metadata, collapsed); + load_network_structure(document_network, document_metadata, selected_nodes, collapsed); } } } @@ -749,7 +761,7 @@ impl MessageHandler) { - document_metadata.load_structure(document_network); - collapsed.retain(|&layer| document_metadata.layer_exists(layer)); +pub fn load_network_structure(document_network: &NodeNetwork, document_metadata: &mut DocumentMetadata, selected_nodes: &mut SelectedNodes, collapsed: &mut CollapsedLayers) { + document_metadata.load_structure(document_network, selected_nodes); + collapsed.0.retain(|&layer| document_metadata.layer_exists(layer)); } diff --git a/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler/transform_utils.rs b/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler/transform_utils.rs index 6ae4a12f..33bdbb0c 100644 --- a/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler/transform_utils.rs +++ b/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler/transform_utils.rs @@ -52,11 +52,11 @@ pub struct LayerBounds { impl LayerBounds { /// Extract the layer bounds and their transform for a layer. - pub fn new(document_metadata: &DocumentMetadata, layer: LayerNodeIdentifier) -> Self { + pub fn new(metadata: &DocumentMetadata, layer: LayerNodeIdentifier) -> Self { Self { - bounds: document_metadata.nonzero_bounding_box(layer), + bounds: metadata.nonzero_bounding_box(layer), bounds_transform: DAffine2::IDENTITY, - layer_transform: document_metadata.transform_to_document(layer), + layer_transform: metadata.transform_to_document(layer), } } diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 4f81b5ac..f85346a3 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -4,7 +4,7 @@ use crate::application::generate_uuid; use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; -use crate::messages::portfolio::document::utility_types::layer_panel::{LayerClassification, LayerPanelEntry}; +use crate::messages::portfolio::document::utility_types::nodes::{CollapsedLayers, LayerClassification, LayerPanelEntry, SelectedNodes}; use crate::messages::prelude::*; use graph_craft::document::value::TaggedValue; @@ -174,20 +174,20 @@ impl NodeGraphMessageHandler { } /// Updates the buttons for disable and preview - fn update_selection_action_buttons(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, responses: &mut VecDeque) { + fn update_selection_action_buttons(&mut self, document_network: &NodeNetwork, selected_nodes: &SelectedNodes, responses: &mut VecDeque) { if let Some(network) = document_network.nested_network(&self.network) { let mut widgets = Vec::new(); // Don't allow disabling input or output nodes - let mut selected_nodes = document_metadata.selected_nodes().filter(|&&id| !network.inputs.contains(&id) && !network.original_outputs_contain(id)); + let mut selection = selected_nodes.selected_nodes().filter(|&&id| !network.inputs.contains(&id) && !network.original_outputs_contain(id)); // If there is at least one other selected node then show the hide or show button - if selected_nodes.next().is_some() { + if selection.next().is_some() { // Check if any of the selected nodes are disabled - let is_hidden = document_metadata.selected_nodes().any(|id| network.disabled.contains(id)); + let is_hidden = selected_nodes.selected_nodes().any(|id| network.disabled.contains(id)); // Check if multiple nodes are selected - let multiple_nodes = selected_nodes.next().is_some(); + let multiple_nodes = selection.next().is_some(); // Generate the enable or disable button accordingly let (hide_show_label, hide_show_icon) = if is_hidden { ("Make Visible", "EyeHidden") } else { ("Make Hidden", "EyeVisible") }; @@ -203,8 +203,8 @@ impl NodeGraphMessageHandler { } // If only one node is selected then show the preview or stop previewing button - let mut selected_nodes = document_metadata.selected_nodes(); - if let (Some(&node_id), None) = (selected_nodes.next(), selected_nodes.next()) { + let mut selection = selected_nodes.selected_nodes(); + if let (Some(&node_id), None) = (selection.next(), selection.next()) { // Is this node the current output let is_output = network.outputs_contain(node_id); @@ -225,7 +225,7 @@ impl NodeGraphMessageHandler { } /// Collate the properties panel sections for a node graph - pub fn collate_properties(&self, context: &mut NodePropertiesContext) -> Vec { + pub fn collate_properties(&self, context: &mut NodePropertiesContext, selected_nodes: &SelectedNodes) -> Vec { let mut network = context.network; for segment in &self.network { @@ -239,7 +239,7 @@ impl NodeGraphMessageHandler { // First, we filter all the selections into layers and nodes let (mut layers, mut nodes) = (Vec::new(), Vec::new()); - for node_id in context.metadata.selected_nodes() { + for node_id in selected_nodes.selected_nodes() { if let Some(layer_or_node) = network.nodes.get(node_id) { if layer_or_node.is_layer() { layers.push(*node_id); @@ -278,8 +278,16 @@ impl NodeGraphMessageHandler { } } - fn send_graph(&self, network: &NodeNetwork, graph_view_overlay_open: bool, document_metadata: &mut DocumentMetadata, collapsed: &Vec, responses: &mut VecDeque) { - document_metadata.load_structure(&network); + fn send_graph( + &self, + network: &NodeNetwork, + graph_view_overlay_open: bool, + metadata: &mut DocumentMetadata, + selected_nodes: &mut SelectedNodes, + collapsed: &CollapsedLayers, + responses: &mut VecDeque, + ) { + metadata.load_structure(network, selected_nodes); let links = network .nodes @@ -371,9 +379,9 @@ impl NodeGraphMessageHandler { if node.is_layer() { let layer = LayerNodeIdentifier::new(node_id, network); let layer_classification = { - if document_metadata.is_artboard(layer) { + if metadata.is_artboard(layer) { LayerClassification::Artboard - } else if document_metadata.is_folder(layer) { + } else if metadata.is_folder(layer) { LayerClassification::Folder } else { LayerClassification::Layer @@ -391,9 +399,9 @@ impl NodeGraphMessageHandler { let data = LayerPanelEntry { id: node_id, layer_classification, - expanded: layer.has_children(document_metadata) && !collapsed.contains(&layer), - depth: layer.ancestors(document_metadata).count() - 1, - parent_id: layer.parent(document_metadata).map(|parent| parent.to_node()), + expanded: layer.has_children(metadata) && !collapsed.0.contains(&layer), + depth: layer.ancestors(metadata).count() - 1, + parent_id: layer.parent(metadata).map(|parent| parent.to_node()), // TODO: Remove and take this from the graph data in the frontend similar to thumbnail? name: network.nodes.get(&node_id).map(|node| node.alias.clone()).unwrap_or_default(), // TODO: Remove and take this from the graph data in the frontend similar to thumbnail? @@ -413,10 +421,10 @@ impl NodeGraphMessageHandler { } /// Updates the frontend's selection state in line with the backend - fn update_selected(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, responses: &mut VecDeque) { - self.update_selection_action_buttons(document_network, document_metadata, responses); + fn update_selected(&mut self, document_network: &NodeNetwork, selected_nodes: &SelectedNodes, responses: &mut VecDeque) { + self.update_selection_action_buttons(document_network, selected_nodes, responses); responses.add(FrontendMessage::UpdateNodeGraphSelection { - selected: document_metadata.selected_nodes_ref().clone(), + selected: selected_nodes.selected_nodes_ref().clone(), }); } @@ -487,7 +495,7 @@ impl NodeGraphMessageHandler { } /// Tries to remove a node from the network, returning true on success. - fn remove_node(&mut self, document_network: &mut NodeNetwork, document_metadata: &mut DocumentMetadata, node_id: NodeId, responses: &mut VecDeque, reconnect: bool) -> bool { + fn remove_node(&mut self, document_network: &mut NodeNetwork, selected_nodes: &mut SelectedNodes, node_id: NodeId, responses: &mut VecDeque, reconnect: bool) -> bool { let Some(network) = document_network.nested_network_mut(&self.network) else { return false; }; @@ -495,7 +503,7 @@ impl NodeGraphMessageHandler { return false; } network.nodes.remove(&node_id); - document_metadata.retain_selected_nodes(|&id| id != node_id); + selected_nodes.retain_selected_nodes(|&id| id != node_id); responses.add(BroadcastEvent::SelectionChanged); true } @@ -521,9 +529,10 @@ impl NodeGraphMessageHandler { pub struct NodeGraphHandlerData<'a> { pub document_network: &'a mut NodeNetwork, pub document_metadata: &'a mut DocumentMetadata, + pub selected_nodes: &'a mut SelectedNodes, pub document_id: DocumentId, pub document_name: &'a str, - pub collapsed: &'a mut Vec, + pub collapsed: &'a mut CollapsedLayers, pub input: &'a InputPreprocessorMessageHandler, pub graph_view_overlay_open: bool, } @@ -533,6 +542,7 @@ impl<'a> MessageHandler> for NodeGrap let NodeGraphHandlerData { document_network, document_metadata, + selected_nodes, document_id, collapsed, graph_view_overlay_open, @@ -545,14 +555,14 @@ impl<'a> MessageHandler> for NodeGrap on: BroadcastEvent::SelectionChanged, send: Box::new(NodeGraphMessage::SelectedNodesUpdated.into()), }); - load_network_structure(document_network, document_metadata, collapsed); + load_network_structure(document_network, document_metadata, selected_nodes, collapsed); } NodeGraphMessage::SelectedNodesUpdated => { - self.update_selection_action_buttons(document_network, document_metadata, responses); - self.update_selected(document_network, document_metadata, responses); - if document_metadata.selected_layers().count() <= 1 { + self.update_selection_action_buttons(document_network, selected_nodes, responses); + self.update_selected(document_network, selected_nodes, responses); + if selected_nodes.selected_layers(document_metadata).count() <= 1 { responses.add(DocumentMessage::SetRangeSelectionLayer { - new_layer: document_metadata.selected_layers().next(), + new_layer: selected_nodes.selected_layers(document_metadata).next(), }); } responses.add(NodeGraphMessage::RunDocumentGraph); @@ -594,7 +604,7 @@ impl<'a> MessageHandler> for NodeGrap }; // Collect the selected nodes - let new_ids = &document_metadata.selected_nodes().copied().enumerate().map(|(new, old)| (old, NodeId(new as u64))).collect(); + let new_ids = &selected_nodes.selected_nodes().copied().enumerate().map(|(new, old)| (old, NodeId(new as u64))).collect(); let copied_nodes: Vec<_> = Self::copy_nodes(network, new_ids).collect(); // Prefix to show that this is nodes @@ -627,18 +637,18 @@ impl<'a> MessageHandler> for NodeGrap responses.add(NodeGraphMessage::DeleteSelectedNodes { reconnect: true }); } NodeGraphMessage::DeleteNode { node_id, reconnect } => { - self.remove_node(document_network, document_metadata, node_id, responses, reconnect); + self.remove_node(document_network, selected_nodes, node_id, responses, reconnect); } NodeGraphMessage::DeleteSelectedNodes { reconnect } => { responses.add(DocumentMessage::StartTransaction); - for node_id in document_metadata.selected_nodes().copied() { + for node_id in selected_nodes.selected_nodes().copied() { responses.add(NodeGraphMessage::DeleteNode { node_id, reconnect }); } if let Some(network) = document_network.nested_network(&self.network) { // Only generate node graph if one of the selected nodes is connected to the output - if document_metadata.selected_nodes().any(|&node_id| network.connected_to_output(node_id)) { + if selected_nodes.selected_nodes().any(|&node_id| network.connected_to_output(node_id)) { responses.add(NodeGraphMessage::RunDocumentGraph); } } @@ -679,24 +689,24 @@ impl<'a> MessageHandler> for NodeGrap } } if let Some(network) = document_network.nested_network(&self.network) { - self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses); + self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } - self.update_selected(document_network, document_metadata, responses); + self.update_selected(document_network, selected_nodes, responses); } NodeGraphMessage::DuplicateSelectedNodes => { if let Some(network) = document_network.nested_network(&self.network) { responses.add(DocumentMessage::StartTransaction); - let new_ids = &document_metadata.selected_nodes().map(|&id| (id, NodeId(generate_uuid()))).collect(); + let new_ids = &selected_nodes.selected_nodes().map(|&id| (id, NodeId(generate_uuid()))).collect(); - document_metadata.clear_selected_nodes(); + selected_nodes.clear_selected_nodes(); responses.add(BroadcastEvent::SelectionChanged); // Copy the selected nodes let copied_nodes = Self::copy_nodes(network, new_ids).collect::>(); // Select the new nodes - document_metadata.add_selected_nodes(copied_nodes.iter().map(|(node_id, _)| *node_id)); + selected_nodes.add_selected_nodes(copied_nodes.iter().map(|(node_id, _)| *node_id)); responses.add(BroadcastEvent::SelectionChanged); for (node_id, mut document_node) in copied_nodes { @@ -707,20 +717,20 @@ impl<'a> MessageHandler> for NodeGrap responses.add(NodeGraphMessage::InsertNode { node_id, document_node }); } - self.update_selected(document_network, document_metadata, responses); + self.update_selected(document_network, selected_nodes, responses); } } NodeGraphMessage::ExitNestedNetwork { depth_of_nesting } => { - document_metadata.clear_selected_nodes(); + selected_nodes.clear_selected_nodes(); responses.add(BroadcastEvent::SelectionChanged); for _ in 0..depth_of_nesting { self.network.pop(); } if let Some(network) = document_network.nested_network(&self.network) { - self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses); + self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } - self.update_selected(document_network, document_metadata, responses); + self.update_selected(document_network, selected_nodes, responses); } NodeGraphMessage::ExposeInput { node_id, input_index, new_exposed } => { let Some(network) = document_network.nested_network(&self.network) else { @@ -761,12 +771,12 @@ impl<'a> MessageHandler> for NodeGrap return; }; - for node_id in document_metadata.selected_nodes() { + for node_id in selected_nodes.selected_nodes() { if let Some(node) = network.nodes.get_mut(node_id) { node.metadata.position += IVec2::new(displacement_x, displacement_y) } } - self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses); + self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } NodeGraphMessage::PasteNodes { serialized_nodes } => { let Some(network) = document_network.nested_network(&self.network) else { @@ -817,21 +827,21 @@ impl<'a> MessageHandler> for NodeGrap responses.add(PortfolioMessage::SubmitGraphRender { document_id }); } NodeGraphMessage::SelectedNodesAdd { nodes } => { - document_metadata.add_selected_nodes(nodes); + selected_nodes.add_selected_nodes(nodes); responses.add(BroadcastEvent::SelectionChanged); } NodeGraphMessage::SelectedNodesRemove { nodes } => { - document_metadata.retain_selected_nodes(|node| !nodes.contains(node)); + selected_nodes.retain_selected_nodes(|node| !nodes.contains(node)); responses.add(BroadcastEvent::SelectionChanged); } NodeGraphMessage::SelectedNodesSet { nodes } => { - document_metadata.set_selected_nodes(nodes); + selected_nodes.set_selected_nodes(nodes); responses.add(BroadcastEvent::SelectionChanged); responses.add(PropertiesPanelMessage::Refresh); } NodeGraphMessage::SendGraph => { if let Some(network) = document_network.nested_network(&self.network) { - self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses); + self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } } NodeGraphMessage::SetInputValue { node_id, input_index, value } => { @@ -858,7 +868,7 @@ impl<'a> MessageHandler> for NodeGrap let structure_changed = node_input.as_node().is_some() || input.as_node().is_some(); *node_input = input; if structure_changed { - load_network_structure(document_network, document_metadata, collapsed); + load_network_structure(document_network, document_metadata, selected_nodes, collapsed); } } } @@ -932,14 +942,14 @@ impl<'a> MessageHandler> for NodeGrap } } - self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses); + self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } NodeGraphMessage::ToggleSelectedHidden => { if let Some(network) = document_network.nested_network(&self.network) { responses.add(DocumentMessage::StartTransaction); - let new_hidden = !document_metadata.selected_nodes().any(|id| network.disabled.contains(id)); - for &node_id in document_metadata.selected_nodes() { + let new_hidden = !selected_nodes.selected_nodes().any(|id| network.disabled.contains(id)); + for &node_id in selected_nodes.selected_nodes() { responses.add(NodeGraphMessage::SetHidden { node_id, hidden: new_hidden }); } } @@ -963,7 +973,7 @@ impl<'a> MessageHandler> for NodeGrap responses.add(NodeGraphMessage::RunDocumentGraph); } } - self.update_selection_action_buttons(document_network, document_metadata, responses); + self.update_selection_action_buttons(document_network, selected_nodes, responses); } NodeGraphMessage::SetName { node_id, name } => { responses.add(DocumentMessage::StartTransaction); @@ -974,7 +984,7 @@ impl<'a> MessageHandler> for NodeGrap if let Some(node) = network.nodes.get_mut(&node_id) { node.alias = name; - self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses); + self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } } } @@ -995,28 +1005,28 @@ impl<'a> MessageHandler> for NodeGrap } } - self.update_selection_action_buttons(document_network, document_metadata, responses); + self.update_selection_action_buttons(document_network, selected_nodes, responses); responses.add(NodeGraphMessage::RunDocumentGraph); } NodeGraphMessage::UpdateNewNodeGraph => { if let Some(network) = document_network.nested_network(&self.network) { - document_metadata.clear_selected_nodes(); + selected_nodes.clear_selected_nodes(); responses.add(BroadcastEvent::SelectionChanged); - self.send_graph(network, graph_view_overlay_open, document_metadata, collapsed, responses); + self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); let node_types = document_node_types::collect_node_types(); responses.add(FrontendMessage::UpdateNodeTypes { node_types }); } - self.update_selected(document_network, document_metadata, responses); + self.update_selected(document_network, selected_nodes, responses); } NodeGraphMessage::UpdateTypes { resolved_types, node_graph_errors } => { self.resolved_types = resolved_types; self.node_graph_errors = node_graph_errors; } } - self.has_selection = document_metadata.has_selected_nodes(); + self.has_selection = selected_nodes.has_selected_nodes(); } fn actions(&self) -> ActionList { diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 75b41b12..f58cfcbe 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2919,7 +2919,7 @@ impl DocumentNodeDefinition { } /// Converts the [DocumentNodeDefinition] type to a [DocumentNode], based on the inputs from the graph (which must be the correct length) and the metadata - pub fn to_document_node(&self, inputs: impl IntoIterator, document_metadata: DocumentNodeMetadata) -> DocumentNode { + pub fn to_document_node(&self, inputs: impl IntoIterator, metadata: DocumentNodeMetadata) -> DocumentNode { let inputs: Vec<_> = inputs.into_iter().collect(); assert_eq!(inputs.len(), self.inputs.len(), "Inputs passed from the graph must be equal to the number required"); DocumentNode { @@ -2927,7 +2927,7 @@ impl DocumentNodeDefinition { inputs, has_primary_output: self.has_primary_output, implementation: self.generate_implementation(), - metadata: document_metadata, + metadata, manual_composition: self.manual_composition.clone(), ..Default::default() } @@ -2935,10 +2935,10 @@ impl DocumentNodeDefinition { /// Converts the [DocumentNodeDefinition] type to a [DocumentNode], using the provided `input_override` and falling back to the default inputs. /// `input_override` does not have to be the correct length. - pub fn to_document_node_default_inputs(&self, input_override: impl IntoIterator>, document_metadata: DocumentNodeMetadata) -> DocumentNode { + pub fn to_document_node_default_inputs(&self, input_override: impl IntoIterator>, metadata: DocumentNodeMetadata) -> DocumentNode { let mut input_override = input_override.into_iter(); let inputs = self.inputs.iter().map(|default| input_override.next().unwrap_or_default().unwrap_or_else(|| default.default.clone())); - self.to_document_node(inputs, document_metadata) + self.to_document_node(inputs, metadata) } /// Converts the [DocumentNodeDefinition] type to a [DocumentNode], completely default diff --git a/editor/src/messages/portfolio/document/overlays/utility_functions.rs b/editor/src/messages/portfolio/document/overlays/utility_functions.rs index 21b6e9a9..1dba4860 100644 --- a/editor/src/messages/portfolio/document/overlays/utility_functions.rs +++ b/editor/src/messages/portfolio/document/overlays/utility_functions.rs @@ -25,7 +25,7 @@ pub fn overlay_canvas_context() -> web_sys::CanvasRenderingContext2d { } pub fn path_overlays(document: &DocumentMessageHandler, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext) { - for layer in document.metadata().selected_layers() { + for layer in document.selected_nodes.selected_layers(document.metadata()) { let Some(subpaths) = get_subpaths(layer, &document.network) else { continue }; let transform = document.metadata().transform_to_viewport(layer); let selected = shape_editor.selected_shape_state.get(&layer); diff --git a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs index 3124e504..bf6b9308 100644 --- a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs +++ b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs @@ -15,10 +15,10 @@ impl<'a> MessageHandler MessageHandler { pub document_name: &'a str, pub document_network: &'a NodeNetwork, pub document_metadata: &'a mut DocumentMetadata, + pub selected_nodes: &'a SelectedNodes, pub node_graph_message_handler: &'a NodeGraphMessageHandler, pub executor: &'a mut NodeGraphExecutor, } diff --git a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs index a679caf6..066ca3ef 100644 --- a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs +++ b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs @@ -1,3 +1,5 @@ +use super::nodes::SelectedNodes; + use graph_craft::document::{DocumentNode, NodeId, NodeNetwork}; use graphene_core::renderer::ClickTarget; use graphene_core::renderer::Quad; @@ -19,7 +21,6 @@ pub struct DocumentMetadata { artboards: HashSet, folders: HashSet, click_targets: HashMap>, - selected_nodes: Vec, /// Transform from document space to viewport space. pub document_to_viewport: DAffine2, } @@ -32,7 +33,6 @@ impl Default for DocumentMetadata { structure: HashMap::from_iter([(LayerNodeIdentifier::ROOT, NodeRelations::default())]), artboards: HashSet::new(), folders: HashSet::new(), - selected_nodes: Vec::new(), document_to_viewport: DAffine2::IDENTITY, } } @@ -52,34 +52,6 @@ impl DocumentMetadata { self.root().decendants(self) } - pub fn all_layers_except_artboards(&self) -> impl Iterator + '_ { - self.all_layers().filter(move |layer| !self.artboards.contains(layer)) - } - - pub fn selected_layers(&self) -> impl Iterator + '_ { - self.all_layers().filter(|layer| self.selected_nodes.contains(&layer.to_node())) - } - - pub fn selected_layers_except_artboards(&self) -> impl Iterator + '_ { - self.selected_layers().filter(move |layer| !self.artboards.contains(layer)) - } - - pub fn selected_layers_contains(&self, layer: LayerNodeIdentifier) -> bool { - self.selected_layers().any(|selected| selected == layer) - } - - pub fn selected_nodes(&self) -> core::slice::Iter<'_, NodeId> { - self.selected_nodes.iter() - } - - pub fn selected_nodes_ref(&self) -> &Vec { - &self.selected_nodes - } - - pub fn has_selected_nodes(&self) -> bool { - !self.selected_nodes.is_empty() - } - pub fn layer_exists(&self, layer: LayerNodeIdentifier) -> bool { self.structure.contains_key(&layer) } @@ -146,14 +118,9 @@ impl DocumentMetadata { self.artboards.contains(&layer) } - /// Filter out non folder layers - pub fn folders<'a>(&'a self, layers: impl Iterator + 'a) -> impl Iterator + 'a { - layers.filter(|layer| self.folders.contains(layer)) - } - /// Folders sorted from most nested to least nested pub fn folders_sorted_by_most_nested(&self, layers: impl Iterator) -> Vec { - let mut folders: Vec<_> = self.folders(layers).collect(); + let mut folders: Vec<_> = layers.filter(|layer| self.folders.contains(layer)).collect(); folders.sort_by_cached_key(|a| std::cmp::Reverse(a.ancestors(self).count())); folders } @@ -164,24 +131,8 @@ impl DocumentMetadata { // ============================================== impl DocumentMetadata { - pub fn retain_selected_nodes(&mut self, f: impl FnMut(&NodeId) -> bool) { - self.selected_nodes.retain(f); - } - - pub fn set_selected_nodes(&mut self, new: Vec) { - self.selected_nodes = new; - } - - pub fn add_selected_nodes(&mut self, iter: impl IntoIterator) { - self.selected_nodes.extend(iter); - } - - pub fn clear_selected_nodes(&mut self) { - self.set_selected_nodes(Vec::new()); - } - /// Loads the structure of layer nodes from a node graph. - pub fn load_structure(&mut self, graph: &NodeNetwork) { + pub fn load_structure(&mut self, graph: &NodeNetwork, selected_nodes: &mut SelectedNodes) { fn first_child_layer<'a>(graph: &'a NodeNetwork, node: &DocumentNode) -> Option<(&'a DocumentNode, NodeId)> { graph.upstream_flow_back_from_nodes(vec![node.inputs[0].as_node()?], true).find(|(node, _)| node.is_layer()) } @@ -224,7 +175,7 @@ impl DocumentMetadata { } } - self.selected_nodes.retain(|node| graph.nodes.contains_key(node)); + selected_nodes.0.retain(|node| graph.nodes.contains_key(node)); self.upstream_transforms.retain(|node, _| graph.nodes.contains_key(node)); self.click_targets.retain(|layer, _| self.structure.contains_key(layer)); } @@ -328,8 +279,9 @@ impl DocumentMetadata { } /// Calculates the selected layer bounds in document space - pub fn selected_bounds_document_space(&self, include_artboards: bool) -> Option<[DVec2; 2]> { - self.selected_layers() + pub fn selected_bounds_document_space(&self, include_artboards: bool, metadata: &DocumentMetadata, selected_nodes: &SelectedNodes) -> Option<[DVec2; 2]> { + selected_nodes + .selected_layers(metadata) .filter(|&layer| include_artboards || !self.is_artboard(layer)) .filter_map(|layer| self.bounding_box_document(layer)) .reduce(Quad::combine_bounds) @@ -388,109 +340,109 @@ impl LayerNodeIdentifier { } /// Access the parent layer if possible - pub fn parent(self, document_metadata: &DocumentMetadata) -> Option { - document_metadata.get_relations(self).and_then(|relations| relations.parent) + pub fn parent(self, metadata: &DocumentMetadata) -> Option { + metadata.get_relations(self).and_then(|relations| relations.parent) } /// Access the previous sibling of this layer (up the Layers panel) - pub fn previous_sibling(self, document_metadata: &DocumentMetadata) -> Option { - document_metadata.get_relations(self).and_then(|relations| relations.previous_sibling) + pub fn previous_sibling(self, metadata: &DocumentMetadata) -> Option { + metadata.get_relations(self).and_then(|relations| relations.previous_sibling) } /// Access the next sibling of this layer (down the Layers panel) - pub fn next_sibling(self, document_metadata: &DocumentMetadata) -> Option { - document_metadata.get_relations(self).and_then(|relations| relations.next_sibling) + pub fn next_sibling(self, metadata: &DocumentMetadata) -> Option { + metadata.get_relations(self).and_then(|relations| relations.next_sibling) } /// Access the first child of this layer (top most in Layers panel) - pub fn first_child(self, document_metadata: &DocumentMetadata) -> Option { - document_metadata.get_relations(self).and_then(|relations| relations.first_child) + pub fn first_child(self, metadata: &DocumentMetadata) -> Option { + metadata.get_relations(self).and_then(|relations| relations.first_child) } /// Access the last child of this layer (bottom most in Layers panel) - pub fn last_child(self, document_metadata: &DocumentMetadata) -> Option { - document_metadata.get_relations(self).and_then(|relations| relations.last_child) + pub fn last_child(self, metadata: &DocumentMetadata) -> Option { + metadata.get_relations(self).and_then(|relations| relations.last_child) } /// Does the layer have children? - pub fn has_children(self, document_metadata: &DocumentMetadata) -> bool { - self.first_child(document_metadata).is_some() + pub fn has_children(self, metadata: &DocumentMetadata) -> bool { + self.first_child(metadata).is_some() } /// Iterator over all direct children (excluding self and recursive children) - pub fn children(self, document_metadata: &DocumentMetadata) -> AxisIter { + pub fn children(self, metadata: &DocumentMetadata) -> AxisIter { AxisIter { - layer_node: self.first_child(document_metadata), + layer_node: self.first_child(metadata), next_node: Self::next_sibling, - document_metadata, + metadata, } } /// All ancestors of this layer, including self, going to the document root - pub fn ancestors(self, document_metadata: &DocumentMetadata) -> AxisIter { + pub fn ancestors(self, metadata: &DocumentMetadata) -> AxisIter { AxisIter { layer_node: Some(self), next_node: Self::parent, - document_metadata, + metadata, } } /// Iterator through all the last children, starting from self - pub fn last_children(self, document_metadata: &DocumentMetadata) -> AxisIter { + pub fn last_children(self, metadata: &DocumentMetadata) -> AxisIter { AxisIter { layer_node: Some(self), next_node: Self::last_child, - document_metadata, + metadata, } } /// Iterator through all decendants, including recursive children (not including self) - pub fn decendants(self, document_metadata: &DocumentMetadata) -> DecendantsIter { + pub fn decendants(self, metadata: &DocumentMetadata) -> DecendantsIter { DecendantsIter { - front: self.first_child(document_metadata), - back: self.last_child(document_metadata).and_then(|child| child.last_children(document_metadata).last()), - document_metadata, + front: self.first_child(metadata), + back: self.last_child(metadata).and_then(|child| child.last_children(metadata).last()), + metadata, } } /// Add a child towards the top of the Layers panel - pub fn push_front_child(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) { - assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer"); - let parent = document_metadata.get_structure_mut(self); + pub fn push_front_child(self, metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) { + assert!(!metadata.structure.contains_key(&new), "Cannot add already existing layer"); + let parent = metadata.get_structure_mut(self); let old_first_child = parent.first_child.replace(new); parent.last_child.get_or_insert(new); if let Some(old_first_child) = old_first_child { - document_metadata.get_structure_mut(old_first_child).previous_sibling = Some(new); + metadata.get_structure_mut(old_first_child).previous_sibling = Some(new); } - document_metadata.get_structure_mut(new).next_sibling = old_first_child; - document_metadata.get_structure_mut(new).parent = Some(self); + metadata.get_structure_mut(new).next_sibling = old_first_child; + metadata.get_structure_mut(new).parent = Some(self); } /// Add a child towards the bottom of the Layers panel - pub fn push_child(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) { - assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer"); - let parent = document_metadata.get_structure_mut(self); + pub fn push_child(self, metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) { + assert!(!metadata.structure.contains_key(&new), "Cannot add already existing layer"); + let parent = metadata.get_structure_mut(self); let old_last_child = parent.last_child.replace(new); parent.first_child.get_or_insert(new); if let Some(old_last_child) = old_last_child { - document_metadata.get_structure_mut(old_last_child).next_sibling = Some(new); + metadata.get_structure_mut(old_last_child).next_sibling = Some(new); } - document_metadata.get_structure_mut(new).previous_sibling = old_last_child; - document_metadata.get_structure_mut(new).parent = Some(self); + metadata.get_structure_mut(new).previous_sibling = old_last_child; + metadata.get_structure_mut(new).parent = Some(self); } /// Add sibling above in the Layers panel - pub fn add_before(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) { - assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer"); - document_metadata.get_structure_mut(new).next_sibling = Some(self); - document_metadata.get_structure_mut(new).parent = self.parent(document_metadata); - let old_previous_sibling = document_metadata.get_structure_mut(self).previous_sibling.replace(new); + pub fn add_before(self, metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) { + assert!(!metadata.structure.contains_key(&new), "Cannot add already existing layer"); + metadata.get_structure_mut(new).next_sibling = Some(self); + metadata.get_structure_mut(new).parent = self.parent(metadata); + let old_previous_sibling = metadata.get_structure_mut(self).previous_sibling.replace(new); if let Some(old_previous_sibling) = old_previous_sibling { - document_metadata.get_structure_mut(old_previous_sibling).next_sibling = Some(new); - document_metadata.get_structure_mut(new).previous_sibling = Some(old_previous_sibling); + metadata.get_structure_mut(old_previous_sibling).next_sibling = Some(new); + metadata.get_structure_mut(new).previous_sibling = Some(old_previous_sibling); } else if let Some(structure) = self - .parent(document_metadata) - .map(|parent| document_metadata.get_structure_mut(parent)) + .parent(metadata) + .map(|parent| metadata.get_structure_mut(parent)) .filter(|structure| structure.first_child == Some(self)) { structure.first_child = Some(new); @@ -498,17 +450,17 @@ impl LayerNodeIdentifier { } /// Add sibling below in the Layers panel - pub fn add_after(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) { - assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer"); - document_metadata.get_structure_mut(new).previous_sibling = Some(self); - document_metadata.get_structure_mut(new).parent = self.parent(document_metadata); - let old_next_sibling = document_metadata.get_structure_mut(self).next_sibling.replace(new); + pub fn add_after(self, metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) { + assert!(!metadata.structure.contains_key(&new), "Cannot add already existing layer"); + metadata.get_structure_mut(new).previous_sibling = Some(self); + metadata.get_structure_mut(new).parent = self.parent(metadata); + let old_next_sibling = metadata.get_structure_mut(self).next_sibling.replace(new); if let Some(old_next_sibling) = old_next_sibling { - document_metadata.get_structure_mut(old_next_sibling).previous_sibling = Some(new); - document_metadata.get_structure_mut(new).next_sibling = Some(old_next_sibling); + metadata.get_structure_mut(old_next_sibling).previous_sibling = Some(new); + metadata.get_structure_mut(new).next_sibling = Some(old_next_sibling); } else if let Some(structure) = self - .parent(document_metadata) - .map(|parent| document_metadata.get_structure_mut(parent)) + .parent(metadata) + .map(|parent| metadata.get_structure_mut(parent)) .filter(|structure| structure.last_child == Some(self)) { structure.last_child = Some(new); @@ -516,18 +468,18 @@ impl LayerNodeIdentifier { } /// Delete layer and all children - pub fn delete(self, document_metadata: &mut DocumentMetadata) { - let previous_sibling = self.previous_sibling(document_metadata); - let next_sibling = self.next_sibling(document_metadata); + pub fn delete(self, metadata: &mut DocumentMetadata) { + let previous_sibling = self.previous_sibling(metadata); + let next_sibling = self.next_sibling(metadata); - if let Some(previous_sibling) = previous_sibling.map(|node| document_metadata.get_structure_mut(node)) { + if let Some(previous_sibling) = previous_sibling.map(|node| metadata.get_structure_mut(node)) { previous_sibling.next_sibling = next_sibling; } - if let Some(next_sibling) = next_sibling.map(|node| document_metadata.get_structure_mut(node)) { + if let Some(next_sibling) = next_sibling.map(|node| metadata.get_structure_mut(node)) { next_sibling.previous_sibling = previous_sibling; } - let mut parent = self.parent(document_metadata).map(|parent| document_metadata.get_structure_mut(parent)); + let mut parent = self.parent(metadata).map(|parent| metadata.get_structure_mut(parent)); if let Some(structure) = parent.as_mut().filter(|structure| structure.first_child == Some(self)) { structure.first_child = next_sibling; } @@ -536,22 +488,22 @@ impl LayerNodeIdentifier { } let mut delete = vec![self]; - delete.extend(self.decendants(document_metadata)); + delete.extend(self.decendants(metadata)); for node in delete { - document_metadata.structure.remove(&node); + metadata.structure.remove(&node); } } - pub fn exists(&self, document_metadata: &DocumentMetadata) -> bool { - document_metadata.get_relations(*self).is_some() + pub fn exists(&self, metadata: &DocumentMetadata) -> bool { + metadata.get_relations(*self).is_some() } - pub fn starts_with(&self, other: Self, document_metadata: &DocumentMetadata) -> bool { - self.ancestors(document_metadata).any(|parent| parent == other) + pub fn starts_with(&self, other: Self, metadata: &DocumentMetadata) -> bool { + self.ancestors(metadata).any(|parent| parent == other) } - pub fn child_of_root(&self, document_metadata: &DocumentMetadata) -> Self { - self.ancestors(document_metadata) + pub fn child_of_root(&self, metadata: &DocumentMetadata) -> Self { + self.ancestors(metadata) .filter(|&layer| layer != LayerNodeIdentifier::ROOT) .last() .expect("There should be a layer before the root") @@ -567,7 +519,7 @@ impl LayerNodeIdentifier { pub struct AxisIter<'a> { pub layer_node: Option, pub next_node: fn(LayerNodeIdentifier, &DocumentMetadata) -> Option, - pub document_metadata: &'a DocumentMetadata, + pub metadata: &'a DocumentMetadata, } impl<'a> Iterator for AxisIter<'a> { @@ -575,7 +527,7 @@ impl<'a> Iterator for AxisIter<'a> { fn next(&mut self) -> Option { let layer_node = self.layer_node.take(); - self.layer_node = layer_node.and_then(|node| (self.next_node)(node, self.document_metadata)); + self.layer_node = layer_node.and_then(|node| (self.next_node)(node, self.metadata)); layer_node } } @@ -588,7 +540,7 @@ impl<'a> Iterator for AxisIter<'a> { pub struct DecendantsIter<'a> { front: Option, back: Option, - document_metadata: &'a DocumentMetadata, + metadata: &'a DocumentMetadata, } impl<'a> Iterator for DecendantsIter<'a> { @@ -602,8 +554,8 @@ impl<'a> Iterator for DecendantsIter<'a> { let layer_node = self.front.take(); if let Some(layer_node) = layer_node { self.front = layer_node - .first_child(self.document_metadata) - .or_else(|| layer_node.ancestors(self.document_metadata).find_map(|ancestor| ancestor.next_sibling(self.document_metadata))); + .first_child(self.metadata) + .or_else(|| layer_node.ancestors(self.metadata).find_map(|ancestor| ancestor.next_sibling(self.metadata))); } layer_node } @@ -618,9 +570,9 @@ impl<'a> DoubleEndedIterator for DecendantsIter<'a> { let layer_node = self.back.take(); if let Some(layer_node) = layer_node { self.back = layer_node - .previous_sibling(self.document_metadata) - .and_then(|sibling| sibling.last_children(self.document_metadata).last()) - .or_else(|| layer_node.parent(self.document_metadata)); + .previous_sibling(self.metadata) + .and_then(|sibling| sibling.last_children(self.metadata).last()) + .or_else(|| layer_node.parent(self.metadata)); } layer_node @@ -659,47 +611,47 @@ pub fn is_folder(layer: LayerNodeIdentifier, network: &NodeNetwork) -> bool { #[test] fn test_tree() { - let mut document_metadata = DocumentMetadata::default(); - let root = document_metadata.root(); - let document_metadata = &mut document_metadata; - root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(3))); - assert_eq!(root.children(document_metadata).collect::>(), vec![LayerNodeIdentifier::new_unchecked(NodeId(3))]); - root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(6))); - assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); - assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); - LayerNodeIdentifier::new_unchecked(NodeId(3)).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(4))); - LayerNodeIdentifier::new_unchecked(NodeId(3)).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(2))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(5))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(9))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(8))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(7))); - root.push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(1))); + let mut metadata = DocumentMetadata::default(); + let root = metadata.root(); + let metadata = &mut metadata; + root.push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(3))); + assert_eq!(root.children(metadata).collect::>(), vec![LayerNodeIdentifier::new_unchecked(NodeId(3))]); + root.push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(6))); + assert_eq!(root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); + assert_eq!(root.decendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); + LayerNodeIdentifier::new_unchecked(NodeId(3)).add_after(metadata, LayerNodeIdentifier::new_unchecked(NodeId(4))); + LayerNodeIdentifier::new_unchecked(NodeId(3)).add_before(metadata, LayerNodeIdentifier::new_unchecked(NodeId(2))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).add_before(metadata, LayerNodeIdentifier::new_unchecked(NodeId(5))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).add_after(metadata, LayerNodeIdentifier::new_unchecked(NodeId(9))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(8))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).push_front_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(7))); + root.push_front_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(1))); assert_eq!( - root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), + root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(9)] ); assert_eq!( - root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), + root.decendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(7), NodeId(8), NodeId(9)] ); assert_eq!( - root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), + root.decendants(metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), vec![NodeId(9), NodeId(8), NodeId(7), NodeId(6), NodeId(5), NodeId(4), NodeId(3), NodeId(2), NodeId(1)] ); - assert!(root.children(document_metadata).all(|child| child.parent(document_metadata) == Some(root))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).delete(document_metadata); - LayerNodeIdentifier::new_unchecked(NodeId(1)).delete(document_metadata); - LayerNodeIdentifier::new_unchecked(NodeId(9)).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(10))); + assert!(root.children(metadata).all(|child| child.parent(metadata) == Some(root))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).delete(metadata); + LayerNodeIdentifier::new_unchecked(NodeId(1)).delete(metadata); + LayerNodeIdentifier::new_unchecked(NodeId(9)).push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(10))); assert_eq!( - root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), + root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9)] ); assert_eq!( - root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), + root.decendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9), NodeId(10)] ); assert_eq!( - root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), + root.decendants(metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), vec![NodeId(10), NodeId(9), NodeId(5), NodeId(4), NodeId(3), NodeId(2)] ); } diff --git a/editor/src/messages/portfolio/document/utility_types/layer_panel.rs b/editor/src/messages/portfolio/document/utility_types/layer_panel.rs deleted file mode 100644 index b4f04730..00000000 --- a/editor/src/messages/portfolio/document/utility_types/layer_panel.rs +++ /dev/null @@ -1,52 +0,0 @@ -use graph_craft::document::NodeId; - -use serde::ser::SerializeStruct; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)] -pub struct RawBuffer(Vec); - -impl From<&[u64]> for RawBuffer { - fn from(iter: &[u64]) -> Self { - let v_from_raw: Vec = iter.iter().flat_map(|x| x.to_ne_bytes()).collect(); - Self(v_from_raw) - } -} -#[derive(Debug, Clone, Deserialize, PartialEq, Eq, specta::Type)] -pub struct JsRawBuffer(Vec); - -impl From for JsRawBuffer { - fn from(buffer: RawBuffer) -> Self { - Self(buffer.0) - } -} -impl Serialize for JsRawBuffer { - fn serialize(&self, serializer: S) -> Result { - let mut buffer = serializer.serialize_struct("Buffer", 2)?; - buffer.serialize_field("pointer", &(self.0.as_ptr() as usize))?; - buffer.serialize_field("length", &(self.0.len()))?; - buffer.end() - } -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)] -pub enum LayerClassification { - #[default] - Folder, - Artboard, - Layer, -} - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)] -pub struct LayerPanelEntry { - pub id: NodeId, - pub name: String, - pub tooltip: String, - #[serde(rename = "layerClassification")] - pub layer_classification: LayerClassification, - pub expanded: bool, - pub disabled: bool, - #[serde(rename = "parentId")] - pub parent_id: Option, - pub depth: usize, -} diff --git a/editor/src/messages/portfolio/document/utility_types/mod.rs b/editor/src/messages/portfolio/document/utility_types/mod.rs index 1417ea9a..af3f1b43 100644 --- a/editor/src/messages/portfolio/document/utility_types/mod.rs +++ b/editor/src/messages/portfolio/document/utility_types/mod.rs @@ -1,6 +1,6 @@ pub mod clipboards; pub mod document_metadata; pub mod error; -pub mod layer_panel; pub mod misc; +pub mod nodes; pub mod transformation; diff --git a/editor/src/messages/portfolio/document/utility_types/nodes.rs b/editor/src/messages/portfolio/document/utility_types/nodes.rs new file mode 100644 index 00000000..01625e12 --- /dev/null +++ b/editor/src/messages/portfolio/document/utility_types/nodes.rs @@ -0,0 +1,110 @@ +use graph_craft::document::{NodeId, NodeNetwork}; + +use serde::ser::SerializeStruct; +use serde::{Deserialize, Serialize}; + +use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)] +pub struct RawBuffer(Vec); + +impl From<&[u64]> for RawBuffer { + fn from(iter: &[u64]) -> Self { + let v_from_raw: Vec = iter.iter().flat_map(|x| x.to_ne_bytes()).collect(); + Self(v_from_raw) + } +} +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, specta::Type)] +pub struct JsRawBuffer(Vec); + +impl From for JsRawBuffer { + fn from(buffer: RawBuffer) -> Self { + Self(buffer.0) + } +} +impl Serialize for JsRawBuffer { + fn serialize(&self, serializer: S) -> Result { + let mut buffer = serializer.serialize_struct("Buffer", 2)?; + buffer.serialize_field("pointer", &(self.0.as_ptr() as usize))?; + buffer.serialize_field("length", &(self.0.len()))?; + buffer.end() + } +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)] +pub enum LayerClassification { + #[default] + Folder, + Artboard, + Layer, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, specta::Type)] +pub struct LayerPanelEntry { + pub id: NodeId, + pub name: String, + pub tooltip: String, + #[serde(rename = "layerClassification")] + pub layer_classification: LayerClassification, + pub expanded: bool, + pub disabled: bool, + #[serde(rename = "parentId")] + pub parent_id: Option, + pub depth: usize, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, specta::Type)] +pub struct SelectedNodes(pub Vec); + +impl SelectedNodes { + pub fn layer_visible(&self, layer: LayerNodeIdentifier, network: &NodeNetwork, metadata: &DocumentMetadata) -> bool { + !layer.ancestors(metadata).any(|layer| network.disabled.contains(&layer.to_node())) + } + + pub fn selected_visible_layers<'a>(&'a self, network: &'a NodeNetwork, metadata: &'a DocumentMetadata) -> impl Iterator + '_ { + self.selected_layers(metadata).filter(move |&layer| self.layer_visible(layer, network, metadata)) + } + + pub fn selected_layers<'a>(&'a self, metadata: &'a DocumentMetadata) -> impl Iterator + '_ { + metadata.all_layers().filter(|layer| self.0.contains(&layer.to_node())) + } + + pub fn selected_layers_except_artboards<'a>(&'a self, metadata: &'a DocumentMetadata) -> impl Iterator + '_ { + self.selected_layers(metadata).filter(move |&layer| !metadata.is_artboard(layer)) + } + + pub fn selected_layers_contains(&self, layer: LayerNodeIdentifier, metadata: &DocumentMetadata) -> bool { + self.selected_layers(metadata).any(|selected| selected == layer) + } + + pub fn selected_nodes(&self) -> core::slice::Iter<'_, NodeId> { + self.0.iter() + } + + pub fn selected_nodes_ref(&self) -> &Vec { + &self.0 + } + + pub fn has_selected_nodes(&self) -> bool { + !self.0.is_empty() + } + + pub fn retain_selected_nodes(&mut self, f: impl FnMut(&NodeId) -> bool) { + self.0.retain(f); + } + + pub fn set_selected_nodes(&mut self, new: Vec) { + self.0 = new; + } + + pub fn add_selected_nodes(&mut self, iter: impl IntoIterator) { + self.0.extend(iter); + } + + pub fn clear_selected_nodes(&mut self) { + self.set_selected_nodes(Vec::new()); + } +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, specta::Type)] +pub struct CollapsedLayers(pub Vec); diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 1dec2986..433862db 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -163,7 +163,10 @@ impl MessageHandler| { - for layer_path in active_document.metadata().shallowest_unique_layers(active_document.metadata().selected_layers()) { + for layer_path in active_document + .metadata() + .shallowest_unique_layers(active_document.selected_nodes.selected_layers(active_document.metadata())) + { let Some(layer) = layer_path.last().copied() else { continue; }; @@ -184,7 +187,7 @@ impl MessageHandler) { - for layer in document.selected_visible_layers() { + for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { let transform = Self::get_layer_pivot_transform(layer, document); let pivot = transform.inverse().transform_point2(position); // Only update the pivot when computed position is finite. Infinite can happen when scale is 0. diff --git a/editor/src/messages/tool/tool_messages/brush_tool.rs b/editor/src/messages/tool/tool_messages/brush_tool.rs index 1e5ec66d..0f81a6f4 100644 --- a/editor/src/messages/tool/tool_messages/brush_tool.rs +++ b/editor/src/messages/tool/tool_messages/brush_tool.rs @@ -266,10 +266,10 @@ impl BrushToolData { fn load_existing_strokes(&mut self, document: &DocumentMessageHandler) -> Option { self.transform = DAffine2::IDENTITY; - if document.metadata().selected_layers().count() != 1 { + if document.selected_nodes.selected_layers(document.metadata()).count() != 1 { return None; } - let Some(layer) = document.metadata().selected_layers().next() else { + let Some(layer) = document.selected_nodes.selected_layers(document.metadata()).next() else { return None; }; diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index 1f55d0a4..a84521c5 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -295,7 +295,7 @@ impl Fsm for GradientToolFsmState { (_, GradientToolMessage::Overlays(mut overlay_context)) => { let selected = tool_data.selected_gradient.as_ref(); - for layer in document.selected_visible_layers() { + for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { let Some(gradient) = get_gradient(layer, &document.network) else { continue }; let transform = gradient_space_transform(layer, document); let dragging = selected.filter(|selected| selected.layer == layer).map(|selected| selected.dragging); @@ -366,7 +366,7 @@ impl Fsm for GradientToolFsmState { self } (_, GradientToolMessage::InsertStop) => { - for layer in document.selected_visible_layers() { + for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { let Some(mut gradient) = get_gradient(layer, &document.network) else { continue }; let transform = gradient_space_transform(layer, document); @@ -407,7 +407,7 @@ impl Fsm for GradientToolFsmState { let tolerance = (MANIPULATOR_GROUP_MARKER_SIZE * 2.).powi(2); let mut dragging = false; - for layer in document.selected_visible_layers() { + for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { let Some(gradient) = get_gradient(layer, &document.network) else { continue }; let transform = gradient_space_transform(layer, document); @@ -448,7 +448,7 @@ impl Fsm for GradientToolFsmState { // Apply the gradient to the selected layer if let Some(layer) = selected_layer { - if !document.metadata().selected_layers_contains(layer) { + if !document.selected_nodes.selected_layers_contains(layer, document.metadata()) { let nodes = vec![layer.to_node()]; responses.add(NodeGraphMessage::SelectedNodesSet { nodes }); diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 7f859e4a..5d377410 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -223,7 +223,7 @@ impl PathToolData { let _selected_layers = shape_editor.selected_layers().cloned().collect::>(); // Select the first point within the threshold (in pixels) - if let Some(selected_points) = shape_editor.select_point(&document.network, &document.document_metadata, input.mouse.position, SELECTION_THRESHOLD, shift) { + if let Some(selected_points) = shape_editor.select_point(&document.network, &document.metadata, input.mouse.position, SELECTION_THRESHOLD, shift) { self.start_dragging_point(selected_points, input, document, responses); responses.add(OverlaysMessage::Draw); @@ -298,7 +298,7 @@ impl PathToolData { // Move the selected points with the mouse let snapped_position = self.snap_manager.snap_position(responses, document, input.mouse.position); - shape_editor.move_selected_points(&document.network, &document.document_metadata, snapped_position - self.previous_mouse_position, shift, responses); + shape_editor.move_selected_points(&document.network, &document.metadata, snapped_position - self.previous_mouse_position, shift, responses); self.previous_mouse_position = snapped_position; } } @@ -316,7 +316,7 @@ impl Fsm for PathToolFsmState { match (self, event) { (_, PathToolMessage::SelectionChanged) => { // Set the newly targeted layers to visible - let target_layers = document.metadata().selected_layers().collect(); + let target_layers = document.selected_nodes.selected_layers(document.metadata()).collect(); shape_editor.set_selected_layers(target_layers); responses.add(OverlaysMessage::Draw); @@ -362,12 +362,7 @@ impl Fsm for PathToolFsmState { if tool_data.drag_start_pos == tool_data.previous_mouse_position { responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![] }); } else { - shape_editor.select_all_in_quad( - &document.network, - &document.document_metadata, - [tool_data.drag_start_pos, tool_data.previous_mouse_position], - !shift_pressed, - ); + shape_editor.select_all_in_quad(&document.network, &document.metadata, [tool_data.drag_start_pos, tool_data.previous_mouse_position], !shift_pressed); } responses.add(OverlaysMessage::Draw); @@ -381,12 +376,7 @@ impl Fsm for PathToolFsmState { if tool_data.drag_start_pos == tool_data.previous_mouse_position { responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![] }); } else { - shape_editor.select_all_in_quad( - &document.network, - &document.document_metadata, - [tool_data.drag_start_pos, tool_data.previous_mouse_position], - !shift_pressed, - ); + shape_editor.select_all_in_quad(&document.network, &document.metadata, [tool_data.drag_start_pos, tool_data.previous_mouse_position], !shift_pressed); } responses.add(OverlaysMessage::Draw); responses.add(PathToolMessage::SelectedPointUpdated); @@ -398,16 +388,16 @@ impl Fsm for PathToolFsmState { let shift_pressed = input.keyboard.get(shift_mirror_distance as usize); let nearest_point = shape_editor - .find_nearest_point_indices(&document.network, &document.document_metadata, input.mouse.position, SELECTION_THRESHOLD) + .find_nearest_point_indices(&document.network, &document.metadata, input.mouse.position, SELECTION_THRESHOLD) .map(|(_, nearest_point)| nearest_point); - shape_editor.delete_selected_handles_with_zero_length(&document.network, &document.document_metadata, &tool_data.opposing_handle_lengths, responses); + shape_editor.delete_selected_handles_with_zero_length(&document.network, &document.metadata, &tool_data.opposing_handle_lengths, responses); if tool_data.drag_start_pos.distance(input.mouse.position) <= DRAG_THRESHOLD && !shift_pressed { let clicked_selected = shape_editor.selected_points().any(|&point| nearest_point == Some(point)); if clicked_selected { shape_editor.deselect_all(); - shape_editor.select_point(&document.network, &document.document_metadata, input.mouse.position, SELECTION_THRESHOLD, false); + shape_editor.select_point(&document.network, &document.metadata, input.mouse.position, SELECTION_THRESHOLD, false); responses.add(OverlaysMessage::Draw); } } @@ -428,9 +418,9 @@ impl Fsm for PathToolFsmState { } (_, PathToolMessage::InsertPoint) => { // First we try and flip the sharpness (if they have clicked on an anchor) - if !shape_editor.flip_sharp(&document.network, &document.document_metadata, input.mouse.position, SELECTION_TOLERANCE, responses) { + if !shape_editor.flip_sharp(&document.network, &document.metadata, input.mouse.position, SELECTION_TOLERANCE, responses) { // If not, then we try and split the path that may have been clicked upon - shape_editor.split(&document.network, &document.document_metadata, input.mouse.position, SELECTION_TOLERANCE, responses); + shape_editor.split(&document.network, &document.metadata, input.mouse.position, SELECTION_TOLERANCE, responses); } responses.add(PathToolMessage::SelectedPointUpdated); @@ -443,7 +433,7 @@ impl Fsm for PathToolFsmState { } (_, PathToolMessage::PointerMove { .. }) => self, (_, PathToolMessage::NudgeSelectedPoints { delta_x, delta_y }) => { - shape_editor.move_selected_points(&document.network, &document.document_metadata, (delta_x, delta_y).into(), true, responses); + shape_editor.move_selected_points(&document.network, &document.metadata, (delta_x, delta_y).into(), true, responses); PathToolFsmState::Ready } @@ -454,18 +444,18 @@ impl Fsm for PathToolFsmState { } (_, PathToolMessage::SelectedPointXChanged { new_x }) => { if let Some(&SingleSelectedPoint { coordinates, id, layer, .. }) = tool_data.selection_status.as_one() { - shape_editor.reposition_control_point(&id, responses, &document.network, &document.document_metadata, DVec2::new(new_x, coordinates.y), layer); + shape_editor.reposition_control_point(&id, responses, &document.network, &document.metadata, DVec2::new(new_x, coordinates.y), layer); } PathToolFsmState::Ready } (_, PathToolMessage::SelectedPointYChanged { new_y }) => { if let Some(&SingleSelectedPoint { coordinates, id, layer, .. }) = tool_data.selection_status.as_one() { - shape_editor.reposition_control_point(&id, responses, &document.network, &document.document_metadata, DVec2::new(coordinates.x, new_y), layer); + shape_editor.reposition_control_point(&id, responses, &document.network, &document.metadata, DVec2::new(coordinates.x, new_y), layer); } PathToolFsmState::Ready } (_, PathToolMessage::SelectedPointUpdated) => { - tool_data.selection_status = get_selection_status(&document.network, &document.document_metadata, shape_editor); + tool_data.selection_status = get_selection_status(&document.network, &document.metadata, shape_editor); self } (_, PathToolMessage::ManipulatorAngleMakeSmooth) => { diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index 420d78bf..0c2912bd 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -720,7 +720,7 @@ fn should_extend(document: &DocumentMessageHandler, pos: DVec2, tolerance: f64) let mut best = None; let mut best_distance_squared = tolerance * tolerance; - for layer in document.metadata().selected_layers() { + for layer in document.selected_nodes.selected_layers(document.metadata()) { let viewspace = document.metadata().transform_to_viewport(layer); let subpaths = get_subpaths(layer, &document.network)?; diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index d0c5ced4..1f996d40 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -381,27 +381,32 @@ impl Fsm for SelectToolFsmState { }; match (self, event) { (_, SelectToolMessage::Overlays(mut overlay_context)) => { - let selected_layers_count = document.metadata().selected_layers().count(); + let selected_layers_count = document.selected_nodes.selected_layers(document.metadata()).count(); tool_data.selected_layers_changed = selected_layers_count != tool_data.selected_layers_count; tool_data.selected_layers_count = selected_layers_count; // Outline selected layers - for layer in document.selected_visible_layers() { + for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { overlay_context.outline(document.metadata().layer_outline(layer), document.metadata().transform_to_viewport(layer)); } // Get the layer the user is hovering over let click = document.click(input.mouse.position, &document.network); - let not_selected_click = click.filter(|&hovered_layer| !document.metadata().selected_layers_contains(hovered_layer)); + let not_selected_click = click.filter(|&hovered_layer| !document.selected_nodes.selected_layers_contains(hovered_layer, document.metadata())); if let Some(layer) = not_selected_click { overlay_context.outline(document.metadata().layer_outline(layer), document.metadata().transform_to_viewport(layer)); } // Update bounds - let transform = document.selected_visible_layers().next().map(|layer| document.metadata().transform_to_viewport(layer)); + let transform = document + .selected_nodes + .selected_visible_layers(document.network(), document.metadata()) + .next() + .map(|layer| document.metadata().transform_to_viewport(layer)); let transform = transform.unwrap_or(DAffine2::IDENTITY); let bounds = document - .selected_visible_layers() + .selected_nodes + .selected_visible_layers(document.network(), document.metadata()) .filter_map(|layer| { document .metadata() @@ -462,7 +467,7 @@ impl Fsm for SelectToolFsmState { .map(|bounding_box| bounding_box.check_rotate(input.mouse.position)) .unwrap_or_default(); - let mut selected: Vec<_> = document.selected_visible_layers().collect(); + let mut selected: Vec<_> = document.selected_nodes.selected_visible_layers(document.network(), document.metadata()).collect(); let intersection = document.click(input.mouse.position, &document.network); // If the user is dragging the bounding box bounds, go into ResizingBounds mode. @@ -491,7 +496,7 @@ impl Fsm for SelectToolFsmState { &tool_data.layers_dragging, responses, &document.network, - &document.document_metadata, + &document.metadata, None, &ToolType::Select, ); @@ -510,7 +515,7 @@ impl Fsm for SelectToolFsmState { &selected, responses, &document.network, - &document.document_metadata, + &document.metadata, None, &ToolType::Select, ); @@ -630,7 +635,7 @@ impl Fsm for SelectToolFsmState { selected, responses, &document.network, - &document.document_metadata, + &document.metadata, None, &ToolType::Select, ); @@ -665,7 +670,7 @@ impl Fsm for SelectToolFsmState { &tool_data.layers_dragging, responses, &document.network, - &document.document_metadata, + &document.metadata, None, &ToolType::Select, ); @@ -723,7 +728,11 @@ impl Fsm for SelectToolFsmState { let intersection = document.intersect_quad(quad, &document.network); if let Some(path) = intersection.last() { - let replacement_selected_layers: Vec<_> = document.metadata().selected_layers().filter(|&layer| !path.starts_with(layer, document.metadata())).collect(); + let replacement_selected_layers: Vec<_> = document + .selected_nodes + .selected_layers(document.metadata()) + .filter(|&layer| !path.starts_with(layer, document.metadata())) + .collect(); tool_data.layers_dragging.clear(); tool_data.layers_dragging.extend(replacement_selected_layers.iter()); @@ -791,7 +800,7 @@ impl Fsm for SelectToolFsmState { (SelectToolFsmState::DrawingBox, SelectToolMessage::DragStop { .. } | SelectToolMessage::Enter) => { let quad = tool_data.selection_quad(); let new_selected: HashSet<_> = document.intersect_quad(quad, &document.network).collect(); - let current_selected: HashSet<_> = document.metadata().selected_layers().collect(); + let current_selected: HashSet<_> = document.selected_nodes.selected_layers(document.metadata()).collect(); if new_selected != current_selected { tool_data.layers_dragging = new_selected.into_iter().collect(); responses.add(DocumentMessage::StartTransaction); @@ -804,7 +813,7 @@ impl Fsm for SelectToolFsmState { SelectToolFsmState::Ready } (SelectToolFsmState::Ready, SelectToolMessage::Enter) => { - let mut selected_layers = document.metadata().selected_layers(); + let mut selected_layers = document.selected_nodes.selected_layers(document.metadata()); if let Some(layer) = selected_layers.next() { // Check that only one layer is selected @@ -832,7 +841,7 @@ impl Fsm for SelectToolFsmState { &tool_data.layers_dragging, responses, &document.network, - &document.document_metadata, + &document.metadata, None, &ToolType::Select, ); @@ -908,7 +917,9 @@ impl Fsm for SelectToolFsmState { fn drag_shallowest_manipulation(responses: &mut VecDeque, selected: Vec, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) { let layer = selected[0]; - let ancestor = layer.ancestors(document.metadata()).find(|&ancestor| document.metadata().selected_layers_contains(ancestor)); + let ancestor = layer + .ancestors(document.metadata()) + .find(|&ancestor| document.selected_nodes.selected_layers_contains(ancestor, document.metadata())); let new_selected = ancestor.unwrap_or_else(|| layer.child_of_root(document.metadata())); @@ -932,15 +943,16 @@ fn drag_deepest_manipulation(responses: &mut VecDeque, mut selected: Ve } fn edit_layer_shallowest_manipulation(document: &DocumentMessageHandler, layer: LayerNodeIdentifier, responses: &mut VecDeque) { - if document.metadata().selected_layers_contains(layer) { + if document.selected_nodes.selected_layers_contains(layer, document.metadata()) { responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Path }); return; } - let Some(new_selected) = layer - .ancestors(document.metadata()) - .find(|ancestor| ancestor.parent(document.metadata()).is_some_and(|parent| document.metadata().selected_layers_contains(parent))) - else { + let Some(new_selected) = layer.ancestors(document.metadata()).find(|ancestor| { + ancestor + .parent(document.metadata()) + .is_some_and(|parent| document.selected_nodes.selected_layers_contains(parent, document.metadata())) + }) else { return; }; diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 2144aa48..2949d11b 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -344,9 +344,9 @@ impl TextToolData { } fn can_edit_selected(document: &DocumentMessageHandler) -> Option { - let mut selected_layers = document.metadata().selected_layers(); - + let mut selected_layers = document.selected_nodes.selected_layers(document.metadata()); let layer = selected_layers.next()?; + // Check that only one layer is selected if selected_layers.next().is_some() { return None; @@ -392,7 +392,7 @@ impl Fsm for TextToolFsmState { TextToolFsmState::Editing } (_, TextToolMessage::Overlays(mut overlay_context)) => { - for layer in document.metadata().selected_layers() { + for layer in document.selected_nodes.selected_layers(document.metadata()) { let Some((text, font, font_size)) = graph_modification_utils::get_text(layer, &document.network) else { continue; }; diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs index a5b04ac0..0773e30b 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs @@ -48,7 +48,7 @@ impl<'a> MessageHandler> for TransformL let using_path_tool = tool_data.active_tool_type == ToolType::Path; - let selected_layers = document.metadata().selected_layers().collect::>(); + let selected_layers = document.selected_nodes.selected_layers(document.metadata()).collect::>(); let mut selected = Selected::new( &mut self.original_transforms, @@ -56,7 +56,7 @@ impl<'a> MessageHandler> for TransformL &selected_layers, responses, &document.network, - &document.document_metadata, + &document.metadata, Some(shape_editor), &tool_data.active_tool_type, ); @@ -222,7 +222,7 @@ impl<'a> MessageHandler> for TransformL self.mouse_position = input.mouse.position; } SelectionChanged => { - let target_layers = document.metadata().selected_layers().collect(); + let target_layers = document.selected_nodes.selected_layers(document.metadata()).collect(); shape_editor.set_selected_layers(target_layers); } TypeBackspace => self.transform_operation.grs_typed(self.typing.type_backspace(), &mut selected, self.snap), diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index 55aa52dc..254d220b 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -449,7 +449,7 @@ impl NodeGraphExecutor { let render_config = RenderConfig { viewport: Footprint { - transform: document.document_metadata.document_to_viewport, + transform: document.metadata.document_to_viewport, resolution: viewport_resolution, ..Default::default() }, @@ -477,7 +477,9 @@ impl NodeGraphExecutor { // Calculate the bounding box of the region to be exported let bounds = match export_config.bounds { ExportBounds::AllArtwork => document.metadata().document_bounds_document_space(!export_config.transparent_background), - ExportBounds::Selection => document.metadata().selected_bounds_document_space(!export_config.transparent_background), + ExportBounds::Selection => document + .metadata() + .selected_bounds_document_space(!export_config.transparent_background, document.metadata(), &document.selected_nodes), ExportBounds::Artboard(id) => document.metadata().bounding_box_document(id), } .ok_or_else(|| "No bounding box".to_string())?; @@ -558,8 +560,8 @@ impl NodeGraphExecutor { let node_graph_output = result.map_err(|e| format!("Node graph evaluation failed: {e:?}"))?; - document.document_metadata.update_transforms(new_upstream_transforms); - document.document_metadata.update_click_targets(new_click_targets); + document.metadata.update_transforms(new_upstream_transforms); + document.metadata.update_click_targets(new_click_targets); let execution_context = self.futures.remove(&execution_id).ok_or_else(|| "Invalid generation ID".to_string())?; if let Some(export_config) = execution_context.export_config { diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs index ae5f0b8f..ae5efc6f 100644 --- a/frontend/src-tauri/src/main.rs +++ b/frontend/src-tauri/src/main.rs @@ -13,7 +13,7 @@ use fern::colors::{Color, ColoredLevelConfig}; // use http::{Response, StatusCode}; use std::cell::RefCell; // use std::collections::HashMap; -use std::sync::Arc; +// use std::sync::Arc; // use std::sync::Mutex; thread_local! {