Migrate vector data and tools to use nodes (#1065)

* Add rendering to vector nodes

* Add line, shape, rectange and freehand tool

* Fix transforms, strokes and fills

* Migrate spline tool

* Remove blank lines

* Fix test

* Fix fill in properties

* Select layers when filling

* Properties panel transform around pivot

* Fix select tool outlines

* Select tool modifies node graph pivot

* Add the pivot assist to the properties

* Improve setting non existant fill UX

* Cleanup hash function

* Path and pen tools

* Bug fixes

* Disable boolean ops

* Fix default handle smoothing on ellipses

* Fix test and warnings

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2023-03-26 08:03:51 +01:00
committed by Keavon Chambers
parent 639a24d8ad
commit 959e790cdf
64 changed files with 2639 additions and 1552 deletions

View File

@@ -6,9 +6,11 @@ use crate::messages::prelude::*;
use document_legacy::{document::pick_safe_imaginate_resolution, layers::layer_info::LayerDataType};
use document_legacy::{LayerId, Operation};
use dyn_any::DynAny;
use graph_craft::document::{generate_uuid, NodeId, NodeInput, NodeNetwork, NodeOutput};
use graph_craft::executor::Compiler;
use graphene_core::raster::{Image, ImageFrame};
use graphene_core::vector::VectorData;
use interpreted_executor::executor::DynamicExecutor;
use glam::{DAffine2, DVec2};
@@ -20,8 +22,8 @@ pub struct NodeGraphExecutor {
}
impl NodeGraphExecutor {
/// Execute the network by flattening it and creating a borrow stack. Casts the output to the generic `T`.
fn execute_network<T: dyn_any::StaticType>(&mut self, network: NodeNetwork, image_frame: ImageFrame) -> Result<T, String> {
/// Execute the network by flattening it and creating a borrow stack.
fn execute_network<'a>(&'a mut self, network: NodeNetwork, image_frame: ImageFrame) -> Result<Box<dyn dyn_any::DynAny + 'a>, String> {
let mut scoped_network = wrap_network_in_scope(network);
scoped_network.duplicate_outputs(&mut generate_uuid);
@@ -40,9 +42,7 @@ impl NodeGraphExecutor {
use dyn_any::IntoDynAny;
use graph_craft::executor::Executor;
let boxed = self.executor.execute(image_frame.into_dyn()).map_err(|e| e.to_string())?;
dyn_any::downcast::<T>(boxed).map(|v| *v)
self.executor.execute(image_frame.into_dyn()).map_err(|e| e.to_string())
}
/// Computes an input for a node in the graph
@@ -82,7 +82,9 @@ impl NodeGraphExecutor {
}
}
self.execute_network(network, image_frame.into_owned())
let boxed = self.execute_network(network, image_frame.into_owned())?;
dyn_any::downcast::<T>(boxed).map(|v| *v)
}
/// Encodes an image into a format using the image crate
@@ -243,11 +245,24 @@ impl NodeGraphExecutor {
}?;
let network = node_graph_frame.network.clone();
// Execute the node graph
// Special execution path for generating imaginate (as generation requires io from outside node graph)
if let Some(imaginate_node) = imaginate_node {
responses.push_back(self.generate_imaginate(network, imaginate_node, (document, document_id), layer_path, image_frame, persistent_data)?);
return Ok(());
}
// Execute the node graph
let boxed_node_graph_output = self.execute_network(network, image_frame)?;
// Check if the output is vector data
if core::any::TypeId::of::<VectorData>() == DynAny::type_id(boxed_node_graph_output.as_ref()) {
// Update the cached vector data on the layer
let vector_data: VectorData = dyn_any::downcast(boxed_node_graph_output).map(|v| *v)?;
let transform = vector_data.transform.to_cols_array();
responses.push_back(Operation::SetLayerTransform { path: layer_path.clone(), transform }.into());
responses.push_back(Operation::SetVectorData { path: layer_path, vector_data }.into());
} else {
let ImageFrame { image, transform } = self.execute_network(network, image_frame)?;
// Attempt to downcast to an image frame
let ImageFrame { image, transform } = dyn_any::downcast(boxed_node_graph_output).map(|image_frame| *image_frame)?;
// If no image was generated, clear the frame
if image.width == 0 || image.height == 0 {