From 2b9337406adaa1303907d387d018e4b9b371e32f Mon Sep 17 00:00:00 2001 From: 0HyperCube <78500760+0HyperCube@users.noreply.github.com> Date: Sun, 30 Jul 2023 20:37:37 +0100 Subject: [PATCH] Fix artboard thumbnails (#1342) * Fix artboard thumbnails * Use GraphIdentifier instead of option * Fix warnings introduced by artboard nodes --- .../input_preprocessor_message_handler.rs | 5 -- .../artboard/artboard_message_handler.rs | 4 +- .../document/document_message_handler.rs | 2 +- .../graph_operation_message_handler.rs | 21 +------ .../node_graph/node_graph_message_handler.rs | 8 +-- .../properties_panel/utility_functions.rs | 2 +- .../portfolio/portfolio_message_handler.rs | 4 +- editor/src/node_graph_executor.rs | 57 +++++++++++-------- node-graph/graph-craft/src/document.rs | 12 ++-- 9 files changed, 51 insertions(+), 64 deletions(-) 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 9f886220..4cccae9d 100644 --- a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs +++ b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs @@ -24,11 +24,6 @@ impl MessageHandler for InputP assert_eq!(bounds_of_viewports.len(), 1, "Only one viewport is currently supported"); for bounds in bounds_of_viewports { - let new_size = bounds.size(); - let existing_size = self.viewport_bounds.size(); - - let translation = ((new_size - existing_size) / 2.).round(); - // TODO: Extend this to multiple viewports instead of setting it to the value of this last loop iteration self.viewport_bounds = bounds; 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 cba03246..ee2d28a0 100644 --- a/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs +++ b/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs @@ -3,7 +3,7 @@ use crate::messages::portfolio::utility_types::PersistentData; use crate::messages::prelude::*; use document_legacy::document::Document as DocumentLegacy; -use document_legacy::layers::style::{self, Fill, RenderData, ViewMode}; +use document_legacy::layers::style::{self, Fill}; use document_legacy::DocumentResponse; use document_legacy::LayerId; use document_legacy::Operation as DocumentOperation; @@ -20,7 +20,7 @@ pub struct ArtboardMessageHandler { impl MessageHandler for ArtboardMessageHandler { #[remain::check] - fn process_message(&mut self, message: ArtboardMessage, responses: &mut VecDeque, persistent_data: &PersistentData) { + fn process_message(&mut self, message: ArtboardMessage, responses: &mut VecDeque, _persistent_data: &PersistentData) { use ArtboardMessage::*; #[remain::sorted] diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index ab4ae654..9a7310d9 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -201,7 +201,7 @@ impl MessageHandler { let properties_panel_message_handler_data = PropertiesPanelMessageHandlerData { - document_name: &self.name.as_str(), + document_name: self.name.as_str(), artwork_document: &self.document_legacy, artboard_document: &self.artboard_message_handler.artboards_document, selected_layers: &mut self.layer_metadata.iter().filter_map(|(path, data)| data.selected.then_some(path.as_slice())), 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 76cc683d..05b8a805 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 @@ -80,19 +80,6 @@ impl<'a> ModifyInputsContext<'a> { Some(id) } - pub fn insert_layer_below(&mut self, node_id: NodeId, input_index: usize) -> Option { - let layer_node = resolve_document_node_type("Layer").expect("Layer node"); - - let new_id = generate_uuid(); - let post_node = self.network.nodes.get_mut(&node_id)?; - post_node.inputs[input_index] = NodeInput::node(new_id, 0); - let document_node = layer_node.to_document_node_default_inputs([], DocumentNodeMetadata::position(post_node.metadata.position + IVec2::new(0, 2))); - - self.network.nodes.insert(new_id, document_node); - - Some(new_id) - } - pub fn insert_node_before(&mut self, new_id: NodeId, node_id: NodeId, input_index: usize, mut document_node: DocumentNode, offset: IVec2) -> Option { let post_node = self.network.nodes.get_mut(&node_id)?; @@ -109,7 +96,7 @@ impl<'a> ModifyInputsContext<'a> { let mut current_input = &self.network.nodes.get(¤t_node)?.inputs[input_index]; while let NodeInput::Node { node_id, output_index, .. } = current_input { - let mut sibling_node = &self.network.nodes.get(node_id)?; + let sibling_node = &self.network.nodes.get(node_id)?; if sibling_node.name == "Layer" { current_node = *node_id; input_index = 7; @@ -148,7 +135,7 @@ impl<'a> ModifyInputsContext<'a> { fn shift_upstream(&mut self, node_id: NodeId, shift: IVec2) { let mut shift_nodes = HashSet::new(); let mut stack = vec![node_id]; - while let Some(node) = stack.pop() { + while let Some(node_id) = stack.pop() { let Some(node) = self.network.nodes.get(&node_id) else { continue }; for input in &node.inputs { let NodeInput::Node { node_id, .. } = input else { continue }; @@ -477,12 +464,10 @@ impl MessageHandler { let mut modify_inputs = ModifyInputsContext::new_doc(document, node_graph, responses); - if let Some(layer) = modify_inputs.locate_layer(id) { + if modify_inputs.locate_layer(id).is_some() { modify_inputs.resize_artboard(location, dimensions); } } 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 87855c9a..c6bd806d 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 @@ -2,7 +2,7 @@ pub use self::document_node_types::*; use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::prelude::*; -use crate::node_graph_executor::NodeGraphExecutor; +use crate::node_graph_executor::{GraphIdentifier, NodeGraphExecutor}; use document_legacy::document::Document; use document_legacy::LayerId; @@ -347,10 +347,8 @@ impl NodeGraphMessageHandler { }) .collect(); - let thumbnail_svg = layer_id - .and_then(|layer_id| executor.thumbnails.get(&layer_id)) - .and_then(|layer| layer.get(id)) - .map(|svg| svg.to_string()); + let graph_identifier = GraphIdentifier::new(layer_id); + let thumbnail_svg = executor.thumbnails.get(&graph_identifier).and_then(|thumbnails| thumbnails.get(id)).map(|svg| svg.to_string()); nodes.push(FrontendNode { id: *id, diff --git a/editor/src/messages/portfolio/document/properties_panel/utility_functions.rs b/editor/src/messages/portfolio/document/properties_panel/utility_functions.rs index 4ec2d94e..54e6f705 100644 --- a/editor/src/messages/portfolio/document/properties_panel/utility_functions.rs +++ b/editor/src/messages/portfolio/document/properties_panel/utility_functions.rs @@ -12,7 +12,7 @@ use crate::messages::prelude::*; use crate::node_graph_executor::NodeGraphExecutor; use document_legacy::document::Document; -use document_legacy::layers::layer_info::{Layer, LayerDataType, LayerDataTypeDiscriminant}; +use document_legacy::layers::layer_info::{Layer, LayerDataType}; use document_legacy::layers::style::{Fill, Gradient, GradientType, LineCap, LineJoin, RenderData, Stroke, ViewMode}; use graphene_core::raster::color::Color; diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 87750d31..15792951 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -482,8 +482,8 @@ impl MessageHandler { - if let (Some(layer_id), Some(node_id)) = (layer_path.last().copied(), node_id) { - self.executor.insert_thumbnail_blob_url(blob_url, layer_id, node_id, responses); + if let Some(node_id) = node_id { + self.executor.insert_thumbnail_blob_url(blob_url, layer_path.last().copied(), node_id, responses); return; } let message = DocumentMessage::SetImageBlobUrl { diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index c53b1279..b13f7d96 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -29,6 +29,22 @@ 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, @@ -36,7 +52,7 @@ pub struct NodeRuntime { sender: InternalNodeGraphUpdateSender, wasm_io: Option, imaginate_preferences: ImaginatePreferences, - pub(crate) thumbnails: HashMap>, + pub(crate) thumbnails: HashMap>, canvas_cache: HashMap, SurfaceId>, } @@ -57,7 +73,7 @@ pub(crate) struct GenerationResponse { generation_id: u64, result: Result, updates: VecDeque, - new_thumbnails: HashMap>, + new_thumbnails: HashMap>, } enum NodeGraphUpdate { @@ -118,7 +134,13 @@ impl NodeRuntime { path, .. }) => { - let (network, monitor_nodes) = Self::wrap_network(graph); + let network = wrap_network_in_scope(graph); + + let monitor_nodes = network + .recursive_nodes() + .filter(|node| node.implementation == DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode<_>")) + .map(|node| node.path.clone().unwrap_or_default()) + .collect(); let result = self.execute_network(&path, network, image_frame).await; let mut responses = VecDeque::new(); @@ -135,20 +157,6 @@ impl NodeRuntime { } } - /// Wraps a network in a scope and returns the new network and the paths to the monitor nodes. - fn wrap_network(network: NodeNetwork) -> (NodeNetwork, Vec>) { - let scoped_network = wrap_network_in_scope(network); - - //scoped_network.generate_node_paths(&[]); - let monitor_nodes = scoped_network - .recursive_nodes() - .filter(|(node, _, _)| node.implementation == DocumentNodeImplementation::proto("graphene_std::memo::MonitorNode<_>")) - .map(|(_, _, path)| path) - .collect(); - - (scoped_network, monitor_nodes) - } - async fn execute_network<'a>(&'a mut self, path: &[LayerId], scoped_network: NodeNetwork, image_frame: Option>) -> Result { if self.wasm_io.is_none() { self.wasm_io = Some(WasmApplicationIo::new().await); @@ -216,8 +224,9 @@ impl NodeRuntime { render.format_svg(min, max); debug!("SVG {}", render.svg); - if let (Some(layer_id), Some(node_id)) = (layer_path.last().copied(), node_path.get(node_path.len() - 2).copied()) { - let old_thumbnail = self.thumbnails.entry(layer_id).or_default().entry(node_id).or_default(); + if let Some(node_id) = node_path.get(node_path.len() - 2).copied() { + let graph_identifier = GraphIdentifier::new(layer_path.last().copied()); + let old_thumbnail = self.thumbnails.entry(graph_identifier).or_default().entry(node_id).or_default(); if *old_thumbnail != render.svg { *old_thumbnail = render.svg; thumbnails_changed = true; @@ -271,7 +280,7 @@ pub struct NodeGraphExecutor { receiver: Receiver, // TODO: This is a memory leak since layers are never removed pub(crate) last_output_type: HashMap, Option>, - pub(crate) thumbnails: HashMap>, + pub(crate) thumbnails: HashMap>, futures: HashMap, } @@ -456,7 +465,7 @@ impl NodeGraphExecutor { Ok(()) } - fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, layer_path: Vec, transform: DAffine2, responses: &mut VecDeque, document_id: u64) -> Result<(), String> { + fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, layer_path: Vec, _transform: DAffine2, responses: &mut VecDeque, document_id: u64) -> Result<(), String> { self.last_output_type.insert(layer_path.clone(), Some(node_graph_output.ty())); match node_graph_output { TaggedValue::VectorData(vector_data) => { @@ -494,7 +503,7 @@ impl NodeGraphExecutor { } TaggedValue::GraphicGroup(graphic_group) => { debug!("{graphic_group:#?}"); - use graphene_core::renderer::{format_transform_matrix, GraphicElementRendered, RenderParams, SvgRender}; + use graphene_core::renderer::{GraphicElementRendered, RenderParams, SvgRender}; // Setup rendering let mut render = SvgRender::new(); @@ -523,8 +532,8 @@ impl NodeGraphExecutor { } /// 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, layer_id: LayerId, node_id: NodeId, responses: &mut VecDeque) { - if let Some(layer) = self.thumbnails.get_mut(&layer_id) { + pub fn insert_thumbnail_blob_url(&mut self, blob_url: String, layer_id: Option, node_id: NodeId, responses: &mut VecDeque) { + if let Some(layer) = self.thumbnails.get_mut(&GraphIdentifier::new(layer_id)) { if let Some(segment) = layer.values_mut().flat_map(|segments| segments.iter_mut()).find(|segment| **segment == SvgSegment::BlobUrl(node_id)) { *segment = SvgSegment::String(blob_url); responses.add(NodeGraphMessage::SendGraph { should_rerender: false }); diff --git a/node-graph/graph-craft/src/document.rs b/node-graph/graph-craft/src/document.rs index 1e2c1002..7385b155 100644 --- a/node-graph/graph-craft/src/document.rs +++ b/node-graph/graph-craft/src/document.rs @@ -887,24 +887,24 @@ impl NodeNetwork { /// Create a [`RecursiveNodeIter`] that iterates over all [`DocumentNode`]s, including ones that are deeply nested. pub fn recursive_nodes(&self) -> RecursiveNodeIter { - let nodes = self.nodes.iter().map(|(id, node)| (node, self, vec![*id])).collect(); + let nodes = self.nodes.values().collect(); RecursiveNodeIter { nodes } } } /// An iterator over all [`DocumentNode`]s, including ones that are deeply nested. pub struct RecursiveNodeIter<'a> { - nodes: Vec<(&'a DocumentNode, &'a NodeNetwork, Vec)>, + nodes: Vec<&'a DocumentNode>, } impl<'a> Iterator for RecursiveNodeIter<'a> { - type Item = (&'a DocumentNode, &'a NodeNetwork, Vec); + type Item = &'a DocumentNode; fn next(&mut self) -> Option { - let (node, network, path) = self.nodes.pop()?; + let node = self.nodes.pop()?; if let DocumentNodeImplementation::Network(network) = &node.implementation { - self.nodes.extend(network.nodes.iter().map(|(id, node)| (node, network, [path.as_slice(), &[*id]].concat()))); + self.nodes.extend(network.nodes.values()); } - Some((node, network, path)) + Some(node) } }