diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index e311c05f9e..db58efaff2 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -1,4 +1,5 @@ use crate::messages::debug::utility_types::MessageLoggingVerbosity; +use crate::messages::defer::DeferMessageContext; use crate::messages::dialog::DialogMessageContext; use crate::messages::layout::layout_message_handler::LayoutMessageContext; use crate::messages::prelude::*; @@ -133,7 +134,10 @@ impl Dispatcher { self.message_handlers.debug_message_handler.process_message(message, &mut queue, ()); } Message::Defer(message) => { - self.message_handlers.defer_message_handler.process_message(message, &mut queue, ()); + let context = DeferMessageContext { + portfolio: &self.message_handlers.portfolio_message_handler, + }; + self.message_handlers.defer_message_handler.process_message(message, &mut queue, context); } Message::Dialog(message) => { let context = DialogMessageContext { diff --git a/editor/src/messages/defer/defer_message.rs b/editor/src/messages/defer/defer_message.rs index 605838260d..66db0ff787 100644 --- a/editor/src/messages/defer/defer_message.rs +++ b/editor/src/messages/defer/defer_message.rs @@ -4,7 +4,7 @@ use crate::messages::prelude::*; #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum DeferMessage { SetGraphSubmissionIndex(u64), - TriggerGraphRun(u64), + TriggerGraphRun(u64, DocumentId), AfterGraphRun { messages: Vec }, TriggerNavigationReady, AfterNavigationReady { messages: Vec }, diff --git a/editor/src/messages/defer/defer_message_handler.rs b/editor/src/messages/defer/defer_message_handler.rs index 762b392988..460eeaba3b 100644 --- a/editor/src/messages/defer/defer_message_handler.rs +++ b/editor/src/messages/defer/defer_message_handler.rs @@ -1,18 +1,24 @@ use crate::messages::prelude::*; +#[derive(ExtractField)] +pub struct DeferMessageContext<'a> { + pub portfolio: &'a PortfolioMessageHandler, +} + #[derive(Debug, Default, ExtractField)] pub struct DeferMessageHandler { - after_graph_run: Vec<(u64, Message)>, + after_graph_run: HashMap>, after_viewport_resize: Vec, current_graph_submission_id: u64, } #[message_handler_data] -impl MessageHandler for DeferMessageHandler { - fn process_message(&mut self, message: DeferMessage, responses: &mut VecDeque, _: ()) { +impl MessageHandler> for DeferMessageHandler { + fn process_message(&mut self, message: DeferMessage, responses: &mut VecDeque, context: DeferMessageContext) { match message { DeferMessage::AfterGraphRun { mut messages } => { - self.after_graph_run.extend(messages.drain(..).map(|m| (self.current_graph_submission_id, m))); + let after_graph_run = self.after_graph_run.entry(context.portfolio.active_document_id.unwrap_or(DocumentId(0))).or_default(); + after_graph_run.extend(messages.drain(..).map(|m| (self.current_graph_submission_id, m))); } DeferMessage::AfterNavigationReady { messages } => { self.after_viewport_resize.extend_from_slice(&messages); @@ -20,16 +26,20 @@ impl MessageHandler for DeferMessageHandler { DeferMessage::SetGraphSubmissionIndex(execution_id) => { self.current_graph_submission_id = execution_id + 1; } - DeferMessage::TriggerGraphRun(execution_id) => { - if self.after_graph_run.is_empty() { + DeferMessage::TriggerGraphRun(execution_id, document_id) => { + let after_graph_run = self.after_graph_run.entry(document_id).or_default(); + if after_graph_run.is_empty() { return; } // Find the index of the last message we can process - let split = self.after_graph_run.partition_point(|&(id, _)| id <= execution_id); - let elements = self.after_graph_run.drain(..split); + let split = after_graph_run.partition_point(|&(id, _)| id <= execution_id); + let elements = after_graph_run.drain(..split); for (_, message) in elements.rev() { responses.add_front(message); } + if !after_graph_run.is_empty() { + responses.add(NodeGraphMessage::RunDocumentGraph); + } } DeferMessage::TriggerNavigationReady => { for message in self.after_viewport_resize.drain(..).rev() { diff --git a/editor/src/messages/defer/mod.rs b/editor/src/messages/defer/mod.rs index 819bbf48e2..3a7b0b3f74 100644 --- a/editor/src/messages/defer/mod.rs +++ b/editor/src/messages/defer/mod.rs @@ -4,4 +4,4 @@ mod defer_message_handler; #[doc(inline)] pub use defer_message::{DeferMessage, DeferMessageDiscriminant}; #[doc(inline)] -pub use defer_message_handler::DeferMessageHandler; +pub use defer_message_handler::{DeferMessageContext, DeferMessageHandler}; 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 015b5d2fdb..c107b68248 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 @@ -32,6 +32,11 @@ impl MessageHandler for NewDocumentDialogMessageHa artboard: graphene_std::Artboard::new(IVec2::ZERO, self.dimensions.as_ivec2()), } .into(), + NodeGraphMessage::ForceRunDocumentGraph.into(), + DeferMessage::AfterGraphRun { + messages: vec![DeferMessage::TriggerNavigationReady.into()], + } + .into(), ], }); responses.add(DeferMessage::AfterNavigationReady { diff --git a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs index 0f4e77fb26..1a8962d974 100644 --- a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs +++ b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs @@ -35,15 +35,6 @@ impl MessageHandler f responses.add(NavigationMessage::CanvasPan { delta: DVec2::ZERO }); responses.add(NodeGraphMessage::SetGridAlignedEdges); - // We have to wait until a node node graph has run and all messages from that execution have been processed. - responses.add(DeferMessage::AfterGraphRun { - messages: vec![ - DeferMessage::AfterGraphRun { - messages: vec![DeferMessage::TriggerNavigationReady.into()], - } - .into(), - ], - }); } } InputPreprocessorMessage::DoubleClick { editor_mouse_state, modifier_keys } => { diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 1b358a00a9..0a1e1d54ed 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -347,12 +347,13 @@ impl MessageHandler> for Portfolio let inspect_node = self.inspect_node_id(); if let Ok(message) = self.executor.submit_node_graph_evaluation( self.documents.get_mut(document_id).expect("Tried to render non-existent document"), + *document_id, ipp.viewport_bounds.size().as_uvec2(), timing_information, inspect_node, true, ) { - responses.add(message); + responses.add_front(message); } } @@ -378,16 +379,19 @@ impl MessageHandler> for Portfolio PortfolioMessage::NewDocumentWithName { name } => { let mut new_document = DocumentMessageHandler::default(); new_document.name = name; - responses.add(DocumentMessage::PTZUpdate); + let mut new_responses = VecDeque::new(); + new_responses.add(DocumentMessage::PTZUpdate); let document_id = DocumentId(generate_uuid()); if self.active_document().is_some() { - responses.add(BroadcastEvent::ToolAbort); - responses.add(NavigationMessage::CanvasPan { delta: (0., 0.).into() }); + new_responses.add(BroadcastEvent::ToolAbort); + new_responses.add(NavigationMessage::CanvasPan { delta: (0., 0.).into() }); } - self.load_document(new_document, document_id, responses, false); - responses.add(PortfolioMessage::SelectDocument { document_id }); + self.load_document(new_document, document_id, &mut new_responses, false); + new_responses.add(PortfolioMessage::SelectDocument { document_id }); + new_responses.extend(responses.drain(..)); + *responses = new_responses; } PortfolioMessage::NextDocument => { if let Some(active_document_id) = self.active_document_id { @@ -899,7 +903,7 @@ impl MessageHandler> for Portfolio transparent_background, ..Default::default() }; - let result = self.executor.submit_document_export(document, export_config); + let result = self.executor.submit_document_export(document, self.active_document_id.unwrap(), export_config); if let Err(description) = result { responses.add(DialogMessage::DisplayDialogError { @@ -917,6 +921,7 @@ impl MessageHandler> for Portfolio let inspect_node = self.inspect_node_id(); let result = self.executor.submit_node_graph_evaluation( self.documents.get_mut(&document_id).expect("Tried to render non-existent document"), + document_id, ipp.viewport_bounds.size().as_uvec2(), timing_information, inspect_node, @@ -930,7 +935,7 @@ impl MessageHandler> for Portfolio description, }); } - Ok(message) => responses.add(message), + Ok(message) => responses.add_front(message), } } PortfolioMessage::ToggleRulers => { diff --git a/editor/src/messages/tool/tool_messages/freehand_tool.rs b/editor/src/messages/tool/tool_messages/freehand_tool.rs index 0ed5b01031..eb862b7fe5 100644 --- a/editor/src/messages/tool/tool_messages/freehand_tool.rs +++ b/editor/src/messages/tool/tool_messages/freehand_tool.rs @@ -251,12 +251,8 @@ impl Fsm for FreehandToolFsmState { let nodes = vec![(NodeId(0), node)]; let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, parent, responses); - let defered_responses = &mut VecDeque::new(); - tool_options.fill.apply_fill(layer, defered_responses); - tool_options.stroke.apply_stroke(tool_data.weight, layer, defered_responses); - responses.add(DeferMessage::AfterGraphRun { - messages: defered_responses.drain(..).collect(), - }); + tool_options.fill.apply_fill(layer, responses); + tool_options.stroke.apply_stroke(tool_data.weight, layer, responses); tool_data.layer = Some(layer); FreehandToolFsmState::Drawing diff --git a/editor/src/messages/tool/tool_messages/shape_tool.rs b/editor/src/messages/tool/tool_messages/shape_tool.rs index 55bb34fb35..c6e6911a60 100644 --- a/editor/src/messages/tool/tool_messages/shape_tool.rs +++ b/editor/src/messages/tool/tool_messages/shape_tool.rs @@ -706,6 +706,7 @@ impl Fsm for ShapeToolFsmState { responses.add(DeferMessage::AfterGraphRun { messages: defered_responses.drain(..).collect(), }); + responses.add(NodeGraphMessage::RunDocumentGraph); ShapeToolFsmState::Drawing(tool_data.current_shape) } diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index 06e9aab9f5..c395ae0de6 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -63,6 +63,7 @@ pub struct NodeGraphExecutor { #[derive(Debug, Clone)] struct ExecutionContext { export_config: Option, + document_id: DocumentId, } impl NodeGraphExecutor { @@ -133,7 +134,13 @@ impl NodeGraphExecutor { } /// Adds an evaluate request for whatever current network is cached. - pub(crate) fn submit_current_node_graph_evaluation(&mut self, document: &mut DocumentMessageHandler, viewport_resolution: UVec2, time: TimingInformation) -> Result { + pub(crate) fn submit_current_node_graph_evaluation( + &mut self, + document: &mut DocumentMessageHandler, + document_id: DocumentId, + viewport_resolution: UVec2, + time: TimingInformation, + ) -> Result { let render_config = RenderConfig { viewport: Footprint { transform: document.metadata().document_to_viewport, @@ -153,7 +160,7 @@ impl NodeGraphExecutor { // Execute the node graph let execution_id = self.queue_execution(render_config); - self.futures.insert(execution_id, ExecutionContext { export_config: None }); + self.futures.insert(execution_id, ExecutionContext { export_config: None, document_id }); Ok(DeferMessage::SetGraphSubmissionIndex(execution_id).into()) } @@ -162,17 +169,18 @@ impl NodeGraphExecutor { pub fn submit_node_graph_evaluation( &mut self, document: &mut DocumentMessageHandler, + document_id: DocumentId, viewport_resolution: UVec2, time: TimingInformation, inspect_node: Option, ignore_hash: bool, ) -> Result { self.update_node_graph(document, inspect_node, ignore_hash)?; - self.submit_current_node_graph_evaluation(document, viewport_resolution, time) + self.submit_current_node_graph_evaluation(document, document_id, viewport_resolution, time) } /// Evaluates a node graph for export - pub fn submit_document_export(&mut self, document: &mut DocumentMessageHandler, mut export_config: ExportConfig) -> Result<(), String> { + pub fn submit_document_export(&mut self, document: &mut DocumentMessageHandler, document_id: DocumentId, mut export_config: ExportConfig) -> Result<(), String> { let network = document.network_interface.document_network().clone(); // Calculate the bounding box of the region to be exported @@ -204,7 +212,10 @@ impl NodeGraphExecutor { .send(GraphRuntimeRequest::GraphUpdate(GraphUpdate { network, inspect_node: None })) .map_err(|e| e.to_string())?; let execution_id = self.queue_execution(render_config); - let execution_context = ExecutionContext { export_config: Some(export_config) }; + let execution_context = ExecutionContext { + export_config: Some(export_config), + document_id, + }; self.futures.insert(execution_id, execution_context); Ok(()) @@ -279,7 +290,7 @@ impl NodeGraphExecutor { } else { self.process_node_graph_output(node_graph_output, transform, responses)? } - responses.add(DeferMessage::TriggerGraphRun(execution_id)); + responses.add_front(DeferMessage::TriggerGraphRun(execution_id, execution_context.document_id)); // Update the spreadsheet on the frontend using the value of the inspect result. if self.old_inspect_node.is_some() { diff --git a/editor/src/test_utils.rs b/editor/src/test_utils.rs index 11eb0052f9..addadae0c2 100644 --- a/editor/src/test_utils.rs +++ b/editor/src/test_utils.rs @@ -49,7 +49,7 @@ impl EditorTestUtils { }; let viewport_resolution = glam::UVec2::ONE; - if let Err(e) = exector.submit_current_node_graph_evaluation(document, viewport_resolution, Default::default()) { + if let Err(e) = exector.submit_current_node_graph_evaluation(document, DocumentId(0), viewport_resolution, Default::default()) { return Err(format!("submit_current_node_graph_evaluation failed\n\n{e}")); } runtime.run().await;