diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index e1b59f6a45..e6751ac460 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -38,10 +38,9 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[ PropertiesPanelMessageDiscriminant::Refresh, ))), MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::DocumentStructureChanged)), - MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerTreeStructure), + MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerStructure), MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad), MessageDiscriminant::Broadcast(BroadcastMessageDiscriminant::TriggerEvent(BroadcastEventDiscriminant::DocumentIsDirty)), - MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::InputFrameRasterizeRegionBelowLayer)), MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::Overlays(OverlaysMessageDiscriminant::Draw))), ]; @@ -262,6 +261,7 @@ mod test { use crate::messages::tool::tool_messages::tool_prelude::ToolType; use crate::test_utils::EditorTestUtils; + use graph_craft::document::NodeId; use graphene_core::raster::color::Color; fn init_logger() { @@ -359,7 +359,7 @@ mod test { fn copy_paste_folder() { let mut editor = create_editor_with_three_layers(); - const FOLDER_ID: u64 = 3; + const FOLDER_ID: NodeId = 3; editor.handle_message(GraphOperationMessage::NewCustomLayer { id: FOLDER_ID, diff --git a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs index 79840bae44..5bf4bdb21d 100644 --- a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs +++ b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs @@ -78,7 +78,7 @@ impl LayoutHolder for ExportDialogMessageHandler { NumberInput::new(Some(self.scale_factor)) .unit("") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .disabled(self.file_type == FileType::Svg) .on_update(|number_input: &NumberInput| ExportDialogMessage::ScaleFactor(number_input.value.unwrap()).into()) .min_width(200) diff --git a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs index fb939f5a13..747cb7fcf9 100644 --- a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs +++ b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs @@ -95,7 +95,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler { .label("W") .unit(" px") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .is_integer(true) .disabled(self.infinite) .min_width(100) @@ -106,7 +106,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler { .label("H") .unit(" px") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .is_integer(true) .disabled(self.infinite) .min_width(100) diff --git a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs index 8f06c2b168..209d10610b 100644 --- a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs +++ b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs @@ -57,7 +57,7 @@ impl PreferencesDialogMessageHandler { NumberInput::new(Some(preferences.imaginate_refresh_frequency)) .unit(" seconds") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .min_width(200) .on_update(|number_input: &NumberInput| PreferencesMessage::ImaginateRefreshFrequency { seconds: number_input.value.unwrap() }.into()) .widget_holder(), diff --git a/editor/src/messages/dialog/simple_dialogs/close_document_dialog.rs b/editor/src/messages/dialog/simple_dialogs/close_document_dialog.rs index 62b80a9e6f..8939b8992a 100644 --- a/editor/src/messages/dialog/simple_dialogs/close_document_dialog.rs +++ b/editor/src/messages/dialog/simple_dialogs/close_document_dialog.rs @@ -5,7 +5,7 @@ use crate::messages::prelude::*; /// A dialog for confirming the closing a document with unsaved changes. pub struct CloseDocumentDialog { pub document_name: String, - pub document_id: u64, + pub document_id: DocumentId, } impl DialogLayoutHolder for CloseDocumentDialog { diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index d72dffd7ec..ccedbc3081 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -80,7 +80,7 @@ pub enum FrontendMessage { TriggerImport, TriggerIndexedDbRemoveDocument { #[serde(rename = "documentId")] - document_id: u64, + document_id: DocumentId, }, TriggerIndexedDbWriteDocument { document: String, @@ -111,7 +111,7 @@ pub enum FrontendMessage { // Update prefix: give the frontend a new value or state for it to use UpdateActiveDocument { #[serde(rename = "documentId")] - document_id: u64, + document_id: DocumentId, }, UpdateDialogButtons { #[serde(rename = "layoutTarget")] @@ -139,11 +139,11 @@ pub enum FrontendMessage { UpdateDocumentLayerDetails { data: LayerPanelEntry, }, - UpdateDocumentLayerTreeStructure { + UpdateDocumentLayerStructure { #[serde(rename = "dataBuffer")] data_buffer: RawBuffer, }, - UpdateDocumentLayerTreeStructureJs { + UpdateDocumentLayerStructureJs { #[serde(rename = "dataBuffer")] data_buffer: JsRawBuffer, }, @@ -180,7 +180,7 @@ pub enum FrontendMessage { }, UpdateImageData { #[serde(rename = "documentId")] - document_id: u64, + document_id: DocumentId, #[serde(rename = "imageData")] image_data: Vec, }, diff --git a/editor/src/messages/frontend/utility_types.rs b/editor/src/messages/frontend/utility_types.rs index 63ff92a49b..c51b4959c1 100644 --- a/editor/src/messages/frontend/utility_types.rs +++ b/editor/src/messages/frontend/utility_types.rs @@ -1,5 +1,5 @@ use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; -use crate::messages::portfolio::document::utility_types::LayerId; +use crate::messages::prelude::*; use serde::{Deserialize, Serialize}; @@ -10,18 +10,14 @@ pub struct FrontendDocumentDetails { #[serde(rename = "isSaved")] pub is_saved: bool, pub name: String, - pub id: u64, + pub id: DocumentId, } #[derive(PartialEq, Clone, Debug, Serialize, Deserialize, specta::Type)] pub struct FrontendImageData { - pub path: Vec, pub mime: String, #[serde(skip)] pub image_data: std::sync::Arc>, - pub transform: Option<[f64; 6]>, - #[serde(rename = "nodeId")] - pub node_id: Option, } #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, specta::Type)] diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index e8e8151cb0..2096fbd979 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -1,7 +1,6 @@ use crate::messages::input_mapper::utility_types::input_keyboard::Key; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis}; -use crate::messages::portfolio::document::utility_types::LayerId; use crate::messages::prelude::*; use graph_craft::document::{NodeId, NodeNetwork}; @@ -42,14 +41,14 @@ pub enum DocumentMessage { BackupDocument { network: NodeNetwork, }, - ClearLayerTree, + ClearLayersPanel, CommitTransaction, CreateEmptyFolder { parent: LayerNodeIdentifier, }, DebugPrintDocument, DeleteLayer { - layer_path: Vec, + id: NodeId, }, DeleteSelectedLayers, DeselectAllLayers, @@ -61,20 +60,11 @@ pub enum DocumentMessage { flip_axis: FlipAxis, }, GroupSelectedLayers, - ImaginateClear { - layer_path: Vec, - }, - ImaginateGenerate { - layer_path: Vec, - }, + ImaginateGenerate, ImaginateRandom { - layer_path: Vec, imaginate_node: Vec, then_generate: bool, }, - InputFrameRasterizeRegionBelowLayer { - layer_path: Vec, - }, MoveSelectedLayersTo { parent: LayerNodeIdentifier, insert_index: isize, @@ -106,7 +96,7 @@ pub enum DocumentMessage { relative_index_offset: isize, }, SelectLayer { - layer_path: Vec, + id: NodeId, ctrl: bool, shift: bool, }, @@ -132,7 +122,7 @@ pub enum DocumentMessage { }, StartTransaction, ToggleLayerExpansion { - layer: NodeId, + id: NodeId, }, Undo, UndoFinished, diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 4a5e24b5af..796a0ce2d7 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -10,7 +10,6 @@ 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::LayerId; 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}; @@ -224,7 +223,7 @@ fn root_network() -> NodeNetwork { } pub struct DocumentInputs<'a> { - pub document_id: u64, + pub document_id: DocumentId, pub ipp: &'a InputPreprocessorMessageHandler, pub persistent_data: &'a PersistentData, pub executor: &'a mut NodeGraphExecutor, @@ -324,7 +323,7 @@ impl MessageHandler> for DocumentMessageHand }; let translation = (aggregated - center) * axis; responses.add(GraphOperationMessage::TransformChange { - layer: layer.to_path(), + layer, transform: DAffine2::from_translation(translation), transform_in: TransformIn::Viewport, skip_rerender: false, @@ -333,10 +332,10 @@ impl MessageHandler> for DocumentMessageHand responses.add(BroadcastEvent::DocumentIsDirty); } BackupDocument { network } => self.backup_with_document(network, responses), - ClearLayerTree => { - // Send an empty layer tree - let data_buffer: RawBuffer = Self::default().serialize_root().as_slice().into(); - responses.add(FrontendMessage::UpdateDocumentLayerTreeStructure { data_buffer }); + ClearLayersPanel => { + // Send an empty layer list + let data_buffer: RawBuffer = Self::default().serialize_root(); + responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer }); // Clear the options bar responses.add(LayoutMessage::SendLayout { @@ -359,8 +358,8 @@ impl MessageHandler> for DocumentMessageHand DebugPrintDocument => { info!("{:#?}", self.network); } - DeleteLayer { layer_path } => { - responses.add(GraphOperationMessage::DeleteLayer { id: layer_path[0] }); + DeleteLayer { id } => { + responses.add(GraphOperationMessage::DeleteLayer { id }); responses.add_front(BroadcastEvent::ToolAbort); } DeleteSelectedLayers => { @@ -368,9 +367,7 @@ impl MessageHandler> for DocumentMessageHand responses.add_front(BroadcastEvent::SelectionChanged); for path in self.metadata().shallowest_unique_layers(self.metadata().selected_layers()) { - responses.add_front(DocumentMessage::DeleteLayer { - layer_path: path.last().unwrap().to_path(), - }); + responses.add_front(DocumentMessage::DeleteLayer { id: path.last().unwrap().to_node() }); } responses.add(BroadcastEvent::DocumentIsDirty); @@ -384,8 +381,8 @@ impl MessageHandler> for DocumentMessageHand DocumentStructureChanged => { self.update_layers_panel_options_bar_widgets(responses); - let data_buffer: RawBuffer = self.serialize_root().as_slice().into(); - responses.add(FrontendMessage::UpdateDocumentLayerTreeStructure { data_buffer }) + let data_buffer: RawBuffer = self.serialize_root(); + responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer }) } DuplicateSelectedLayers => { // TODO: Reimplement selected layer duplication @@ -406,7 +403,7 @@ impl MessageHandler> for DocumentMessageHand let bbox_trans = DAffine2::from_translation(-center); for layer in self.metadata().selected_layers() { responses.add(GraphOperationMessage::TransformChange { - layer: layer.to_path(), + layer, transform: DAffine2::from_scale(scale), transform_in: TransformIn::Scope { scope: bbox_trans }, skip_rerender: false, @@ -438,13 +435,8 @@ impl MessageHandler> for DocumentMessageHand responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![folder_id] }); } - ImaginateClear { layer_path } => responses.add(InputFrameRasterizeRegionBelowLayer { layer_path }), - ImaginateGenerate { layer_path } => responses.add(PortfolioMessage::SubmitGraphRender { document_id, layer_path }), - ImaginateRandom { - layer_path, - imaginate_node, - then_generate, - } => { + ImaginateGenerate => responses.add(PortfolioMessage::SubmitGraphRender { document_id }), + ImaginateRandom { imaginate_node, then_generate } => { // Generate a random seed. We only want values between -2^53 and 2^53, because integer values // outside of this range can get rounded in f64 let random_bits = generate_uuid(); @@ -459,10 +451,9 @@ impl MessageHandler> for DocumentMessageHand // Generate the image if then_generate { - responses.add(DocumentMessage::ImaginateGenerate { layer_path }); + responses.add(DocumentMessage::ImaginateGenerate); } } - InputFrameRasterizeRegionBelowLayer { layer_path } => responses.add(PortfolioMessage::SubmitGraphRender { document_id, layer_path }), MoveSelectedLayersTo { parent, insert_index } => { let selected_layers = self.metadata().selected_layers().collect::>(); @@ -496,7 +487,7 @@ impl MessageHandler> for DocumentMessageHand // Nudge translation if !ipp.keyboard.key(resize) { responses.add(GraphOperationMessage::TransformChange { - layer: layer.to_path(), + layer, transform: DAffine2::from_translation(delta), transform_in: TransformIn::Local, skip_rerender: false, @@ -525,7 +516,7 @@ impl MessageHandler> for DocumentMessageHand let original_transform = self.metadata().upstream_transform(layer.to_node()); let new = to.inverse() * transformation * to * original_transform; responses.add(GraphOperationMessage::TransformSet { - layer: layer.to_path(), + layer, transform: new, transform_in: TransformIn::Local, skip_rerender: false, @@ -561,7 +552,7 @@ impl MessageHandler> for DocumentMessageHand responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![layer.to_node()] }); responses.add(GraphOperationMessage::TransformSet { - layer: layer.to_path(), + layer, transform, transform_in: TransformIn::Local, skip_rerender: false, @@ -655,16 +646,15 @@ impl MessageHandler> for DocumentMessageHand SelectedLayersReorder { relative_index_offset } => { self.selected_layers_reorder(relative_index_offset, responses); } - SelectLayer { layer_path, ctrl, shift } => { - let clicked_node = *layer_path.last().expect("Cannot select root"); - let layer = LayerNodeIdentifier::new(clicked_node, self.network()); + SelectLayer { id, ctrl, shift } => { + let layer = LayerNodeIdentifier::new(id, self.network()); let mut nodes = vec![]; // If we have shift pressed and a layer already selected then fill the range if let Some(last_selected) = self.layer_range_selection_reference.filter(|_| shift) { nodes.push(last_selected.to_node()); - nodes.push(clicked_node); + nodes.push(id); // Fill the selection range self.metadata() @@ -677,13 +667,13 @@ impl MessageHandler> for DocumentMessageHand if ctrl { // Toggle selection when holding ctrl if self.metadata().selected_layers_contains(layer) { - responses.add_front(NodeGraphMessage::SelectedNodesRemove { nodes: vec![clicked_node] }); + responses.add_front(NodeGraphMessage::SelectedNodesRemove { nodes: vec![id] }); } else { - responses.add_front(NodeGraphMessage::SelectedNodesAdd { nodes: vec![clicked_node] }); + responses.add_front(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] }); } responses.add(BroadcastEvent::SelectionChanged); } else { - nodes.push(clicked_node); + nodes.push(id); } // Set our last selection reference @@ -703,7 +693,7 @@ impl MessageHandler> for DocumentMessageHand SetBlendModeForSelectedLayers { blend_mode } => { self.backup(responses); for layer in self.metadata().selected_layers_except_artboards() { - responses.add(GraphOperationMessage::BlendModeSet { layer: layer.to_path(), blend_mode }); + responses.add(GraphOperationMessage::BlendModeSet { layer, blend_mode }); } } SetOpacityForSelectedLayers { opacity } => { @@ -711,7 +701,7 @@ impl MessageHandler> for DocumentMessageHand let opacity = opacity.clamp(0., 1.) as f32; for layer in self.metadata().selected_layers_except_artboards() { - responses.add(GraphOperationMessage::OpacitySet { layer: layer.to_path(), opacity }); + responses.add(GraphOperationMessage::OpacitySet { layer, opacity }); } } SetOverlaysVisibility { visible } => { @@ -742,8 +732,8 @@ impl MessageHandler> for DocumentMessageHand responses.add_front(NodeGraphMessage::RunDocumentGraph); } StartTransaction => self.backup(responses), - ToggleLayerExpansion { layer } => { - let layer = LayerNodeIdentifier::new(layer, self.network()); + ToggleLayerExpansion { id } => { + let layer = LayerNodeIdentifier::new(id, self.network()); if self.collapsed.contains(&layer) { self.collapsed.retain(|&collapsed_layer| collapsed_layer != layer); } else { @@ -908,23 +898,23 @@ impl DocumentMessageHandler { std::iter::empty() } - fn serialize_structure(&self, folder: LayerNodeIdentifier, structure: &mut Vec, data: &mut Vec, path: &mut Vec) { + fn serialize_structure(&self, folder: LayerNodeIdentifier, structure: &mut Vec, data: &mut Vec, path: &mut Vec) { let mut space = 0; for layer_node in folder.children(self.metadata()) { - data.push(layer_node.to_node()); + data.push(layer_node); space += 1; if layer_node.has_children(self.metadata()) && !self.collapsed.contains(&layer_node) { - path.push(layer_node.to_node()); + path.push(layer_node); // TODO: Skip if folder is not expanded. - structure.push(space); + structure.push(LayerNodeIdentifier::new_unchecked(space)); self.serialize_structure(layer_node, structure, data, path); space = 0; path.pop(); } } - structure.push(space | 1 << 63); + structure.push(LayerNodeIdentifier::new_unchecked(space | 1 << 63)); } /// Serializes the layer structure into a condensed 1D structure. @@ -959,13 +949,15 @@ impl DocumentMessageHandler { /// [3427872634365736244,18115028555707261608,15878401910454357952] /// [3427872634365736244,18115028555707261608,449479075714955186] /// ``` - pub fn serialize_root(&self) -> Vec { - let (mut structure, mut data) = (vec![0], Vec::new()); + pub fn serialize_root(&self) -> RawBuffer { + let mut structure = vec![LayerNodeIdentifier::ROOT]; + let mut data = Vec::new(); self.serialize_structure(self.metadata().root(), &mut structure, &mut data, &mut vec![]); - structure[0] = structure.len() as u64 - 1; + + structure[0] = LayerNodeIdentifier::new_unchecked(structure.len() as NodeId - 1); structure.extend(data); - structure + structure.iter().map(|id| id.to_node()).collect::>().as_slice().into() } /// Places a document into the history system @@ -1064,10 +1056,9 @@ impl DocumentMessageHandler { /// /// This function updates the insert index so that it points to the same place after the specified `layers` are deleted. fn update_insert_index(&self, layers: &[LayerNodeIdentifier], parent: LayerNodeIdentifier, insert_index: isize) -> isize { - let layer_ids_above = parent.children(self.metadata()).take(if insert_index < 0 { usize::MAX } else { insert_index as usize }); - let new_insert_index = layer_ids_above.filter(|layer_id| !layers.contains(layer_id)).count() as isize; - - new_insert_index + let take_amount = if insert_index < 0 { usize::MAX } else { insert_index as usize }; + let layer_ids_above = parent.children(self.metadata()).take(take_amount); + layer_ids_above.filter(|layer_id| !layers.contains(layer_id)).count() as isize } pub fn new_layer_parent(&self) -> LayerNodeIdentifier { diff --git a/editor/src/messages/portfolio/document/node_graph/graph_operation_message.rs b/editor/src/messages/portfolio/document/node_graph/graph_operation_message.rs index 26d98f3a5a..3dc45cf0de 100644 --- a/editor/src/messages/portfolio/document/node_graph/graph_operation_message.rs +++ b/editor/src/messages/portfolio/document/node_graph/graph_operation_message.rs @@ -1,5 +1,4 @@ use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; -use crate::messages::portfolio::document::utility_types::LayerId; use crate::messages::prelude::*; use bezier_rs::Subpath; @@ -16,56 +15,54 @@ use graphene_core::{Artboard, Color}; use glam::{DAffine2, DVec2, IVec2}; -pub type LayerIdentifier = Vec; - #[impl_message(Message, DocumentMessage, GraphOperation)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum GraphOperationMessage { FillSet { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, fill: Fill, }, OpacitySet { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, opacity: f32, }, BlendModeSet { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, blend_mode: BlendMode, }, UpdateBounds { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, old_bounds: [DVec2; 2], new_bounds: [DVec2; 2], }, StrokeSet { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, stroke: Stroke, }, TransformChange { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, transform: DAffine2, transform_in: TransformIn, skip_rerender: bool, }, TransformSet { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, transform: DAffine2, transform_in: TransformIn, skip_rerender: bool, }, TransformSetPivot { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, pivot: DVec2, }, Vector { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, modification: VectorDataModification, }, Brush { - layer: LayerIdentifier, + layer: LayerNodeIdentifier, strokes: Vec, }, 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 22c55a0678..7b739bcf56 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,6 +1,5 @@ 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::LayerId; use crate::messages::prelude::*; use bezier_rs::Subpath; @@ -26,7 +25,6 @@ struct ModifyInputsContext<'a> { document_network: &'a mut NodeNetwork, node_graph: &'a mut NodeGraphMessageHandler, responses: &'a mut VecDeque, - layer: &'a [LayerId], outwards_links: HashMap>, layer_node: Option, } @@ -38,27 +36,25 @@ impl<'a> ModifyInputsContext<'a> { document_network, node_graph, responses, - layer: &[], layer_node: None, document_metadata, } } fn new_with_layer( - layer: &'a [LayerId], + id: NodeId, document_network: &'a mut NodeNetwork, document_metadata: &'a mut DocumentMetadata, node_graph: &'a mut NodeGraphMessageHandler, responses: &'a mut VecDeque, ) -> Option { let mut document = Self::new(document_network, document_metadata, node_graph, responses); - let Some(mut id) = layer.last().copied() else { - error!("Tried to modify root layer"); - return None; - }; + + let mut id = id; while !document.document_network.nodes.get(&id)?.is_layer() { id = document.outwards_links.get(&id)?.first().copied()?; } + document.layer_node = Some(id); Some(document) } @@ -325,10 +321,9 @@ impl<'a> ModifyInputsContext<'a> { self.node_graph.network.clear(); self.responses.add(PropertiesPanelMessage::Refresh); - let layer_path = self.layer.to_vec(); if !skip_rerender { - self.responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path }); + self.responses.add(NodeGraphMessage::RunDocumentGraph); } else { // Code was removed from here which cleared the frame } @@ -354,10 +349,9 @@ impl<'a> ModifyInputsContext<'a> { } self.responses.add(PropertiesPanelMessage::Refresh); - let layer_path = self.layer.to_vec(); if !skip_rerender { - self.responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path }); + self.responses.add(NodeGraphMessage::RunDocumentGraph); } else { // Code was removed from here which cleared the frame } @@ -509,8 +503,8 @@ impl<'a> ModifyInputsContext<'a> { self.update_bounds([old_bounds_min, old_bounds_max], [new_bounds_min, new_bounds_max]); if empty { - if let Some(layer) = self.layer_node { - self.responses.add(DocumentMessage::DeleteLayer { layer_path: vec![layer] }) + if let Some(id) = self.layer_node { + self.responses.add(DocumentMessage::DeleteLayer { id }) } } } @@ -594,27 +588,27 @@ impl MessageHandler { - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.fill_set(fill); } } GraphOperationMessage::OpacitySet { layer, opacity } => { - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.opacity_set(opacity); } } GraphOperationMessage::BlendModeSet { layer, blend_mode } => { - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.blend_mode_set(blend_mode); } } GraphOperationMessage::UpdateBounds { layer, old_bounds, new_bounds } => { - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.update_bounds(old_bounds, new_bounds); } } GraphOperationMessage::StrokeSet { layer, stroke } => { - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.stroke_set(stroke); } } @@ -624,10 +618,9 @@ impl MessageHandler { - let layer_identifier = LayerNodeIdentifier::new(*layer.last().unwrap(), document_network); - let parent_transform = document_metadata.downstream_transform_to_viewport(layer_identifier); - let bounds = LayerBounds::new(document_network, document_metadata, &layer); - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + let parent_transform = document_metadata.downstream_transform_to_viewport(layer); + let bounds = LayerBounds::new(document_metadata, layer); + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.transform_change(transform, transform_in, parent_transform, bounds, skip_rerender); } } @@ -637,28 +630,27 @@ impl MessageHandler { - let layer_identifier = LayerNodeIdentifier::new(*layer.last().unwrap(), document_network); - let parent_transform = document_metadata.downstream_transform_to_viewport(layer_identifier); + let parent_transform = document_metadata.downstream_transform_to_viewport(layer); - let current_transform = Some(document_metadata.transform_to_viewport(layer_identifier)); - let bounds = LayerBounds::new(document_network, document_metadata, &layer); - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + let current_transform = Some(document_metadata.transform_to_viewport(layer)); + let bounds = LayerBounds::new(document_metadata, layer); + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.transform_set(transform, transform_in, parent_transform, current_transform, bounds, skip_rerender); } } GraphOperationMessage::TransformSetPivot { layer, pivot } => { - let bounds = LayerBounds::new(document_network, document_metadata, &layer); - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + let bounds = LayerBounds::new(document_metadata, layer); + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.pivot_set(pivot, bounds); } } GraphOperationMessage::Vector { layer, modification } => { - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.vector_modify(modification); } } GraphOperationMessage::Brush { layer, strokes } => { - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) { + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) { modify_inputs.brush_modify(strokes); } } @@ -744,7 +736,7 @@ impl MessageHandler { - if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&[id], document_network, document_metadata, node_graph, responses) { + if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(id, document_network, document_metadata, node_graph, responses) { modify_inputs.resize_artboard(location, dimensions); } } 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 7d69b21e6e..6ae4a12fd4 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 @@ -2,7 +2,6 @@ use crate::messages::portfolio::document::node_graph::VectorDataModification; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; use bezier_rs::{ManipulatorGroup, Subpath}; -use graph_craft::document::NodeNetwork; use graph_craft::document::{value::TaggedValue, NodeInput}; use graphene_core::uuid::ManipulatorGroupId; use graphene_core::vector::{ManipulatorPointId, SelectedType}; @@ -53,8 +52,7 @@ pub struct LayerBounds { impl LayerBounds { /// Extract the layer bounds and their transform for a layer. - pub fn new(document_network: &NodeNetwork, document_metadata: &DocumentMetadata, layer: &[u64]) -> Self { - let layer = LayerNodeIdentifier::new(*layer.last().unwrap(), document_network); + pub fn new(document_metadata: &DocumentMetadata, layer: LayerNodeIdentifier) -> Self { Self { bounds: document_metadata.nonzero_bounding_box(layer), bounds_transform: DAffine2::IDENTITY, diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs index 3a3b9061b6..52c3b083fd 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs @@ -1,4 +1,3 @@ -use crate::messages::portfolio::document::utility_types::LayerId; use crate::messages::prelude::*; use graph_craft::document::value::TaggedValue; @@ -11,14 +10,13 @@ pub enum NodeGraphMessage { Init, SelectedNodesUpdated, ConnectNodesByLink { - output_node: u64, + output_node: NodeId, output_node_connector_index: usize, - input_node: u64, + input_node: NodeId, input_node_connector_index: usize, }, Copy, CreateNode { - // Having the caller generate the id means that we don't have to return it. This can be a random u64. node_id: Option, node_type: String, x: i32, @@ -83,7 +81,6 @@ pub enum NodeGraphMessage { input: NodeInput, }, SetQualifiedInputValue { - layer_path: Vec, node_path: Vec, input_index: usize, value: TaggedValue, 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 a2bc46de7c..c4292a379b 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 @@ -3,9 +3,7 @@ use super::load_network_structure; 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::LayerId; use crate::messages::prelude::*; -use crate::node_graph_executor::GraphIdentifier; use graph_craft::document::value::TaggedValue; use graph_craft::document::{DocumentNode, NodeId, NodeInput, NodeNetwork, NodeOutput}; @@ -99,13 +97,13 @@ pub struct FrontendNode { #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] pub struct FrontendNodeLink { #[serde(rename = "linkStart")] - pub link_start: u64, + pub link_start: NodeId, #[serde(rename = "linkStartOutputIndex")] pub link_start_output_index: usize, #[serde(rename = "linkEnd")] - pub link_end: u64, + pub link_end: NodeId, #[serde(rename = "linkEndInputIndex")] - pub link_end_input_index: u64, + pub link_end_input_index: usize, } #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] @@ -124,10 +122,9 @@ impl FrontendNodeType { #[derive(Debug, Clone, PartialEq)] pub struct NodeGraphMessageHandler { - pub layer_path: Option>, pub network: Vec, has_selection: bool, - pub widgets: [LayoutGroup; 2], + widgets: [LayoutGroup; 2], } impl Default for NodeGraphMessageHandler { @@ -137,7 +134,6 @@ impl Default for NodeGraphMessageHandler { let add_nodes_label_row = LayoutGroup::Row { widgets: vec![add_nodes_label] }; Self { - layer_path: None, network: Vec::new(), has_selection: false, widgets: [add_nodes_label_row, LayoutGroup::default()], @@ -261,15 +257,13 @@ impl NodeGraphMessageHandler { } } - fn send_graph(network: &NodeNetwork, layer_path: &Option>, graph_view_overlay_open: bool, responses: &mut VecDeque) { + fn send_graph(network: &NodeNetwork, graph_view_overlay_open: bool, responses: &mut VecDeque) { responses.add(PropertiesPanelMessage::Refresh); if !graph_view_overlay_open { return; } - let layer_id = layer_path.as_ref().and_then(|path| path.last().copied()); - // List of links in format (link_start, link_end, link_end_input_index) let links = network .nodes @@ -278,16 +272,16 @@ impl NodeGraphMessageHandler { .filter_map(|(input, &link_end, link_end_input_index)| { if let NodeInput::Node { node_id: link_start, - output_index: link_start_index, + output_index: link_start_output_index, // TODO: add ui for lambdas lambda: _, } = *input { Some(FrontendNodeLink { link_start, - link_start_output_index: link_start_index, + link_start_output_index, link_end, - link_end_input_index: link_end_input_index as u64, + link_end_input_index, }) } else { None @@ -318,8 +312,6 @@ impl NodeGraphMessageHandler { }); let primary_output = if node.has_primary_output { outputs.next() } else { None }; - let _graph_identifier = GraphIdentifier::new(layer_id); - nodes.push(FrontendNode { is_layer: node.is_layer(), id: *id, @@ -446,7 +438,7 @@ impl NodeGraphMessageHandler { pub struct NodeGraphHandlerData<'a> { pub document_network: &'a mut NodeNetwork, pub document_metadata: &'a mut DocumentMetadata, - pub document_id: u64, + pub document_id: DocumentId, pub document_name: &'a str, pub collapsed: &'a mut Vec, pub input: &'a InputPreprocessorMessageHandler, @@ -495,7 +487,7 @@ impl<'a> MessageHandler> for NodeGrap error!("No network"); return; }; - let Some(input_node) = network.nodes.get(&input_node) else { + let Some(input_node) = network.nodes.get(&node_id) else { error!("No to"); return; }; @@ -569,11 +561,7 @@ impl<'a> MessageHandler> for NodeGrap 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 metadata.selected_nodes().any(|&node_id| network.connected_to_output(node_id)) { - if let Some(layer_path) = self.layer_path.clone() { - responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path }); - } else { - responses.add(NodeGraphMessage::RunDocumentGraph); - } + responses.add(NodeGraphMessage::RunDocumentGraph); } } } @@ -612,7 +600,7 @@ impl<'a> MessageHandler> for NodeGrap } } if let Some(network) = document_network.nested_network(&self.network) { - Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses); + Self::send_graph(network, graph_view_overlay_open, responses); } self.update_selected(document_network, metadata, responses); } @@ -640,7 +628,7 @@ impl<'a> MessageHandler> for NodeGrap responses.add(NodeGraphMessage::InsertNode { node_id, document_node }); } - Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses); + Self::send_graph(network, graph_view_overlay_open, responses); self.update_selected(document_network, metadata, responses); responses.add(NodeGraphMessage::SendGraph { should_rerender: false }); } @@ -653,7 +641,7 @@ impl<'a> MessageHandler> for NodeGrap self.network.pop(); } if let Some(network) = document_network.nested_network(&self.network) { - Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses); + Self::send_graph(network, graph_view_overlay_open, responses); } self.update_selected(document_network, metadata, responses); } @@ -703,7 +691,7 @@ impl<'a> MessageHandler> for NodeGrap node.metadata.position += IVec2::new(displacement_x, displacement_y) } } - Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses); + Self::send_graph(network, graph_view_overlay_open, responses); } NodeGraphMessage::PasteNodes { serialized_nodes } => { let Some(network) = document_network.nested_network(&self.network) else { @@ -752,7 +740,7 @@ impl<'a> MessageHandler> for NodeGrap responses.add(NodeGraphMessage::SendGraph { should_rerender: false }); } - NodeGraphMessage::RunDocumentGraph => responses.add(PortfolioMessage::SubmitGraphRender { document_id, layer_path: Vec::new() }), + NodeGraphMessage::RunDocumentGraph => responses.add(PortfolioMessage::SubmitGraphRender { document_id }), NodeGraphMessage::SelectedNodesAdd { nodes } => { metadata.add_selected_nodes(nodes); responses.add(BroadcastEvent::SelectionChanged); @@ -768,13 +756,9 @@ impl<'a> MessageHandler> for NodeGrap } NodeGraphMessage::SendGraph { should_rerender } => { if let Some(network) = document_network.nested_network(&self.network) { - Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses); + Self::send_graph(network, graph_view_overlay_open, responses); if should_rerender { - if let Some(layer_path) = self.layer_path.clone() { - responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path }); - } else { - responses.add(NodeGraphMessage::RunDocumentGraph); - } + responses.add(NodeGraphMessage::RunDocumentGraph); } } } @@ -787,11 +771,7 @@ impl<'a> MessageHandler> for NodeGrap responses.add(NodeGraphMessage::SetNodeInput { node_id, input_index, input }); responses.add(PropertiesPanelMessage::Refresh); if (node.name != "Imaginate" || input_index == 0) && network.connected_to_output(node_id) { - if let Some(layer_path) = self.layer_path.clone() { - responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path }); - } else { - responses.add(NodeGraphMessage::RunDocumentGraph); - } + responses.add(NodeGraphMessage::RunDocumentGraph); } } } @@ -811,12 +791,7 @@ impl<'a> MessageHandler> for NodeGrap } } } - NodeGraphMessage::SetQualifiedInputValue { - layer_path, - node_path, - input_index, - value, - } => { + NodeGraphMessage::SetQualifiedInputValue { node_path, input_index, value } => { let Some((node_id, node_path)) = node_path.split_last() else { error!("Node path is empty"); return; @@ -832,7 +807,7 @@ impl<'a> MessageHandler> for NodeGrap } node.inputs[input_index] = NodeInput::Value { tagged_value: value, exposed: false }; if network.connected_to_output(*node_id) { - responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path }); + responses.add(NodeGraphMessage::RunDocumentGraph); } } } @@ -908,7 +883,7 @@ impl<'a> MessageHandler> for NodeGrap } else if !network.inputs.contains(&node_id) && !network.original_outputs().iter().any(|output| output.node_id == node_id) { network.disabled.push(node_id); } - Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses); + Self::send_graph(network, graph_view_overlay_open, responses); // Only generate node graph if one of the selected nodes is connected to the output if network.connected_to_output(node_id) { @@ -944,21 +919,17 @@ impl<'a> MessageHandler> for NodeGrap } else { return; } - Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses); + Self::send_graph(network, graph_view_overlay_open, responses); } self.update_selection_action_buttons(document_network, metadata, responses); - if let Some(layer_path) = self.layer_path.clone() { - responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path }); - } else { - responses.add(NodeGraphMessage::RunDocumentGraph); - } + responses.add(NodeGraphMessage::RunDocumentGraph); } NodeGraphMessage::UpdateNewNodeGraph => { if let Some(network) = document_network.nested_network(&self.network) { metadata.clear_selected_nodes(); responses.add(BroadcastEvent::SelectionChanged); - Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses); + Self::send_graph(network, graph_view_overlay_open, responses); let node_types = document_node_types::collect_node_types(); responses.add(FrontendMessage::UpdateNodeTypes { node_types }); 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 92e97bf737..181dfb9011 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 @@ -2,7 +2,6 @@ use super::{node_properties, FrontendGraphDataType, FrontendNodeType}; use crate::consts::{DEFAULT_FONT_FAMILY, DEFAULT_FONT_STYLE}; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::utility_types::document_metadata::DocumentMetadata; -use crate::messages::portfolio::document::utility_types::LayerId; use crate::messages::portfolio::utility_types::PersistentData; use crate::messages::prelude::Message; use crate::node_graph_executor::NodeGraphExecutor; @@ -74,7 +73,6 @@ impl DocumentOutputType { pub struct NodePropertiesContext<'a> { pub persistent_data: &'a PersistentData, pub responses: &'a mut VecDeque, - pub layer_path: &'a [LayerId], pub nested_path: &'a [NodeId], pub executor: &'a mut NodeGraphExecutor, pub network: &'a NodeNetwork, @@ -279,7 +277,7 @@ fn static_nodes() -> Vec { name: "Image Frame", data_type: FrontendGraphDataType::Raster, }], - properties: node_properties::input_properties, + properties: node_properties::node_no_properties, ..Default::default() }, DocumentNodeDefinition { @@ -1069,7 +1067,7 @@ fn static_nodes() -> Vec { name: "OutputBuffer", data_type: FrontendGraphDataType::General, }], - properties: node_properties::input_properties, + properties: node_properties::node_no_properties, ..Default::default() }, #[cfg(feature = "gpu")] @@ -1137,7 +1135,7 @@ fn static_nodes() -> Vec { name: "CommandBuffer", data_type: FrontendGraphDataType::General, }], - properties: node_properties::input_properties, + properties: node_properties::node_no_properties, ..Default::default() }, #[cfg(feature = "gpu")] @@ -1171,7 +1169,7 @@ fn static_nodes() -> Vec { name: "PipelineLayout", data_type: FrontendGraphDataType::General, }], - properties: node_properties::input_properties, + properties: node_properties::node_no_properties, ..Default::default() }, #[cfg(feature = "gpu")] @@ -2377,7 +2375,7 @@ pub static IMAGINATE_NODE: Lazy = Lazy::new(|| DocumentN name: "Imaginate", category: "Image Synthesis", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + inputs: vec![0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], outputs: vec![NodeOutput::new(1, 0)], nodes: [ ( @@ -2404,14 +2402,13 @@ pub static IMAGINATE_NODE: Lazy = Lazy::new(|| DocumentN NodeInput::Network(concrete!(String)), NodeInput::Network(concrete!(bool)), NodeInput::Network(concrete!(f32)), - NodeInput::Network(concrete!(Option>)), NodeInput::Network(concrete!(bool)), NodeInput::Network(concrete!(f32)), NodeInput::Network(concrete!(ImaginateMaskStartingFill)), NodeInput::Network(concrete!(bool)), NodeInput::Network(concrete!(bool)), ], - implementation: DocumentNodeImplementation::proto("graphene_std::raster::ImaginateNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _>"), + implementation: DocumentNodeImplementation::proto("graphene_std::raster::ImaginateNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _>"), ..Default::default() }, ), @@ -2436,7 +2433,6 @@ pub static IMAGINATE_NODE: Lazy = Lazy::new(|| DocumentN DocumentInputType::value("Negative Prompt", TaggedValue::String(String::new()), false), DocumentInputType::value("Adapt Input Image", TaggedValue::Bool(false), false), DocumentInputType::value("Image Creativity", TaggedValue::F32(66.), false), - DocumentInputType::value("Masking Layer", TaggedValue::LayerPath(None), false), DocumentInputType::value("Inpaint", TaggedValue::Bool(true), false), DocumentInputType::value("Mask Blur", TaggedValue::F32(4.), false), DocumentInputType::value("Mask Starting Fill", TaggedValue::ImaginateMaskStartingFill(ImaginateMaskStartingFill::Fill), false), diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 96ab95314e..ec2b305da4 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -144,16 +144,16 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name NumberInput::new(Some(dvec2.x)) .label(x) .unit(unit) - .min(min.unwrap_or(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64))) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), dvec2.y)), node_id, index)) .widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), NumberInput::new(Some(dvec2.y)) .label(y) .unit(unit) - .min(min.unwrap_or(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64))) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(dvec2.x, input.value.unwrap())), node_id, index)) .widget_holder(), ]); @@ -170,8 +170,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name .int() .label(x) .unit(unit) - .min(min.unwrap_or(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64))) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(update_value(update_x, node_id, index)) .widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), @@ -179,8 +179,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name .int() .label(y) .unit(unit) - .min(min.unwrap_or(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64))) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(update_value(update_y, node_id, index)) .widget_holder(), ]); @@ -198,7 +198,7 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name .label(x) .unit(unit) .min(min.unwrap_or(0.)) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(update_value(update_x, node_id, index)) .widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), @@ -207,7 +207,7 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name .label(y) .unit(unit) .min(min.unwrap_or(0.)) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(update_value(update_y, node_id, index)) .widget_holder(), ]); @@ -359,7 +359,7 @@ fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, na } //TODO Generalize this instead of using a separate function per dropdown menu enum -fn color_channel(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { +fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::RedGreenBlue(mode), @@ -382,7 +382,7 @@ fn color_channel(document_node: &DocumentNode, node_id: u64, index: usize, name: } // TODO Generalize this instead of using a separate function per dropdown menu enum -fn noise_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { +fn noise_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::NoiseType(noise_type), @@ -403,7 +403,7 @@ fn noise_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &s } // TODO Generalize this instead of using a separate function per dropdown menu enum -fn fractal_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { +fn fractal_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::FractalType(fractal_type), @@ -424,7 +424,7 @@ fn fractal_type(document_node: &DocumentNode, node_id: u64, index: usize, name: } // TODO Generalize this instead of using a separate function per dropdown menu enum -fn cellular_distance_function(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { +fn cellular_distance_function(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::CellularDistanceFunction(cellular_distance_function), @@ -450,7 +450,7 @@ fn cellular_distance_function(document_node: &DocumentNode, node_id: u64, index: } // TODO Generalize this instead of using a separate function per dropdown menu enum -fn cellular_return_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { +fn cellular_return_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::CellularReturnType(cellular_return_type), @@ -471,7 +471,7 @@ fn cellular_return_type(document_node: &DocumentNode, node_id: u64, index: usize } // TODO Generalize this instead of using a separate function per dropdown menu enum -fn domain_warp_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { +fn domain_warp_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::DomainWarpType(domain_warp_type), @@ -492,7 +492,7 @@ fn domain_warp_type(document_node: &DocumentNode, node_id: u64, index: usize, na } // TODO: Generalize this instead of using a separate function per dropdown menu enum -fn blend_mode(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { +fn blend_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::BlendMode(blend_mode), @@ -520,7 +520,7 @@ fn blend_mode(document_node: &DocumentNode, node_id: u64, index: usize, name: &s } // TODO: Generalize this for all dropdowns (also see blend_mode and channel_extration) -fn luminance_calculation(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { +fn luminance_calculation(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::LuminanceCalculation(calculation), @@ -542,7 +542,7 @@ fn luminance_calculation(document_node: &DocumentNode, node_id: u64, index: usiz LayoutGroup::Row { widgets }.with_tooltip("Formula used to calculate the luminance of a pixel") } -fn line_cap_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { +fn line_cap_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::LineCap(line_cap), @@ -562,7 +562,7 @@ fn line_cap_widget(document_node: &DocumentNode, node_id: u64, index: usize, nam LayoutGroup::Row { widgets } } -fn line_join_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { +fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let &NodeInput::Value { tagged_value: TaggedValue::LineJoin(line_join), @@ -582,7 +582,7 @@ fn line_join_widget(document_node: &DocumentNode, node_id: u64, index: usize, na LayoutGroup::Row { widgets } } -fn fill_type_widget(document_node: &DocumentNode, node_id: u64, index: usize) -> LayoutGroup { +fn fill_type_widget(document_node: &DocumentNode, node_id: NodeId, index: usize) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, "Fill Type", FrontendGraphDataType::General, true); if let &NodeInput::Value { tagged_value: TaggedValue::FillType(fill_type), @@ -607,7 +607,7 @@ fn fill_type_widget(document_node: &DocumentNode, node_id: u64, index: usize) -> LayoutGroup::Row { widgets } } -fn gradient_type_widget(document_node: &DocumentNode, node_id: u64, index: usize) -> LayoutGroup { +fn gradient_type_widget(document_node: &DocumentNode, node_id: NodeId, index: usize) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, "Gradient Type", FrontendGraphDataType::General, true); if let &NodeInput::Value { tagged_value: TaggedValue::GradientType(gradient_type), @@ -699,7 +699,7 @@ fn gradient_row(row: &mut Vec, positions: &Vec<(f64, Option } } -fn gradient_positions(rows: &mut Vec, document_node: &DocumentNode, name: &str, node_id: u64, input_index: usize) { +fn gradient_positions(rows: &mut Vec, document_node: &DocumentNode, name: &str, node_id: NodeId, input_index: usize) { let mut widgets = vec![expose_widget(node_id, input_index, FrontendGraphDataType::General, document_node.inputs[input_index].is_exposed())]; widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); if let NodeInput::Value { @@ -742,7 +742,7 @@ fn gradient_positions(rows: &mut Vec, document_node: &DocumentNode, } } -fn color_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, color_props: ColorButton, blank_assist: bool) -> LayoutGroup { +fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, color_props: ColorButton, blank_assist: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Number, blank_assist); if let NodeInput::Value { tagged_value, exposed: false } = &document_node.inputs[index] { @@ -767,7 +767,7 @@ fn color_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: LayoutGroup::Row { widgets } } -fn curves_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { +fn curves_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); if let NodeInput::Value { @@ -785,17 +785,6 @@ fn curves_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: LayoutGroup::Row { widgets } } -/// Properties for the input node, with information describing how frames work and a refresh button -pub fn input_properties(_document_node: &DocumentNode, _node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { - let information = TextLabel::new("The graph's input frame is the rasterized artwork under the layer").widget_holder(); - let layer_path = context.layer_path.to_vec(); - let refresh_button = TextButton::new("Refresh Input") - .tooltip("Refresh the artwork under the layer") - .on_update(move |_| DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path: layer_path.clone() }.into()) - .widget_holder(); - vec![LayoutGroup::Row { widgets: vec![information] }, LayoutGroup::Row { widgets: vec![refresh_button] }] -} - pub fn levels_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let input_shadows = number_widget(document_node, node_id, 1, "Shadows", NumberInput::default().min(0.).max(100.).unit("%"), true); let input_midtones = number_widget(document_node, node_id, 2, "Midtones", NumberInput::default().min(0.).max(100.).unit("%"), true); @@ -1629,12 +1618,10 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte .tooltip("Generate with a new random seed") .on_update({ let imaginate_node = imaginate_node.clone(); - let layer_path = context.layer_path.to_vec(); let controller = controller.clone(); move |_| { controller.trigger_regenerate(); DocumentMessage::ImaginateRandom { - layer_path: layer_path.clone(), imaginate_node: imaginate_node.clone(), then_generate: true, } @@ -1646,11 +1633,10 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte TextButton::new("Generate") .tooltip("Fill layer frame by generating a new image") .on_update({ - let layer_path = context.layer_path.to_vec(); let controller = controller.clone(); move |_| { controller.trigger_regenerate(); - DocumentMessage::ImaginateGenerate { layer_path: layer_path.clone() }.into() + DocumentMessage::ImaginateGenerate.into() } }) .widget_holder(), @@ -1659,11 +1645,10 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte .tooltip("Remove generated image from the layer frame") .disabled(!matches!(imaginate_status, ImaginateStatus::ReadyDone)) .on_update({ - let layer_path = context.layer_path.to_vec(); let controller = controller.clone(); move |_| { controller.set_status(ImaginateStatus::Ready); - DocumentMessage::ImaginateClear { layer_path: layer_path.clone() }.into() + DocumentMessage::ImaginateGenerate.into() } }) .widget_holder(), @@ -1687,10 +1672,8 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte .tooltip("Set a new random seed") .on_update({ let imaginate_node = imaginate_node.clone(); - let layer_path = context.layer_path.to_vec(); move |_| { DocumentMessage::ImaginateRandom { - layer_path: layer_path.clone(), imaginate_node: imaginate_node.clone(), then_generate: false, } @@ -1701,8 +1684,8 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte Separator::new(SeparatorType::Unrelated).widget_holder(), NumberInput::new(Some(seed)) .int() - .min(-((1u64 << f64::MANTISSA_DIGITS) as f64)) - .max((1u64 << f64::MANTISSA_DIGITS) as f64) + .min(-((1_u64 << f64::MANTISSA_DIGITS) as f64)) + .max((1_u64 << f64::MANTISSA_DIGITS) as f64) .on_update(update_value(move |input: &NumberInput| TaggedValue::F64(input.value.unwrap()), node_id, seed_index)) .mode(NumberInputMode::Increment) .widget_holder(), 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 3924a11bf7..552c8e4d56 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 @@ -37,7 +37,6 @@ impl<'a> MessageHandler>(); - sorted_layers.sort(); + // Sorting here creates groups of similar UUID paths + sorted_layers.sort(); sorted_layers.dedup_by(|a, b| a.starts_with(b)); sorted_layers } @@ -386,32 +387,27 @@ impl LayerNodeIdentifier { u64::from(self.0) - 1 } - /// Convert layer to layer path - pub fn to_path(self) -> Vec { - vec![self.to_node()] - } - /// Access the parent layer if possible pub fn parent(self, document_metadata: &DocumentMetadata) -> Option { document_metadata.get_relations(self).and_then(|relations| relations.parent) } - /// Access the previous sibling of this layer (up the layer tree) + /// 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) } - /// Access the next sibling of this layer (down the layer tree) + /// 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) } - /// Access the first child of this layer (top most in layer tree) + /// 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) } - /// Access the last child of this layer (bottom most in layer tree) + /// 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) } @@ -457,7 +453,7 @@ impl LayerNodeIdentifier { } } - /// Add a child towards the top of the layer tree + /// 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); @@ -470,7 +466,7 @@ impl LayerNodeIdentifier { document_metadata.get_structure_mut(new).parent = Some(self); } - /// Add a child towards the bottom of the layer tree + /// 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); @@ -483,7 +479,7 @@ impl LayerNodeIdentifier { document_metadata.get_structure_mut(new).parent = Some(self); } - /// Add sibling above in the layer tree + /// 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); @@ -501,7 +497,7 @@ impl LayerNodeIdentifier { } } - /// Add sibling below in the layer tree + /// 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); diff --git a/editor/src/messages/portfolio/document/utility_types/layer_panel.rs b/editor/src/messages/portfolio/document/utility_types/layer_panel.rs index a7eaf7a3bc..5858c52675 100644 --- a/editor/src/messages/portfolio/document/utility_types/layer_panel.rs +++ b/editor/src/messages/portfolio/document/utility_types/layer_panel.rs @@ -1,4 +1,4 @@ -use crate::messages::portfolio::document::utility_types::LayerId; +use graph_craft::document::NodeId; use serde::ser::SerializeStruct; use serde::{Deserialize, Serialize}; @@ -45,6 +45,9 @@ pub struct LayerPanelEntry { pub layer_classification: LayerClassification, pub selected: bool, pub expanded: bool, - pub path: Vec, + #[serde(rename = "parentId")] + pub parent_id: Option, + pub id: NodeId, + pub depth: usize, pub thumbnail: String, } diff --git a/editor/src/messages/portfolio/document/utility_types/misc.rs b/editor/src/messages/portfolio/document/utility_types/misc.rs index 453398ea5f..f347ad3d83 100644 --- a/editor/src/messages/portfolio/document/utility_types/misc.rs +++ b/editor/src/messages/portfolio/document/utility_types/misc.rs @@ -1,7 +1,4 @@ pub use super::layer_panel::LayerPanelEntry; -use crate::messages::portfolio::document::utility_types::LayerId; - -use graphene_core::raster::color::Color; use glam::DVec2; use serde::{Deserialize, Serialize}; @@ -54,12 +51,6 @@ impl DocumentMode { } } -pub enum DocumentRenderMode<'a> { - Root, - OnlyBelowLayerInFolder(&'a [LayerId]), - LayerCutout(&'a [LayerId], Color), -} - #[derive(Clone, Debug)] /// SnappingState determines the current individual snapping states pub struct SnappingState { diff --git a/editor/src/messages/portfolio/document/utility_types/mod.rs b/editor/src/messages/portfolio/document/utility_types/mod.rs index 80f67ae8b2..1417ea9a8c 100644 --- a/editor/src/messages/portfolio/document/utility_types/mod.rs +++ b/editor/src/messages/portfolio/document/utility_types/mod.rs @@ -4,8 +4,3 @@ pub mod error; pub mod layer_panel; pub mod misc; pub mod transformation; - -// TODO: Remove this entirely -/// A number that identifies a layer. -/// This does not technically need to be unique globally, only within a folder. -pub type LayerId = u64; diff --git a/editor/src/messages/portfolio/document/utility_types/transformation.rs b/editor/src/messages/portfolio/document/utility_types/transformation.rs index 2b01623bc1..0ca12de26f 100644 --- a/editor/src/messages/portfolio/document/utility_types/transformation.rs +++ b/editor/src/messages/portfolio/document/utility_types/transformation.rs @@ -376,7 +376,7 @@ impl<'a> Selected<'a> { let to = document_metadata.downstream_transform_to_viewport(layer); let new = to.inverse() * transformation * to * original_transform; responses.add(GraphOperationMessage::TransformSet { - layer: layer.to_path(), + layer, transform: new, transform_in: TransformIn::Local, skip_rerender: false, @@ -404,7 +404,7 @@ impl<'a> Selected<'a> { let position = new_pos_viewport; responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position }, }); } @@ -438,17 +438,17 @@ impl<'a> Selected<'a> { OriginalTransforms::Layer(hash) => { let Some(matrix) = hash.get(&layer) else { continue }; self.responses.add(GraphOperationMessage::TransformSet { - layer: layer.to_path(), + layer, transform: *matrix, transform_in: TransformIn::Local, skip_rerender: false, }); } OriginalTransforms::Path(path) => { - for (layer, points) in path { + for (&layer, points) in path { for &(point, position) in points { self.responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position }, }); } diff --git a/editor/src/messages/portfolio/portfolio_message.rs b/editor/src/messages/portfolio/portfolio_message.rs index e0355aa8d6..1082266e27 100644 --- a/editor/src/messages/portfolio/portfolio_message.rs +++ b/editor/src/messages/portfolio/portfolio_message.rs @@ -1,8 +1,8 @@ use super::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::frontend::utility_types::{ExportBounds, FileType}; use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; -use crate::messages::portfolio::document::utility_types::LayerId; use crate::messages::prelude::*; + use graphene_core::text::Font; use serde::{Deserialize, Serialize}; @@ -22,21 +22,21 @@ pub enum PortfolioMessage { // Messages #[remain::unsorted] DocumentPassMessage { - document_id: u64, + document_id: DocumentId, message: DocumentMessage, }, AutoSaveActiveDocument, AutoSaveDocument { - document_id: u64, + document_id: DocumentId, }, CloseActiveDocumentWithConfirmation, CloseAllDocuments, CloseAllDocumentsWithConfirmation, CloseDocument { - document_id: u64, + document_id: DocumentId, }, CloseDocumentWithConfirmation { - document_id: u64, + document_id: DocumentId, }, Copy { clipboard: Clipboard, @@ -45,7 +45,7 @@ pub enum PortfolioMessage { clipboard: Clipboard, }, DeleteDocument { - document_id: u64, + document_id: DocumentId, }, DestroyAllDocuments, FontLoaded { @@ -65,7 +65,7 @@ pub enum PortfolioMessage { ImaginateServerHostname, Import, LoadDocumentResources { - document_id: u64, + document_id: DocumentId, }, LoadFont { font: Font, @@ -81,7 +81,7 @@ pub enum PortfolioMessage { document_serialized_content: String, }, OpenDocumentFileWithId { - document_id: u64, + document_id: DocumentId, document_name: String, document_is_auto_saved: bool, document_is_saved: bool, @@ -97,10 +97,10 @@ pub enum PortfolioMessage { }, PrevDocument, SelectDocument { - document_id: u64, + document_id: DocumentId, }, SetActiveDocument { - document_id: u64, + document_id: DocumentId, }, SubmitDocumentExport { file_name: String, @@ -110,8 +110,7 @@ pub enum PortfolioMessage { transparent_background: bool, }, SubmitGraphRender { - document_id: u64, - layer_path: Vec, + document_id: DocumentId, }, ToggleRulers, UpdateDocumentWidgets, diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 6c011ad620..da77df04d7 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -19,9 +19,9 @@ use std::sync::Arc; #[derive(Debug, Default)] pub struct PortfolioMessageHandler { menu_bar_message_handler: MenuBarMessageHandler, - documents: HashMap, - document_ids: Vec, - active_document_id: Option, + documents: HashMap, + document_ids: Vec, + active_document_id: Option, graph_view_overlay_open: bool, copy_buffer: [Vec; INTERNAL_CLIPBOARD_COUNT as usize], pub persistent_data: PersistentData, @@ -109,7 +109,7 @@ impl MessageHandler { + PortfolioMessage::SubmitGraphRender { document_id } => { let result = self.executor.submit_node_graph_evaluation( self.documents.get_mut(&document_id).expect("Tried to render no existent Document"), - layer_path, ipp.viewport_bounds.size().as_uvec2(), ); @@ -591,11 +590,11 @@ impl PortfolioMessageHandler { self.executor.introspect_node(node_path) } - pub fn document(&self, document_id: u64) -> Option<&DocumentMessageHandler> { + pub fn document(&self, document_id: DocumentId) -> Option<&DocumentMessageHandler> { self.documents.get(&document_id) } - pub fn document_mut(&mut self, document_id: u64) -> Option<&mut DocumentMessageHandler> { + pub fn document_mut(&mut self, document_id: DocumentId) -> Option<&mut DocumentMessageHandler> { self.documents.get_mut(&document_id) } @@ -607,7 +606,7 @@ impl PortfolioMessageHandler { self.active_document_id.and_then(|id| self.documents.get_mut(&id)) } - pub fn active_document_id(&self) -> Option { + pub fn active_document_id(&self) -> Option { self.active_document_id } @@ -637,7 +636,7 @@ impl PortfolioMessageHandler { } // TODO: Fix how this doesn't preserve tab order upon loading new document from *File > Load* - fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: u64, responses: &mut VecDeque) { + fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: DocumentId, responses: &mut VecDeque) { self.document_ids.push(document_id); new_document.update_layers_panel_options_bar_widgets(responses); @@ -667,7 +666,7 @@ impl PortfolioMessageHandler { self.document_ids.iter().map(|id| self.documents.get(id).expect("document id was not found in the document hashmap")) } - fn document_index(&self, document_id: u64) -> usize { + fn document_index(&self, document_id: DocumentId) -> usize { self.document_ids.iter().position(|id| id == &document_id).expect("Active document is missing from document ids") } diff --git a/editor/src/messages/prelude.rs b/editor/src/messages/prelude.rs index f014a65080..90e6c471bc 100644 --- a/editor/src/messages/prelude.rs +++ b/editor/src/messages/prelude.rs @@ -56,6 +56,9 @@ pub use graphite_proc_macros::*; pub use std::collections::{HashMap, HashSet, VecDeque}; +// TODO: Convert from a type alias to a newtype +pub type DocumentId = u64; + pub trait Responses { fn add(&mut self, message: impl Into); diff --git a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs index f86e992944..0649ecbb15 100644 --- a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs +++ b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs @@ -38,7 +38,7 @@ pub fn new_image_layer(image_frame: ImageFrame, id: NodeId, parent: Layer pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup], layer: LayerNodeIdentifier, mirror_angle: bool, responses: &mut VecDeque) { for manipulator_group in manipulator_groups { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id: manipulator_group.id, mirror_angle, @@ -216,7 +216,7 @@ impl<'a> NodeGraphLayer<'a> { } /// Return an iterator up the primary flow of the layer - pub fn primary_layer_flow(&self) -> impl Iterator { + pub fn primary_layer_flow(&self) -> impl Iterator { self.node_graph.upstream_flow_back_from_nodes(vec![self.layer_node], true) } diff --git a/editor/src/messages/tool/common_functionality/pivot.rs b/editor/src/messages/tool/common_functionality/pivot.rs index 1054d1ac34..859be5c489 100644 --- a/editor/src/messages/tool/common_functionality/pivot.rs +++ b/editor/src/messages/tool/common_functionality/pivot.rs @@ -105,7 +105,6 @@ impl Pivot { let pivot = transform.inverse().transform_point2(position); // Only update the pivot when computed position is finite. Infinite can happen when scale is 0. if pivot.is_finite() { - let layer = layer.to_path(); responses.add(GraphOperationMessage::TransformSetPivot { layer, pivot }); } } diff --git a/editor/src/messages/tool/common_functionality/resize.rs b/editor/src/messages/tool/common_functionality/resize.rs index 4490e99f27..d29187c018 100644 --- a/editor/src/messages/tool/common_functionality/resize.rs +++ b/editor/src/messages/tool/common_functionality/resize.rs @@ -17,7 +17,6 @@ impl Resize { /// Starts a resize, assigning the snap targets and snapping the starting position. pub fn start(&mut self, responses: &mut VecDeque, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) { self.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); let root_transform = document.metadata().document_to_viewport; self.drag_start = root_transform.inverse().transform_point2(self.snap_manager.snap_position(responses, document, input.mouse.position)); } @@ -25,7 +24,6 @@ impl Resize { /// Recalculates snap targets without snapping the starting position. pub fn recalculate_snaps(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) { self.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); } /// Calculate the drag start position in viewport space. @@ -65,7 +63,7 @@ impl Resize { Some( GraphOperationMessage::TransformSet { - layer: layer.to_path(), + layer, transform: DAffine2::from_scale_angle_translation(size, 0., start), transform_in: TransformIn::Viewport, skip_rerender, diff --git a/editor/src/messages/tool/common_functionality/shape_editor.rs b/editor/src/messages/tool/common_functionality/shape_editor.rs index c5f9f82d0a..9337cc3ba8 100644 --- a/editor/src/messages/tool/common_functionality/shape_editor.rs +++ b/editor/src/messages/tool/common_functionality/shape_editor.rs @@ -192,7 +192,7 @@ impl ShapeState { if point.manipulator_type.is_handle() { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id: group.id, mirror_angle: false }, }); } @@ -202,7 +202,7 @@ impl ShapeState { return; }; responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position: (position + delta) }, }); }; @@ -270,7 +270,7 @@ impl ShapeState { // Mirror the angle but not the distance responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id: manipulator.id, mirror_angle: true, @@ -291,7 +291,7 @@ impl ShapeState { if let Some(in_handle) = length_previous.map(|length| anchor_position + handle_vector * length) { let point = ManipulatorPointId::new(manipulator.id, SelectedType::InHandle); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position: in_handle }, }); } @@ -299,7 +299,7 @@ impl ShapeState { if let Some(out_handle) = length_next.map(|length| anchor_position - handle_vector * length) { let point = ManipulatorPointId::new(manipulator.id, SelectedType::OutHandle); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position: out_handle }, }); } @@ -338,7 +338,7 @@ impl ShapeState { let out_handle = ManipulatorPointId::new(point.group, SelectedType::OutHandle); if let Some(position) = group.out_handle { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point: out_handle, position }, }); } @@ -347,7 +347,7 @@ impl ShapeState { let in_handle = ManipulatorPointId::new(point.group, SelectedType::InHandle); if let Some(position) = group.in_handle { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point: in_handle, position }, }); } @@ -391,7 +391,7 @@ impl ShapeState { let Some(previous_position) = point.manipulator_type.get_position(group) else { return }; let position = previous_position + delta; responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position }, }); }; @@ -410,7 +410,7 @@ impl ShapeState { // and set angle mirroring to true. if !mirror && point.manipulator_type.opposite().get_position(group).is_none() { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id: group.id, mirror_angle: true }, }); mirror = true; @@ -428,7 +428,7 @@ impl ShapeState { } let position = group.anchor - (original_handle_position - group.anchor); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position }, }); } @@ -471,7 +471,7 @@ impl ShapeState { if (anchor_position - point_position).length() < DRAG_THRESHOLD { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::RemoveManipulatorPoint { point }, }); @@ -481,7 +481,7 @@ impl ShapeState { if let Some(lengths) = opposing_handle_lengths { if lengths.contains_key(&point.group) { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::RemoveManipulatorPoint { point: opposite_point }, }); } @@ -567,7 +567,7 @@ impl ShapeState { let Some(opposing_handle_length) = opposing_handle_length else { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::RemoveManipulatorPoint { point: ManipulatorPointId::new(manipulator_group.id, single_selected_handle.opposite()), }, @@ -586,7 +586,7 @@ impl ShapeState { assert!(position.is_finite(), "Opposing handle not finite!"); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position }, }); } @@ -596,10 +596,10 @@ impl ShapeState { /// Dissolve the selected points. pub fn delete_selected_points(&self, responses: &mut VecDeque) { - for (layer, state) in &self.selected_shape_state { + for (&layer, state) in &self.selected_shape_state { for &point in &state.selected_points { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::RemoveManipulatorPoint { point }, }) } @@ -608,10 +608,10 @@ impl ShapeState { /// Toggle if the handles should mirror angle across the anchor position. pub fn toggle_handle_mirroring_on_selected(&self, responses: &mut VecDeque) { - for (layer, state) in &self.selected_shape_state { + for (&layer, state) in &self.selected_shape_state { for point in &state.selected_points { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::ToggleManipulatorHandleMirroring { id: point.group }, }) } @@ -620,10 +620,10 @@ impl ShapeState { /// Toggle if the handles should mirror angle across the anchor position. pub fn set_handle_mirroring_on_selected(&self, mirror_angle: bool, responses: &mut VecDeque) { - for (layer, state) in &self.selected_shape_state { + for (&layer, state) in &self.selected_shape_state { for point in &state.selected_points { responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id: point.group, mirror_angle }, }); } @@ -732,7 +732,7 @@ impl ShapeState { let point = ManipulatorPointId::new(start, SelectedType::OutHandle); let position = first.handle_start().unwrap_or(first.start()); let out_handle = GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position }, }; responses.add(out_handle); @@ -740,7 +740,7 @@ impl ShapeState { // Insert a new manipulator group between the existing ones let manipulator_group = ManipulatorGroup::new(first.end(), first.handle_end(), second.handle_start()); let insert = GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::AddManipulatorGroup { manipulator_group, after_id: start }, }; responses.add(insert); @@ -749,7 +749,7 @@ impl ShapeState { let point = ManipulatorPointId::new(end, SelectedType::InHandle); let position = second.handle_end().unwrap_or(second.end()); let in_handle = GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position }, }; responses.add(in_handle); @@ -797,16 +797,16 @@ impl ShapeState { } else { let point = ManipulatorPointId::new(manipulator.id, SelectedType::InHandle); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position: anchor_position }, }); let point = ManipulatorPointId::new(manipulator.id, SelectedType::OutHandle); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position: anchor_position }, }); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id: manipulator.id, mirror_angle: false, diff --git a/editor/src/messages/tool/common_functionality/snapping.rs b/editor/src/messages/tool/common_functionality/snapping.rs index 3c99b5fb8a..65028a41c2 100644 --- a/editor/src/messages/tool/common_functionality/snapping.rs +++ b/editor/src/messages/tool/common_functionality/snapping.rs @@ -1,6 +1,4 @@ -use super::shape_editor::ManipulatorPointInfo; use crate::consts::{SNAP_AXIS_TOLERANCE, SNAP_POINT_TOLERANCE}; -use crate::messages::portfolio::document::utility_types::LayerId; use crate::messages::prelude::*; use glam::DVec2; @@ -100,23 +98,6 @@ impl SnapManager { } } - /// Adds all of the shape handles in the document, including bézier handles of the points specified - pub fn add_all_document_handles( - &mut self, - _document_message_handler: &DocumentMessageHandler, - _input: &InputPreprocessorMessageHandler, - _include_handles: &[&[LayerId]], - _exclude: &[&[LayerId]], - _ignore_points: &[ManipulatorPointInfo], - ) { - // for path in document_message_handler.all_layers() { - // if !exclude.contains(&path) { - // let layer = document_message_handler.document_legacy.layer(path).expect("Could not get layer for snapping"); - // self.add_snap_path(document_message_handler, input, layer, path, include_handles.contains(&path), ignore_points); - // } - // } - } - /// Finds the closest snap from an array of layers to the specified snap targets in viewport coords. /// Returns 0 for each axis that there is no snap less than the snap tolerance. pub fn snap_layers(&mut self, responses: &mut VecDeque, document_message_handler: &DocumentMessageHandler, snap_anchors: Vec, mouse_delta: DVec2) -> DVec2 { diff --git a/editor/src/messages/tool/tool_message_handler.rs b/editor/src/messages/tool/tool_message_handler.rs index 5e83424499..596efb05f6 100644 --- a/editor/src/messages/tool/tool_message_handler.rs +++ b/editor/src/messages/tool/tool_message_handler.rs @@ -16,13 +16,13 @@ pub struct ToolMessageHandler { pub shape_editor: ShapeState, } -impl MessageHandler for ToolMessageHandler { +impl MessageHandler for ToolMessageHandler { #[remain::check] fn process_message( &mut self, message: ToolMessage, responses: &mut VecDeque, - (document, document_id, input, persistent_data, node_graph): (&DocumentMessageHandler, u64, &InputPreprocessorMessageHandler, &PersistentData, &NodeGraphExecutor), + (document, document_id, input, persistent_data, node_graph): (&DocumentMessageHandler, DocumentId, &InputPreprocessorMessageHandler, &PersistentData, &NodeGraphExecutor), ) { let font_cache = &persistent_data.font_cache; diff --git a/editor/src/messages/tool/tool_messages/artboard_tool.rs b/editor/src/messages/tool/tool_messages/artboard_tool.rs index cbb6440aaa..0cbb7bee75 100644 --- a/editor/src/messages/tool/tool_messages/artboard_tool.rs +++ b/editor/src/messages/tool/tool_messages/artboard_tool.rs @@ -120,7 +120,6 @@ impl ArtboardToolData { let snap_y = selected_edges.0 || selected_edges.1; self.snap_manager.start_snap(document, input, document.bounding_boxes(), snap_x, snap_y); - self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); if let Some(bounds) = &mut self.bounding_box_manager { bounds.center_of_transformation = (bounds.bounds[0] + bounds.bounds[1]) / 2.; @@ -139,7 +138,6 @@ impl ArtboardToolData { self.selected_artboard = Some(intersection); self.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); true } else { @@ -279,7 +277,6 @@ impl Fsm for ArtboardToolFsmState { tool_data.selected_artboard = Some(LayerNodeIdentifier::new_unchecked(id)); tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); responses.add(GraphOperationMessage::NewArtboard { id, diff --git a/editor/src/messages/tool/tool_messages/brush_tool.rs b/editor/src/messages/tool/tool_messages/brush_tool.rs index dfc44ac423..0dad7bb11d 100644 --- a/editor/src/messages/tool/tool_messages/brush_tool.rs +++ b/editor/src/messages/tool/tool_messages/brush_tool.rs @@ -301,7 +301,7 @@ impl BrushToolData { fn update_strokes(&self, responses: &mut VecDeque) { let Some(layer) = self.layer else { return }; let strokes = self.strokes.clone(); - responses.add(GraphOperationMessage::Brush { layer: layer.to_path(), strokes }); + responses.add(GraphOperationMessage::Brush { layer, strokes }); } } diff --git a/editor/src/messages/tool/tool_messages/ellipse_tool.rs b/editor/src/messages/tool/tool_messages/ellipse_tool.rs index 89f05a4aea..211248e4bb 100644 --- a/editor/src/messages/tool/tool_messages/ellipse_tool.rs +++ b/editor/src/messages/tool/tool_messages/ellipse_tool.rs @@ -80,7 +80,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .unit(" px") .label("Weight") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(|number_input: &NumberInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) .widget_holder() } @@ -211,12 +211,12 @@ impl Fsm for EllipseToolFsmState { let fill_color = tool_options.fill.active_color(); responses.add(GraphOperationMessage::FillSet { - layer: layer.to_path(), + layer, fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None }, }); responses.add(GraphOperationMessage::StrokeSet { - layer: layer.to_path(), + layer, stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight), }); diff --git a/editor/src/messages/tool/tool_messages/fill_tool.rs b/editor/src/messages/tool/tool_messages/fill_tool.rs index 23dc27fd0f..f1b4f2f54b 100644 --- a/editor/src/messages/tool/tool_messages/fill_tool.rs +++ b/editor/src/messages/tool/tool_messages/fill_tool.rs @@ -72,8 +72,6 @@ impl Fsm for FillToolFsmState { let Some(layer_identifier) = document.click(input.mouse.position, &document.network) else { return self; }; - let layer = layer_identifier.to_path(); - let color = match event { FillToolMessage::LeftPointerDown => global_tool_data.primary_color, FillToolMessage::RightPointerDown => global_tool_data.secondary_color, @@ -81,7 +79,7 @@ impl Fsm for FillToolFsmState { let fill = Fill::Solid(color); responses.add(DocumentMessage::StartTransaction); - responses.add(GraphOperationMessage::FillSet { layer, fill }); + responses.add(GraphOperationMessage::FillSet { layer: layer_identifier, fill }); responses.add(DocumentMessage::CommitTransaction); FillToolFsmState::Ready diff --git a/editor/src/messages/tool/tool_messages/freehand_tool.rs b/editor/src/messages/tool/tool_messages/freehand_tool.rs index 25b22ad9be..a75947e594 100644 --- a/editor/src/messages/tool/tool_messages/freehand_tool.rs +++ b/editor/src/messages/tool/tool_messages/freehand_tool.rs @@ -87,7 +87,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .unit(" px") .label("Weight") .min(1.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(|number_input: &NumberInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) .widget_holder() } @@ -215,12 +215,12 @@ impl Fsm for FreehandToolFsmState { tool_data.layer = Some(layer); responses.add(GraphOperationMessage::FillSet { - layer: layer.to_path(), + layer, fill: if let Some(color) = tool_options.fill.active_color() { Fill::Solid(color) } else { Fill::None }, }); responses.add(GraphOperationMessage::StrokeSet { - layer: layer.to_path(), + layer, stroke: Stroke::new(tool_options.stroke.active_color(), tool_data.weight), }); @@ -234,7 +234,7 @@ impl Fsm for FreehandToolFsmState { if tool_data.last_point != pos { let manipulator_group = ManipulatorGroup::new_anchor(pos); let modification = VectorDataModification::AddEndManipulatorGroup { subpath_index: 0, manipulator_group }; - responses.add(GraphOperationMessage::Vector { layer: layer.to_path(), modification }); + responses.add(GraphOperationMessage::Vector { layer, modification }); tool_data.dragged = true; tool_data.last_point = pos; } diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index cb84590bad..1f55d0a4e9 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -1,5 +1,4 @@ use super::tool_prelude::*; -use crate::application::generate_uuid; use crate::consts::{LINE_ROTATE_SNAP_ANGLE, MANIPULATOR_GROUP_MARKER_SIZE, SELECTION_THRESHOLD}; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; @@ -235,9 +234,10 @@ impl SelectedGradient { /// Update the layer fill to the current gradient pub fn render_gradient(&mut self, responses: &mut VecDeque) { self.gradient.transform = self.transform; - let fill = Fill::Gradient(self.gradient.clone()); - let layer = self.layer.to_path(); - responses.add(GraphOperationMessage::FillSet { layer, fill }); + responses.add(GraphOperationMessage::FillSet { + layer: self.layer, + fill: Fill::Gradient(self.gradient.clone()), + }); } } @@ -269,7 +269,6 @@ struct GradientToolData { pub fn start_snap(snap_manager: &mut SnapManager, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) { snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - snap_manager.add_all_document_handles(document, input, &[], &[], &[]); } impl Fsm for GradientToolFsmState { @@ -338,9 +337,10 @@ impl Fsm for GradientToolFsmState { // The gradient has only one point and so should become a fill if selected_gradient.gradient.positions.len() == 1 { - let fill = Fill::Solid(selected_gradient.gradient.positions[0].1.unwrap_or(Color::BLACK)); - let layer = selected_gradient.layer.to_path(); - responses.add(GraphOperationMessage::FillSet { layer, fill }); + responses.add(GraphOperationMessage::FillSet { + layer: selected_gradient.layer, + fill: Fill::Solid(selected_gradient.gradient.positions[0].1.unwrap_or(Color::BLACK)), + }); return self; } @@ -467,7 +467,6 @@ impl Fsm for GradientToolFsmState { DVec2::ONE, global_tool_data.primary_color, DAffine2::IDENTITY, - generate_uuid(), tool_options.gradient_type, ) }; diff --git a/editor/src/messages/tool/tool_messages/imaginate_tool.rs b/editor/src/messages/tool/tool_messages/imaginate_tool.rs index 16403a8b67..c22d03e626 100644 --- a/editor/src/messages/tool/tool_messages/imaginate_tool.rs +++ b/editor/src/messages/tool/tool_messages/imaginate_tool.rs @@ -172,10 +172,6 @@ impl Fsm for ImaginateToolFsmState { state } (ImaginateToolFsmState::Drawing, ImaginateToolMessage::DragStop) => { - if let Some(layer) = &shape_data.layer { - responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path: layer.to_path() }); - } - input.mouse.finish_transaction(shape_data.viewport_drag_start(document), responses); shape_data.cleanup(responses); diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index ec8977e6bc..47edbb75ab 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -81,7 +81,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .unit(" px") .label("Weight") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(|number_input: &NumberInput| LineToolMessage::UpdateOptions(LineOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) .widget_holder() } @@ -175,7 +175,6 @@ impl Fsm for LineToolFsmState { match (self, event) { (LineToolFsmState::Ready, LineToolMessage::DragStart) => { tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); let viewport_start = tool_data.snap_manager.snap_position(responses, document, input.mouse.position); tool_data.drag_start = document.metadata().document_to_viewport.inverse().transform_point2(viewport_start); @@ -186,7 +185,7 @@ impl Fsm for LineToolFsmState { let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses); responses.add(GraphOperationMessage::StrokeSet { - layer: layer.to_path(), + layer, stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight), }); tool_data.layer = Some(layer); @@ -280,7 +279,7 @@ fn generate_transform(tool_data: &mut LineToolData, document_to_viewport: DAffin } GraphOperationMessage::TransformSet { - layer: tool_data.layer.unwrap().to_path(), + layer: tool_data.layer.unwrap(), transform: glam::DAffine2::from_scale_angle_translation(DVec2::new(line_length, 1.), angle, start), transform_in: TransformIn::Viewport, skip_rerender: false, diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 1a0601ae92..4dbe057aa8 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -91,8 +91,8 @@ impl LayoutHolder for PathTool { .label("X") .min_width(120) .disabled(x.is_none()) - .min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64)) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .min(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(move |number_input: &NumberInput| { let new_x = number_input.value.unwrap_or(x.unwrap()); PathToolMessage::SelectedPointXChanged { new_x }.into() @@ -104,8 +104,8 @@ impl LayoutHolder for PathTool { .label("Y") .min_width(120) .disabled(y.is_none()) - .min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64)) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .min(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(move |number_input: &NumberInput| { let new_y = number_input.value.unwrap_or(y.unwrap()); PathToolMessage::SelectedPointYChanged { new_y }.into() @@ -275,9 +275,6 @@ impl PathToolData { } selected_points.points.extend(additional_selected_points); - //let include_handles: Vec<_> = selected_layers.iter().map(|x| x.as_slice()).collect(); - //self.snap_manager.add_all_document_handles(document, input, &include_handles, &[], &selected_points.points); - self.drag_start_pos = input.mouse.position; self.previous_mouse_position = input.mouse.position - selected_points.offset; } diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index c3b2245f9a..1165e0de1a 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -102,7 +102,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .unit(" px") .label("Weight") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(|number_input: &NumberInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) .widget_holder() } @@ -226,7 +226,7 @@ impl PenToolData { }; responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id: last_handle.id, mirror_angle: false, @@ -259,12 +259,12 @@ impl PenToolData { self.layer = Some(layer); responses.add(GraphOperationMessage::FillSet { - layer: layer.to_path(), + layer, fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None }, }); responses.add(GraphOperationMessage::StrokeSet { - layer: layer.to_path(), + layer, stroke: Stroke::new(stroke_color, line_weight), }); @@ -298,21 +298,21 @@ impl PenToolData { } // Remove the point that has just been placed responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id }, }); // Move the in handle of the previous anchor to on top of the previous position let point = ManipulatorPointId::new(previous_manipulator_group.id, outwards_handle); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position: previous_anchor }, }); // Stop the handles on the last point from mirroring let id = previous_manipulator_group.id; responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: false }, }); @@ -353,26 +353,26 @@ impl PenToolData { // Move the in handle of the first point to where the user has placed it let point = ManipulatorPointId::new(first_manipulator_group.id, inwards_handle); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position: last_in }, }); // Stop the handles on the first point from mirroring let id = first_manipulator_group.id; responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: false }, }); // Remove the point that has just been placed responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id }, }); // Push a close path node responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetClosed { index: 0, closed: true }, }); @@ -387,7 +387,7 @@ impl PenToolData { } // Add a new manipulator for the next anchor that we will place if let Some(out_handle) = outwards_handle.get_position(last_manipulator_group) { - responses.add(add_manipulator_group(&self.layer, self.from_start, bezier_rs::ManipulatorGroup::new_anchor(out_handle))); + responses.add(add_manipulator_group(self.layer, self.from_start, bezier_rs::ManipulatorGroup::new_anchor(out_handle))); } Some(PenToolFsmState::PlacingAnchor) @@ -419,7 +419,7 @@ impl PenToolData { // Update points on current segment (to show preview of new handle) let point = ManipulatorPointId::new(last_manipulator_group.id, outwards_handle); responses.add(GraphOperationMessage::Vector { - layer: self.layer?.to_path(), + layer: self.layer?, modification: VectorDataModification::SetManipulatorPosition { point, position: pos }, }); @@ -430,7 +430,7 @@ impl PenToolData { let pos = last_anchor - (pos - last_anchor); let point = ManipulatorPointId::new(last_manipulator_group.id, inwards_handle); responses.add(GraphOperationMessage::Vector { - layer: self.layer?.to_path(), + layer: self.layer?, modification: VectorDataModification::SetManipulatorPosition { point, position: pos }, }); } @@ -438,7 +438,7 @@ impl PenToolData { // Update the mirror status of the currently modifying point let id = last_manipulator_group.id; responses.add(GraphOperationMessage::Vector { - layer: self.layer?.to_path(), + layer: self.layer?, modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: should_mirror }, }); @@ -483,7 +483,7 @@ impl PenToolData { for manipulator_type in [SelectedType::Anchor, SelectedType::InHandle, SelectedType::OutHandle] { let point = ManipulatorPointId::new(last_manipulator_group.id, manipulator_type); responses.add(GraphOperationMessage::Vector { - layer: layer.to_path(), + layer, modification: VectorDataModification::SetManipulatorPosition { point, position: pos }, }); } @@ -516,7 +516,7 @@ impl PenToolData { // Remove the unplaced anchor if in anchor placing mode if fsm == PenToolFsmState::PlacingAnchor { responses.add(GraphOperationMessage::Vector { - layer: self.layer?.to_path(), + layer: self.layer?, modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id }, }); last_manipulator_group = previous_manipulator_group; @@ -526,7 +526,7 @@ impl PenToolData { let point = ManipulatorPointId::new(last_manipulator_group.id, outwards_handle); let position = last_manipulator_group.anchor; responses.add(GraphOperationMessage::Vector { - layer: self.layer?.to_path(), + layer: self.layer?, modification: VectorDataModification::SetManipulatorPosition { point, position }, }); @@ -591,7 +591,6 @@ impl Fsm for PenToolFsmState { // Initialize snapping tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); // Disable this tool's mirroring tool_data.should_mirror = false; @@ -703,11 +702,10 @@ fn compute_snapped_angle(cached_angle: &mut f64, lock_angle: bool, snap_angle: b } /// Pushes a [ManipulatorGroup] to the current layer via a [GraphOperationMessage]. -fn add_manipulator_group(layer: &Option, from_start: bool, manipulator_group: bezier_rs::ManipulatorGroup) -> Message { +fn add_manipulator_group(layer: Option, from_start: bool, manipulator_group: bezier_rs::ManipulatorGroup) -> Message { let Some(layer) = layer else { return Message::NoOp; }; - let layer = layer.to_path(); let modification = if from_start { VectorDataModification::AddStartManipulatorGroup { subpath_index: 0, manipulator_group } } else { diff --git a/editor/src/messages/tool/tool_messages/polygon_tool.rs b/editor/src/messages/tool/tool_messages/polygon_tool.rs index 20c9d278c2..9031089778 100644 --- a/editor/src/messages/tool/tool_messages/polygon_tool.rs +++ b/editor/src/messages/tool/tool_messages/polygon_tool.rs @@ -111,7 +111,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .unit(" px") .label("Weight") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(|number_input: &NumberInput| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) .widget_holder() } @@ -251,12 +251,12 @@ impl Fsm for PolygonToolFsmState { let fill_color = tool_options.fill.active_color(); responses.add(GraphOperationMessage::FillSet { - layer: layer.to_path(), + layer, fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None }, }); responses.add(GraphOperationMessage::StrokeSet { - layer: layer.to_path(), + layer, stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight), }); diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index 730641b1a2..e6890410d8 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -68,7 +68,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .unit(" px") .label("Weight") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(|number_input: &NumberInput| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) .widget_holder() } @@ -220,12 +220,12 @@ impl Fsm for RectangleToolFsmState { let fill_color = tool_options.fill.active_color(); responses.add(GraphOperationMessage::FillSet { - layer: layer.to_path(), + layer, fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None }, }); responses.add(GraphOperationMessage::StrokeSet { - layer: layer.to_path(), + layer, stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight), }); diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index a37be17b28..0a2efbbe0b 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -302,10 +302,10 @@ impl SelectToolData { // Duplicate each previously selected layer and select the new ones. for layer_ancestors in document.metadata().shallowest_unique_layers(self.layers_dragging.iter().copied()) { - let layer = layer_ancestors.last().unwrap(); + let layer = *layer_ancestors.last().unwrap(); // Moves the original back to its starting position. responses.add_front(GraphOperationMessage::TransformChange { - layer: layer.to_path(), + layer, transform: DAffine2::from_translation(self.drag_start - self.drag_current), transform_in: TransformIn::Viewport, skip_rerender: true, @@ -336,11 +336,6 @@ impl SelectToolData { // layer_metadata, // }); } - - // // Since the selected layers have now moved back to their original transforms before the drag began, we rerender them to be displayed as if they weren't touched. - // for layer_path in self.not_duplicated_layers.iter().flatten() { - // responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path: layer_path.clone() }); - // } } /// Removes the duplicated layers. Called when Alt is released and the layers have previously been duplicated. @@ -361,7 +356,7 @@ impl SelectToolData { // Move the original to under the mouse for layer_ancestors in document.metadata().shallowest_unique_layers(originals.iter().copied()) { responses.add_front(GraphOperationMessage::TransformChange { - layer: layer_ancestors.last().unwrap().to_path(), + layer: *layer_ancestors.last().unwrap(), transform: DAffine2::from_translation(self.drag_current - self.drag_start), transform_in: TransformIn::Viewport, skip_rerender: true, @@ -482,22 +477,11 @@ impl Fsm for SelectToolFsmState { responses.add(DocumentMessage::StartTransaction); tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); SelectToolFsmState::DraggingPivot } else if let Some(_selected_edges) = dragging_bounds { responses.add(DocumentMessage::StartTransaction); - // let snap_x = selected_edges.2 || selected_edges.3; - // let snap_y = selected_edges.0 || selected_edges.1; - // - // tool_data - // .snap_manager - // .start_snap(document, input, document.bounding_boxes(Some(&selected), None, font_cache), snap_x, snap_y); - // tool_data - // .snap_manager - // .add_all_document_handles(document, input, &[], &selected.iter().map(|x| x.as_slice()).collect::>(), &[]); - tool_data.layers_dragging = selected; if let Some(bounds) = &mut tool_data.bounding_box_manager { @@ -606,7 +590,7 @@ impl Fsm for SelectToolFsmState { // TODO: Cache the result of `shallowest_unique_layers` to avoid this heavy computation every frame of movement, see https://github.com/GraphiteEditor/Graphite/pull/481 for layer_ancestors in document.metadata().shallowest_unique_layers(tool_data.layers_dragging.iter().copied()) { responses.add_front(GraphOperationMessage::TransformChange { - layer: layer_ancestors.last().unwrap().to_path(), + layer: *layer_ancestors.last().unwrap(), transform: DAffine2::from_translation(mouse_delta + closest_move), transform_in: TransformIn::Viewport, skip_rerender: false, diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index f732b4c906..dc104367c5 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -89,7 +89,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .unit(" px") .label("Weight") .min(0.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(|number_input: &NumberInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) .widget_holder() } @@ -215,7 +215,6 @@ impl Fsm for SplineToolFsmState { let transform = document.metadata().transform_to_viewport(parent); tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); - tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); let snapped_position = tool_data.snap_manager.snap_position(responses, document, input.mouse.position); let pos = transform.inverse().transform_point2(snapped_position); @@ -228,12 +227,12 @@ impl Fsm for SplineToolFsmState { let layer = graph_modification_utils::new_vector_layer(vec![], generate_uuid(), parent, responses); responses.add(GraphOperationMessage::FillSet { - layer: layer.to_path(), + layer, fill: if let Some(color) = tool_options.fill.active_color() { Fill::Solid(color) } else { Fill::None }, }); responses.add(GraphOperationMessage::StrokeSet { - layer: layer.to_path(), + layer, stroke: Stroke::new(tool_options.stroke.active_color(), tool_data.weight), }); tool_data.layer = Some(layer); @@ -329,5 +328,5 @@ fn update_spline(tool_data: &SplineToolData, show_preview: bool, responses: &mut graph_modification_utils::set_manipulator_mirror_angle(subpath.manipulator_groups(), layer, true, responses); let subpaths = vec![subpath]; let modification = VectorDataModification::UpdateSubpaths { subpaths }; - responses.add_front(GraphOperationMessage::Vector { layer: layer.to_path(), modification }); + responses.add_front(GraphOperationMessage::Vector { layer, modification }); } diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 363010120b..27e9b4b47f 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -113,7 +113,7 @@ fn create_text_widgets(tool: &TextTool) -> Vec { .label("Size") .int() .min(1.) - .max((1u64 << std::f64::MANTISSA_DIGITS) as f64) + .max((1_u64 << std::f64::MANTISSA_DIGITS) as f64) .on_update(|number_input: &NumberInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::FontSize(number_input.value.unwrap() as u32)).into()) .widget_holder(); vec![ @@ -298,11 +298,11 @@ impl TextToolData { insert_index: -1, }); responses.add(GraphOperationMessage::FillSet { - layer: self.layer.to_path(), + layer: self.layer, fill: if editing_text.color.is_some() { Fill::Solid(editing_text.color.unwrap()) } else { Fill::None }, }); responses.add(GraphOperationMessage::TransformSet { - layer: self.layer.to_path(), + layer: self.layer, transform: editing_text.transform, transform_in: TransformIn::Viewport, skip_rerender: true, @@ -310,7 +310,7 @@ impl TextToolData { self.set_editing(true, font_cache, document, responses); - responses.add(NodeGraphMessage::SelectedNodesSet { nodes: self.layer.to_path() }); + responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![self.layer.to_node()] }); TextToolFsmState::Editing } else { @@ -331,10 +331,11 @@ impl TextToolData { } fn fix_text_bounds(&self, new_text: &str, _document: &DocumentMessageHandler, font_cache: &FontCache, responses: &mut VecDeque) -> Option<()> { - let layer = self.layer.to_path(); - let old_bounds = self.get_bounds(&self.editing_text.as_ref()?.text, font_cache)?; - let new_bounds = self.get_bounds(new_text, font_cache)?; - responses.add(GraphOperationMessage::UpdateBounds { layer, old_bounds, new_bounds }); + responses.add(GraphOperationMessage::UpdateBounds { + layer: self.layer, + old_bounds: self.get_bounds(&self.editing_text.as_ref()?.text, font_cache)?, + new_bounds: self.get_bounds(new_text, font_cache)?, + }); Some(()) } @@ -437,7 +438,6 @@ impl Fsm for TextToolFsmState { (TextToolFsmState::Editing, TextToolMessage::TextChange { new_text }) => { tool_data.fix_text_bounds(&new_text, document, font_cache, responses); responses.add(NodeGraphMessage::SetQualifiedInputValue { - layer_path: Vec::new(), node_path: vec![graph_modification_utils::get_text_id(tool_data.layer, &document.network).unwrap()], input_index: 1, value: TaggedValue::String(new_text), diff --git a/editor/src/messages/tool/utility_types.rs b/editor/src/messages/tool/utility_types.rs index 93d380cf20..9d0e30e6c9 100644 --- a/editor/src/messages/tool/utility_types.rs +++ b/editor/src/messages/tool/utility_types.rs @@ -20,7 +20,7 @@ use std::fmt::{self, Debug}; pub struct ToolActionHandlerData<'a> { pub document: &'a DocumentMessageHandler, - pub document_id: u64, + pub document_id: DocumentId, pub global_tool_data: &'a DocumentToolData, pub input: &'a InputPreprocessorMessageHandler, pub font_cache: &'a FontCache, @@ -30,7 +30,7 @@ pub struct ToolActionHandlerData<'a> { impl<'a> ToolActionHandlerData<'a> { pub fn new( document: &'a DocumentMessageHandler, - document_id: u64, + document_id: DocumentId, global_tool_data: &'a DocumentToolData, input: &'a InputPreprocessorMessageHandler, font_cache: &'a FontCache, diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index 3a98a96a9d..038b471571 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -5,23 +5,22 @@ use crate::messages::portfolio::document::node_graph::wrap_network_in_scope; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::layer_panel::LayerClassification; use crate::messages::portfolio::document::utility_types::misc::LayerPanelEntry; -use crate::messages::portfolio::document::utility_types::LayerId; use crate::messages::prelude::*; +use graph_craft::concrete; use graph_craft::document::value::TaggedValue; use graph_craft::document::{generate_uuid, DocumentNodeImplementation, NodeId, NodeNetwork}; use graph_craft::graphene_compiler::Compiler; use graph_craft::imaginate_input::ImaginatePreferences; -use graph_craft::{concrete, Type}; -use graphene_core::application_io::{ApplicationIo, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig}; +use graphene_core::application_io::{NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig}; use graphene_core::memo::IORecord; use graphene_core::raster::{Image, ImageFrame}; -use graphene_core::renderer::{ClickTarget, GraphicElementRendered, SvgSegment, SvgSegmentList}; +use graphene_core::renderer::{ClickTarget, GraphicElementRendered, SvgSegmentList}; use graphene_core::text::FontCache; use graphene_core::transform::{Footprint, Transform}; use graphene_core::vector::style::ViewMode; use graphene_core::vector::VectorData; -use graphene_core::{Color, GraphicElement, SurfaceFrame, SurfaceId}; +use graphene_core::{Color, GraphicElement, SurfaceFrame}; use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi}; use interpreted_executor::dynamic_executor::DynamicExecutor; @@ -31,22 +30,6 @@ use std::rc::Rc; use std::sync::mpsc::{Receiver, Sender}; use std::sync::Arc; -/// Identifies a node graph, either the document graph or a node graph associated with a legacy layer. -#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] -pub enum GraphIdentifier { - DocumentGraph, - LayerGraph(LayerId), -} - -impl GraphIdentifier { - pub const fn new(layer_id: Option) -> Self { - match layer_id { - Some(layer_id) => Self::LayerGraph(layer_id), - None => Self::DocumentGraph, - } - } -} - pub struct NodeRuntime { pub(crate) executor: DynamicExecutor, font_cache: FontCache, @@ -58,7 +41,6 @@ pub struct NodeRuntime { pub(crate) click_targets: HashMap>, pub(crate) upstream_transforms: HashMap, graph_hash: Option, - canvas_cache: HashMap, SurfaceId>, monitor_nodes: Vec>, } @@ -81,7 +63,6 @@ pub struct ExportConfig { pub(crate) struct GenerationRequest { generation_id: u64, graph: NodeNetwork, - path: Vec, render_config: RenderConfig, } @@ -129,7 +110,6 @@ impl NodeRuntime { imaginate_preferences: Default::default(), thumbnails: Default::default(), wasm_io: None, - canvas_cache: HashMap::new(), click_targets: HashMap::new(), graph_hash: None, upstream_transforms: HashMap::new(), @@ -142,7 +122,7 @@ impl NodeRuntime { // This should be avoided in the future. requests.reverse(); requests.dedup_by_key(|x| match x { - NodeRuntimeMessage::GenerationRequest(x) => Some(x.path.clone()), + NodeRuntimeMessage::GenerationRequest(x) => Some(x.graph.current_hash()), _ => None, }); requests.reverse(); @@ -151,17 +131,13 @@ impl NodeRuntime { NodeRuntimeMessage::FontCacheUpdate(font_cache) => self.font_cache = font_cache, NodeRuntimeMessage::ImaginatePreferencesUpdate(preferences) => self.imaginate_preferences = preferences, NodeRuntimeMessage::GenerationRequest(GenerationRequest { - generation_id, - graph, - render_config, - path, - .. + generation_id, graph, render_config, .. }) => { let transform = render_config.viewport.transform; - let result = self.execute_network(&path, graph, render_config).await; + let result = self.execute_network(graph, render_config).await; let mut responses = VecDeque::new(); - self.update_thumbnails(&path, &mut responses); + self.update_thumbnails(&mut responses); self.update_upstream_transforms(); let response = GenerationResponse { @@ -179,7 +155,7 @@ impl NodeRuntime { } } - async fn execute_network<'a>(&'a mut self, path: &[LayerId], graph: NodeNetwork, render_config: RenderConfig) -> Result { + async fn execute_network<'a>(&'a mut self, graph: NodeNetwork, render_config: RenderConfig) -> Result { if self.wasm_io.is_none() { self.wasm_io = Some(WasmApplicationIo::new().await); } @@ -245,21 +221,21 @@ impl NodeRuntime { Err(e) => return Err(e), }; - if let TaggedValue::SurfaceFrame(SurfaceFrame { surface_id, transform: _ }) = result { - let old_id = self.canvas_cache.insert(path.to_vec(), surface_id); - if let Some(old_id) = old_id { - if old_id != surface_id { - if let Some(io) = self.wasm_io.as_ref() { - io.destroy_surface(old_id) - } - } - } - } + // if let TaggedValue::SurfaceFrame(SurfaceFrame { surface_id, transform: _ }) = result { + // let old_id = self.canvas_cache.insert(path.to_vec(), surface_id); + // if let Some(old_id) = old_id { + // if old_id != surface_id { + // if let Some(io) = self.wasm_io.as_ref() { + // io.destroy_surface(old_id) + // } + // } + // } + // } Ok(result) } /// Recomputes the thumbnails for the layers in the graph, modifying the state and updating the UI. - pub fn update_thumbnails(&mut self, layer_path: &[LayerId], responses: &mut VecDeque) { + pub fn update_thumbnails(&mut self, responses: &mut VecDeque) { let mut image_data: Vec<_> = Vec::new(); self.thumbnails.retain(|id, _| self.monitor_nodes.iter().any(|node_path| node_path.contains(id))); for node_path in &self.monitor_nodes { @@ -299,8 +275,7 @@ impl NodeRuntime { } let resize = Some(DVec2::splat(100.)); - let create_image_data = |(node_id, image)| NodeGraphExecutor::to_frontend_image_data(image, None, layer_path, Some(node_id), resize).ok(); - image_data.extend(render.image_data.into_iter().filter_map(create_image_data)) + image_data.extend(render.image_data.into_iter().filter_map(|(_, image)| NodeGraphExecutor::to_frontend_image_data(image, resize).ok())) } if !image_data.is_empty() { responses.add(FrontendMessage::UpdateImageData { document_id: 0, image_data }); @@ -370,15 +345,11 @@ pub async fn run_node_graph() { pub struct NodeGraphExecutor { sender: Sender, receiver: Receiver, - // TODO: This is a memory leak since layers are never removed - pub(crate) last_output_type: HashMap, Option>, - pub(crate) thumbnails: HashMap, futures: HashMap, } #[derive(Debug, Clone)] struct ExecutionContext { - layer_path: Vec, export_config: Option, } @@ -394,18 +365,15 @@ impl Default for NodeGraphExecutor { futures: Default::default(), sender: request_sender, receiver: response_receiver, - last_output_type: Default::default(), - thumbnails: Default::default(), } } } impl NodeGraphExecutor { /// Execute the network by flattening it and creating a borrow stack. - fn queue_execution(&self, network: NodeNetwork, layer_path: Vec, render_config: RenderConfig) -> u64 { + fn queue_execution(&self, network: NodeNetwork, render_config: RenderConfig) -> u64 { let generation_id = generate_uuid(); let request = GenerationRequest { - path: layer_path, graph: network, generation_id, render_config, @@ -470,23 +438,17 @@ impl NodeGraphExecutor { } /// Generate a new [`FrontendImageData`] from the [`Image`]. - fn to_frontend_image_data(image: Image, transform: Option<[f64; 6]>, layer_path: &[LayerId], node_id: Option, resize: Option) -> Result { + fn to_frontend_image_data(image: Image, resize: Option) -> Result { let (image_data, _size) = Self::encode_img(image, resize, image::ImageOutputFormat::Bmp)?; let mime = "image/bmp".to_string(); let image_data = std::sync::Arc::new(image_data); - Ok(FrontendImageData { - path: layer_path.to_vec(), - node_id, - image_data, - mime, - transform, - }) + Ok(FrontendImageData { image_data, mime }) } /// Evaluates a node graph, computing the entire graph - pub fn submit_node_graph_evaluation(&mut self, document: &mut DocumentMessageHandler, layer_path: Vec, viewport_resolution: UVec2) -> Result<(), String> { + pub fn submit_node_graph_evaluation(&mut self, document: &mut DocumentMessageHandler, viewport_resolution: UVec2) -> Result<(), String> { // Get the node graph layer let network = document.network().clone(); @@ -506,9 +468,9 @@ impl NodeGraphExecutor { }; // Execute the node graph - let generation_id = self.queue_execution(network, layer_path.clone(), render_config); + let generation_id = self.queue_execution(network, render_config); - self.futures.insert(generation_id, ExecutionContext { layer_path, export_config: None }); + self.futures.insert(generation_id, ExecutionContext { export_config: None }); Ok(()) } @@ -541,11 +503,8 @@ impl NodeGraphExecutor { export_config.size = size; // Execute the node graph - let generation_id = self.queue_execution(network, Vec::new(), render_config); - let execution_context = ExecutionContext { - layer_path: Vec::new(), - export_config: Some(export_config), - }; + let generation_id = self.queue_execution(network, render_config); + let execution_context = ExecutionContext { export_config: Some(export_config) }; self.futures.insert(generation_id, execution_context); Ok(()) @@ -626,16 +585,17 @@ impl NodeGraphExecutor { }, expanded: layer.has_children(document_metadata) && !collapsed.contains(&layer), selected: document_metadata.selected_layers_contains(layer), - path: vec![node_id], + parent_id: layer.parent(document_metadata).map(|parent| parent.to_node()), + id: node_id, + depth: layer.ancestors(document_metadata).count() - 1, thumbnail: svg.to_string(), }, }); } - self.thumbnails = new_thumbnails; document_metadata.update_transforms(new_upstream_transforms); document_metadata.update_click_targets(new_click_targets); responses.extend(updates); - self.process_node_graph_output(node_graph_output, execution_context.layer_path.clone(), transform, responses)?; + self.process_node_graph_output(node_graph_output, transform, responses)?; responses.add(DocumentMessage::RenderDocument); responses.add(DocumentMessage::DocumentStructureChanged); responses.add(BroadcastEvent::DocumentIsDirty); @@ -665,8 +625,7 @@ impl NodeGraphExecutor { responses.add(FrontendMessage::UpdateDocumentArtwork { svg }); } - fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, layer_path: Vec, transform: DAffine2, responses: &mut VecDeque) -> Result<(), String> { - self.last_output_type.insert(layer_path.clone(), Some(node_graph_output.ty())); + fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, transform: DAffine2, responses: &mut VecDeque) -> Result<(), String> { match node_graph_output { TaggedValue::SurfaceFrame(SurfaceFrame { surface_id: _, transform: _ }) => { // TODO: Reimplement this now that document-legacy is gone @@ -709,19 +668,4 @@ impl NodeGraphExecutor { }; Ok(()) } - - /// When a blob url for a thumbnail is loaded, update the state and the UI. - pub fn insert_thumbnail_blob_url(&mut self, blob_url: String, node_id: NodeId, responses: &mut VecDeque) { - for segment_list in self.thumbnails.values_mut() { - if let Some(segment) = segment_list.iter_mut().find(|segment| **segment == SvgSegment::BlobUrl(node_id)) { - *segment = SvgSegment::String(blob_url); - responses.add(FrontendMessage::UpdateNodeThumbnail { - id: node_id, - value: segment_list.to_string(), - }); - return; - } - } - warn!("Received blob url for invalid segment") - } } diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs index acbd9cdaa5..f53cbf3c8a 100644 --- a/frontend/src-tauri/src/main.rs +++ b/frontend/src-tauri/src/main.rs @@ -4,36 +4,35 @@ use graphite_editor::application::Editor; use graphite_editor::messages::frontend::utility_types::FrontendImageData; use graphite_editor::messages::prelude::*; -use axum::body::StreamBody; -use axum::extract::Path; -use axum::http; -use axum::response::IntoResponse; +// use axum::body::StreamBody; +// use axum::extract::Path; +// use axum::http; +// use axum::response::IntoResponse; use axum::routing::get; use axum::Router; use fern::colors::{Color, ColoredLevelConfig}; -use http::{Response, StatusCode}; +// use http::{Response, StatusCode}; use std::cell::RefCell; -use std::collections::HashMap; +// use std::collections::HashMap; use std::sync::Arc; -use std::sync::Mutex; +// use std::sync::Mutex; -static IMAGES: Mutex>> = Mutex::new(None); thread_local! { static EDITOR: RefCell> = RefCell::new(None); } -async fn respond_to(id: Path) -> impl IntoResponse { - let builder = Response::builder().header("Access-Control-Allow-Origin", "*").status(StatusCode::OK); +// async fn respond_to(id: Path) -> impl IntoResponse { +// let builder = Response::builder().header("Access-Control-Allow-Origin", "*").status(StatusCode::OK); - let guard = IMAGES.lock().unwrap(); - let images = guard; - let image = images.as_ref().unwrap().get(&id.0).unwrap(); +// let guard = IMAGES.lock().unwrap(); +// let images = guard; +// let image = images.as_ref().unwrap().get(&id.0).unwrap(); - println!("image: {:#?}", image.path); - let result: Result, &str> = Ok((*image.image_data).clone()); - let stream = futures::stream::once(async move { result }); - builder.body(StreamBody::new(stream)).unwrap() -} +// println!("image: {:#?}", image.path); +// let result: Result, &str> = Ok((*image.image_data).clone()); +// let stream = futures::stream::once(async move { result }); +// builder.body(StreamBody::new(stream)).unwrap() +// } #[tokio::main] async fn main() { @@ -56,10 +55,10 @@ async fn main() { .apply() .unwrap(); - *(IMAGES.lock().unwrap()) = Some(HashMap::new()); + // *(IMAGES.lock().unwrap()) = Some(HashMap::new()); graphite_editor::application::set_uuid_seed(0); EDITOR.with(|editor| editor.borrow_mut().replace(Editor::new())); - let app = Router::new().route("/", get(|| async { "Hello, World!" })).route("/image/:id", get(respond_to)); + let app = Router::new().route("/", get(|| async { "Hello, World!" }))/*.route("/image/:id", get(respond_to))*/; // run it with hyper on localhost:3000 tauri::async_runtime::spawn(async { @@ -78,8 +77,7 @@ async fn main() { } #[tauri::command] fn set_random_seed(seed: f64) { - let seed = seed as u64; - graphite_editor::application::set_uuid_seed(seed); + graphite_editor::application::set_uuid_seed(seed as u64); } #[tauri::command] @@ -96,20 +94,11 @@ fn handle_message(message: String) -> String { fn send_frontend_message_to_js(message: FrontendMessage) -> FrontendMessage { // Special case for update image data to avoid serialization times. if let FrontendMessage::UpdateImageData { document_id, image_data } = message { - let mut guard = IMAGES.lock().unwrap(); - let images = (*guard).as_mut().unwrap(); let mut stub_data = Vec::with_capacity(image_data.len()); for image in image_data { - let path = image.path.clone(); - let mime = image.mime.clone(); - let transform = image.transform; - images.insert(format!("{:?}_{}", image.path, document_id), image); stub_data.push(FrontendImageData { - path, - node_id: None, - mime, + mime: image.mime.clone(), image_data: Arc::new(Vec::new()), - transform, }); } FrontendMessage::UpdateImageData { document_id, image_data: stub_data } diff --git a/frontend/src/components/panels/Layers.svelte b/frontend/src/components/panels/Layers.svelte index 0473f2682f..e175aa4f12 100644 --- a/frontend/src/components/panels/Layers.svelte +++ b/frontend/src/components/panels/Layers.svelte @@ -4,7 +4,7 @@ import { beginDraggingElement } from "@graphite/io-managers/drag"; import { platformIsMac } from "@graphite/utility-functions/platform"; import type { Editor } from "@graphite/wasm-communication/editor"; - import { defaultWidgetLayout, patchWidgetLayout, UpdateDocumentLayerDetails, UpdateDocumentLayerTreeStructureJs, UpdateLayersPanelOptionsLayout } from "@graphite/wasm-communication/messages"; + import { defaultWidgetLayout, patchWidgetLayout, UpdateDocumentLayerDetails, UpdateDocumentLayerStructureJs, UpdateLayersPanelOptionsLayout } from "@graphite/wasm-communication/messages"; import type { LayerClassification, LayerPanelEntry } from "@graphite/wasm-communication/messages"; import LayoutCol from "@graphite/components/layout/LayoutCol.svelte"; @@ -27,8 +27,9 @@ type DraggingData = { select?: () => void; - insertFolder: BigUint64Array; - insertIndex: number; + insertParentId: bigint | undefined; + insertDepth: number; + insertIndex: number | undefined; highlightFolder: boolean; markerHeight: number; }; @@ -42,7 +43,7 @@ // Interactive dragging let draggable = true; let draggingData: undefined | DraggingData = undefined; - let fakeHighlight: undefined | BigUint64Array[] = undefined; + let fakeHighlight: undefined | bigint = undefined; let dragInPanel = false; // Layouts @@ -54,24 +55,24 @@ layersPanelOptionsLayout = layersPanelOptionsLayout; }); - editor.subscriptions.subscribeJsMessage(UpdateDocumentLayerTreeStructureJs, (updateDocumentLayerTreeStructure) => { - rebuildLayerTree(updateDocumentLayerTreeStructure); + editor.subscriptions.subscribeJsMessage(UpdateDocumentLayerStructureJs, (updateDocumentLayerStructure) => { + rebuildLayerHierarchy(updateDocumentLayerStructure); }); editor.subscriptions.subscribeJsMessage(UpdateDocumentLayerDetails, (updateDocumentLayerDetails) => { const targetLayer = updateDocumentLayerDetails.data; - const targetPath = targetLayer.path; + const targetId = targetLayer.id; - updateLayerInTree(targetPath, targetLayer); + updateLayerInTree(targetId, targetLayer); }); }); - function toggleLayerVisibility(path: BigUint64Array) { - editor.instance.toggleLayerVisibility(path); + function toggleLayerVisibility(id: bigint) { + editor.instance.toggleLayerVisibility(id); } - function handleExpandArrowClick(path: BigUint64Array) { - editor.instance.toggleLayerExpansion(path); + function handleExpandArrowClick(id: bigint) { + editor.instance.toggleLayerExpansion(id); } async function onEditLayerName(listing: LayerListingInfo) { @@ -97,7 +98,7 @@ layers = layers; const name = (e.target instanceof HTMLInputElement && e.target.value) || ""; - editor.instance.setLayerName(listing.entry.path, name); + editor.instance.setLayerName(listing.entry.id, name); listing.entry.name = name; } @@ -120,16 +121,16 @@ const [accel, oppositeAccel] = platformIsMac() ? [meta, ctrl] : [ctrl, meta]; // Select the layer only if the accel and/or shift keys are pressed - if (!oppositeAccel && !alt) selectLayer(accel, shift, listing); + if (!oppositeAccel && !alt) selectLayer(listing, accel, shift); e.stopPropagation(); } - function selectLayer(accel: boolean, shift: boolean, listing: LayerListingInfo) { + function selectLayer(listing: LayerListingInfo, accel: boolean, shift: boolean) { // Don't select while we are entering text to rename the layer if (listing.editingName) return; - editor.instance.selectLayer(listing.entry.path, accel, shift); + editor.instance.selectLayer(listing.entry.id, accel, shift); } async function deselectAllLayers() { @@ -148,10 +149,11 @@ let closest = Infinity; // Folder to insert into - let insertFolder = new BigUint64Array(); + let insertParentId: bigint | undefined = undefined; + let insertDepth = 0; - // Insert index - let insertIndex = -1; + // Insert index (starts at the end, essentially infinity) + let insertIndex = undefined; // Whether you are inserting into a folder and should show the folder outline let highlightFolder = false; @@ -171,7 +173,8 @@ // Inserting above current row if (distance > 0 && distance < closest) { - insertFolder = layer.path.slice(0, layer.path.length - 1); + insertParentId = layer.parentId; + insertDepth = layer.depth - 1; insertIndex = folderIndex; highlightFolder = false; closest = distance; @@ -179,15 +182,24 @@ } // Inserting below current row else if (distance > -closest && distance > -RANGE_TO_INSERT_WITHIN_BOTTOM_FOLDER_NOT_ROOT && distance < 0) { - insertFolder = isNestingLayer(layer.layerClassification) ? layer.path : layer.path.slice(0, layer.path.length - 1); - insertIndex = isNestingLayer(layer.layerClassification) ? 0 : folderIndex + 1; - highlightFolder = isNestingLayer(layer.layerClassification); + if (isNestingLayer(layer.layerClassification)) { + insertParentId = layer.id; + insertDepth = layer.depth; + insertIndex = 0; + highlightFolder = true; + } else { + insertParentId = layer.parentId; + insertDepth = layer.depth - 1; + insertIndex = folderIndex + 1; + highlightFolder = false; + } + closest = -distance; markerHeight = index === treeChildren.length - 1 ? rect.bottom - INSERT_MARK_OFFSET : rect.bottom; } // Inserting with no nesting at the end of the panel else if (closest === Infinity) { - if (layer.path.length === 1) insertIndex = folderIndex + 1; + if (layer.parentId === undefined) insertIndex = folderIndex + 1; markerHeight = rect.bottom - INSERT_MARK_OFFSET; } @@ -199,7 +211,8 @@ return { select, - insertFolder, + insertParentId, + insertDepth, insertIndex, highlightFolder, markerHeight, @@ -210,10 +223,10 @@ const layer = listing.entry; dragInPanel = true; if (!layer.selected) { - fakeHighlight = [layer.path]; + fakeHighlight = layer.id; } const select = () => { - if (!layer.selected) selectLayer(false, false, listing); + if (!layer.selected) selectLayer(listing, false, false); }; const target = (event.target instanceof HTMLElement && event.target) || undefined; @@ -240,58 +253,49 @@ async function drop() { if (draggingData && dragInPanel) { - const { select, insertFolder, insertIndex } = draggingData; + const { select, insertParentId, insertIndex } = draggingData; select?.(); - editor.instance.moveLayerInTree(insertFolder, insertIndex); + editor.instance.moveLayerInTree(insertParentId, insertIndex); } draggingData = undefined; fakeHighlight = undefined; dragInPanel = false; } - function rebuildLayerTree(updateDocumentLayerTreeStructure: UpdateDocumentLayerTreeStructureJs) { + function rebuildLayerHierarchy(updateDocumentLayerStructure: UpdateDocumentLayerStructureJs) { const layerWithNameBeingEdited = layers.find((layer: LayerListingInfo) => layer.editingName); - const layerPathWithNameBeingEdited = layerWithNameBeingEdited?.entry.path; - const layerIdWithNameBeingEdited = layerPathWithNameBeingEdited?.slice(-1)[0]; - const path: bigint[] = []; + const layerIdWithNameBeingEdited = layerWithNameBeingEdited?.entry.id; - // Clear the layer tree before rebuilding it + // Clear the layer hierarchy before rebuilding it layers = []; - // Build the new layer tree - const recurse = (folder: UpdateDocumentLayerTreeStructureJs) => { + // Build the new layer hierarchy + const recurse = (folder: UpdateDocumentLayerStructureJs) => { folder.children.forEach((item, index) => { - // TODO: fix toString - const layerId = BigInt(item.layerId.toString()); - path.push(layerId); - - const mapping = layerCache.get([path[path.length - 1]].toString()); + const mapping = layerCache.get(String(item.layerId)); if (mapping) { - mapping.path = new BigUint64Array(path); + mapping.id = item.layerId; layers.push({ folderIndex: index, bottomLayer: index === folder.children.length - 1, entry: mapping, - editingName: layerIdWithNameBeingEdited === layerId, + editingName: layerIdWithNameBeingEdited === item.layerId, }); } // Call self recursively if there are any children if (item.children.length >= 1) recurse(item); - - path.pop(); }); }; - recurse(updateDocumentLayerTreeStructure); + recurse(updateDocumentLayerStructure); layers = layers; } - function updateLayerInTree(targetPath: BigUint64Array, targetLayer: LayerPanelEntry) { - const path = targetPath.toString(); - layerCache.set(path, targetLayer); + function updateLayerInTree(targetId: bigint, targetLayer: LayerPanelEntry) { + layerCache.set(String(targetId), targetLayer); - const layer = layers.find((layer: LayerListingInfo) => layer.entry.path.toString() === path); + const layer = layers.find((layer: LayerListingInfo) => layer.entry.id === targetId); if (layer) { layer.entry = targetLayer; layers = layers; @@ -305,15 +309,15 @@ deselectAllLayers()} on:dragover={(e) => draggable && updateInsertLine(e)} on:dragend={() => draggable && drop()}> - {#each layers as listing, index (String(listing.entry.path.slice(-1)))} + {#each layers as listing, index (String(listing.entry.id))} selectLayerWithModifiers(e, listing)} > {#if isNestingLayer(listing.entry.layerClassification)} -