Fix artboard thumbnails (#1342)
* Fix artboard thumbnails * Use GraphIdentifier instead of option * Fix warnings introduced by artboard nodes
This commit is contained in:
parent
f151ba39b5
commit
2b9337406a
|
|
@ -24,11 +24,6 @@ impl MessageHandler<InputPreprocessorMessage, KeyboardPlatformLayout> 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ArtboardMessage, &PersistentData> for ArtboardMessageHandler {
|
||||
#[remain::check]
|
||||
fn process_message(&mut self, message: ArtboardMessage, responses: &mut VecDeque<Message>, persistent_data: &PersistentData) {
|
||||
fn process_message(&mut self, message: ArtboardMessage, responses: &mut VecDeque<Message>, _persistent_data: &PersistentData) {
|
||||
use ArtboardMessage::*;
|
||||
|
||||
#[remain::sorted]
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
|||
#[remain::unsorted]
|
||||
PropertiesPanel(message) => {
|
||||
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())),
|
||||
|
|
|
|||
|
|
@ -80,19 +80,6 @@ impl<'a> ModifyInputsContext<'a> {
|
|||
Some(id)
|
||||
}
|
||||
|
||||
pub fn insert_layer_below(&mut self, node_id: NodeId, input_index: usize) -> Option<NodeId> {
|
||||
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<NodeId> {
|
||||
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<GraphOperationMessage, (&mut Document, &mut NodeGraphMessage
|
|||
if let Some(layer) = modify_inputs.create_layer(id, modify_inputs.network.outputs[0].node_id) {
|
||||
modify_inputs.insert_artboard(artboard, layer);
|
||||
}
|
||||
|
||||
//modify_inputs.brush_modify(strokes);
|
||||
}
|
||||
GraphOperationMessage::ResizeArtboard { id, location, dimensions } => {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -482,8 +482,8 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
|
|||
blob_url,
|
||||
resolution,
|
||||
} => {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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<LayerId>) -> 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<WasmApplicationIo>,
|
||||
imaginate_preferences: ImaginatePreferences,
|
||||
pub(crate) thumbnails: HashMap<LayerId, HashMap<NodeId, SvgSegmentList>>,
|
||||
pub(crate) thumbnails: HashMap<GraphIdentifier, HashMap<NodeId, SvgSegmentList>>,
|
||||
canvas_cache: HashMap<Vec<LayerId>, SurfaceId>,
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +73,7 @@ pub(crate) struct GenerationResponse {
|
|||
generation_id: u64,
|
||||
result: Result<TaggedValue, String>,
|
||||
updates: VecDeque<Message>,
|
||||
new_thumbnails: HashMap<LayerId, HashMap<NodeId, SvgSegmentList>>,
|
||||
new_thumbnails: HashMap<GraphIdentifier, HashMap<NodeId, SvgSegmentList>>,
|
||||
}
|
||||
|
||||
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<Vec<NodeId>>) {
|
||||
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<ImageFrame<Color>>) -> Result<TaggedValue, String> {
|
||||
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<NodeGraphUpdate>,
|
||||
// TODO: This is a memory leak since layers are never removed
|
||||
pub(crate) last_output_type: HashMap<Vec<LayerId>, Option<Type>>,
|
||||
pub(crate) thumbnails: HashMap<LayerId, HashMap<NodeId, SvgSegmentList>>,
|
||||
pub(crate) thumbnails: HashMap<GraphIdentifier, HashMap<NodeId, SvgSegmentList>>,
|
||||
futures: HashMap<u64, ExecutionContext>,
|
||||
}
|
||||
|
||||
|
|
@ -456,7 +465,7 @@ impl NodeGraphExecutor {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, layer_path: Vec<LayerId>, transform: DAffine2, responses: &mut VecDeque<Message>, document_id: u64) -> Result<(), String> {
|
||||
fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, layer_path: Vec<LayerId>, _transform: DAffine2, responses: &mut VecDeque<Message>, 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<Message>) {
|
||||
if let Some(layer) = self.thumbnails.get_mut(&layer_id) {
|
||||
pub fn insert_thumbnail_blob_url(&mut self, blob_url: String, layer_id: Option<LayerId>, node_id: NodeId, responses: &mut VecDeque<Message>) {
|
||||
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 });
|
||||
|
|
|
|||
|
|
@ -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<NodeId>)>,
|
||||
nodes: Vec<&'a DocumentNode>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for RecursiveNodeIter<'a> {
|
||||
type Item = (&'a DocumentNode, &'a NodeNetwork, Vec<NodeId>);
|
||||
type Item = &'a DocumentNode;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue