diff --git a/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs b/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs index 478188e4..677e20b5 100644 --- a/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs +++ b/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs @@ -12,7 +12,7 @@ use document_legacy::Operation as DocumentOperation; use glam::DAffine2; use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] pub struct ArtboardMessageHandler { pub artboards_document: DocumentLegacy, pub artboard_ids: Vec, diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index 918d5f78..d4c8ef70 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -49,6 +49,7 @@ pub enum DocumentMessage { }, BackupDocument { document: DocumentLegacy, + artboard: Box, layer_metadata: HashMap, LayerMetadata>, }, BooleanOperation(BooleanOperationType), diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 6c11d26e..27a56f70 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -247,7 +247,7 @@ impl MessageHandler self.backup_with_document(document, layer_metadata, responses), + BackupDocument { document, artboard, layer_metadata } => self.backup_with_document(document, *artboard, layer_metadata, responses), BooleanOperation(op) => { // Convert Vec<&[LayerId]> to Vec> because Vec<&[LayerId]> does not implement several traits (Debug, Serialize, Deserialize, ...) required by DocumentOperation enum responses.push_back(StartTransaction.into()); @@ -1288,9 +1288,9 @@ impl DocumentMessageHandler { } /// Places a document into the history system - fn backup_with_document(&mut self, document: DocumentLegacy, layer_metadata: HashMap, LayerMetadata>, responses: &mut VecDeque) { + fn backup_with_document(&mut self, document: DocumentLegacy, artboard: ArtboardMessageHandler, layer_metadata: HashMap, LayerMetadata>, responses: &mut VecDeque) { self.document_redo_history.clear(); - self.document_undo_history.push_back((document, layer_metadata)); + self.document_undo_history.push_back(DocumentSave { document, artboard, layer_metadata }); if self.document_undo_history.len() > crate::consts::MAX_UNDO_HISTORY_LEN { self.document_undo_history.pop_front(); } @@ -1301,7 +1301,7 @@ impl DocumentMessageHandler { /// Copies the entire document into the history system pub fn backup(&mut self, responses: &mut VecDeque) { - self.backup_with_document(self.document_legacy.clone(), self.layer_metadata.clone(), responses); + self.backup_with_document(self.document_legacy.clone(), self.artboard_message_handler.clone(), self.layer_metadata.clone(), responses); } /// Push a message backing up the document in its current state @@ -1309,6 +1309,7 @@ impl DocumentMessageHandler { responses.push_back( DocumentMessage::BackupDocument { document: self.document_legacy.clone(), + artboard: Box::new(self.artboard_message_handler.clone()), layer_metadata: self.layer_metadata.clone(), } .into(), @@ -1321,6 +1322,23 @@ impl DocumentMessageHandler { // TODO: Consider if we should check if the document is saved } + /// Replace the document with a new document save, returning the document save. + pub fn replace_document(&mut self, DocumentSave { document, artboard, layer_metadata }: DocumentSave) -> DocumentSave { + // Keeping the root is required if the bounds of the viewport have changed during the operation + let old_root = self.document_legacy.root.transform; + let old_artboard_root = self.artboard_message_handler.artboards_document.root.transform; + let document = std::mem::replace(&mut self.document_legacy, document); + let artboard = std::mem::replace(&mut self.artboard_message_handler, artboard); + self.document_legacy.root.transform = old_root; + self.artboard_message_handler.artboards_document.root.transform = old_artboard_root; + self.document_legacy.root.cache_dirty = true; + self.artboard_message_handler.artboards_document.root.cache_dirty = true; + + let layer_metadata = std::mem::replace(&mut self.layer_metadata, layer_metadata); + + DocumentSave { document, artboard, layer_metadata } + } + pub fn undo(&mut self, responses: &mut VecDeque) -> Result<(), EditorError> { // Push the UpdateOpenDocumentsList message to the bus in order to update the save status of the open documents responses.push_back(PortfolioMessage::UpdateOpenDocumentsList.into()); @@ -1328,7 +1346,7 @@ impl DocumentMessageHandler { let selected_paths: Vec> = self.selected_layers().map(|path| path.to_vec()).collect(); match self.document_undo_history.pop_back() { - Some((document, layer_metadata)) => { + Some(DocumentSave { document, artboard, layer_metadata }) => { // Update the currently displayed layer on the Properties panel if the selection changes after an undo action // Also appropriately update the Properties panel if an undo action results in a layer being deleted let prev_selected_paths: Vec> = layer_metadata.iter().filter_map(|(layer_id, metadata)| metadata.selected.then_some(layer_id.clone())).collect(); @@ -1337,14 +1355,9 @@ impl DocumentMessageHandler { responses.push_back(BroadcastEvent::SelectionChanged.into()); } - // Keeping the root is required if the bounds of the viewport have changed during the operation - let old_root = self.document_legacy.root.transform; - let document = std::mem::replace(&mut self.document_legacy, document); - self.document_legacy.root.transform = old_root; - self.document_legacy.root.cache_dirty = true; + let document_save = self.replace_document(DocumentSave { document, artboard, layer_metadata }); - let layer_metadata = std::mem::replace(&mut self.layer_metadata, layer_metadata); - self.document_redo_history.push_back((document, layer_metadata)); + self.document_redo_history.push_back(document_save); if self.document_redo_history.len() > crate::consts::MAX_UNDO_HISTORY_LEN { self.document_redo_history.pop_front(); } @@ -1368,7 +1381,7 @@ impl DocumentMessageHandler { let selected_paths: Vec> = self.selected_layers().map(|path| path.to_vec()).collect(); match self.document_redo_history.pop_back() { - Some((document, layer_metadata)) => { + Some(DocumentSave { document, artboard, layer_metadata }) => { // Update currently displayed layer on property panel if selection changes after redo action // Also appropriately update property panel if redo action results in a layer being added let next_selected_paths: Vec> = layer_metadata.iter().filter_map(|(layer_id, metadata)| metadata.selected.then_some(layer_id.clone())).collect(); @@ -1377,14 +1390,8 @@ impl DocumentMessageHandler { responses.push_back(BroadcastEvent::SelectionChanged.into()); } - // Keeping the root is required if the bounds of the viewport have changed during the operation - let old_root = self.document_legacy.root.transform; - let document = std::mem::replace(&mut self.document_legacy, document); - self.document_legacy.root.transform = old_root; - self.document_legacy.root.cache_dirty = true; - - let layer_metadata = std::mem::replace(&mut self.layer_metadata, layer_metadata); - self.document_undo_history.push_back((document, layer_metadata)); + let document_save = self.replace_document(DocumentSave { document, artboard, layer_metadata }); + self.document_undo_history.push_back(document_save); if self.document_undo_history.len() > crate::consts::MAX_UNDO_HISTORY_LEN { self.document_undo_history.pop_front(); } @@ -1407,7 +1414,7 @@ impl DocumentMessageHandler { self.document_undo_history .iter() .last() - .map(|(document_legacy, _)| document_legacy.current_state_identifier()) + .map(|DocumentSave { document, .. }| document.current_state_identifier()) .unwrap_or(0) } diff --git a/editor/src/messages/portfolio/document/utility_types/misc.rs b/editor/src/messages/portfolio/document/utility_types/misc.rs index 0ea83b83..4a302f84 100644 --- a/editor/src/messages/portfolio/document/utility_types/misc.rs +++ b/editor/src/messages/portfolio/document/utility_types/misc.rs @@ -1,4 +1,5 @@ pub use super::layer_panel::{LayerMetadata, LayerPanelEntry}; +use crate::messages::prelude::ArtboardMessageHandler; use document_legacy::color::Color; use document_legacy::document::Document as DocumentLegacy; @@ -8,7 +9,12 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; -pub type DocumentSave = (DocumentLegacy, HashMap, LayerMetadata>); +#[derive(Debug, Clone)] +pub struct DocumentSave { + pub document: DocumentLegacy, + pub artboard: ArtboardMessageHandler, + pub layer_metadata: HashMap, LayerMetadata>, +} #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, Hash)] pub enum FlipAxis { diff --git a/editor/src/messages/tool/tool_messages/artboard_tool.rs b/editor/src/messages/tool/tool_messages/artboard_tool.rs index b0831879..98da5d6b 100644 --- a/editor/src/messages/tool/tool_messages/artboard_tool.rs +++ b/editor/src/messages/tool/tool_messages/artboard_tool.rs @@ -190,6 +190,8 @@ impl Fsm for ArtboardToolFsmState { }; if let Some(selected_edges) = dragging_bounds { + responses.push_back(DocumentMessage::StartTransaction.into()); + let snap_x = selected_edges.2 || selected_edges.3; let snap_y = selected_edges.0 || selected_edges.1; @@ -206,6 +208,7 @@ impl Fsm for ArtboardToolFsmState { ArtboardToolFsmState::ResizingBounds } else { + responses.push_back(DocumentMessage::StartTransaction.into()); let tolerance = DVec2::splat(SELECTION_TOLERANCE); let quad = Quad::from_box([input.mouse.position - tolerance, input.mouse.position + tolerance]); let intersection = document.artboard_message_handler.artboards_document.intersects_quad_root(quad, font_cache);