From ff8fec6ecae325ae8d5bba38a6e6d9c758da37c9 Mon Sep 17 00:00:00 2001 From: adamgerhant <116332429+adamgerhant@users.noreply.github.com> Date: Sat, 26 Oct 2024 11:39:48 -0700 Subject: [PATCH] Allow the Path tool to edit an upstream path even if there's a type conversion midway (#2055) Remove type check when iterating upstream Convert to doc comment --- .../document/graph_operation/utility_types.rs | 27 ++++++++++++++----- .../tool/common_functionality/shape_editor.rs | 7 +---- node-graph/gcore/src/vector/vector_nodes.rs | 4 ++- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs index 7ef1ee02..789adec1 100644 --- a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs +++ b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs @@ -5,6 +5,7 @@ use crate::messages::portfolio::document::utility_types::network_interface::{sel use crate::messages::prelude::*; use bezier_rs::Subpath; +use graph_craft::concrete; use graph_craft::document::value::TaggedValue; use graph_craft::document::{NodeId, NodeInput}; use graphene_core::raster::{BlendMode, ImageFrame}; @@ -16,6 +17,7 @@ use graphene_core::{Artboard, Color}; use glam::{DAffine2, DVec2, IVec2}; use graphene_std::vector::VectorData; +use graphene_std::GraphicGroup; #[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)] pub enum TransformIn { @@ -236,11 +238,13 @@ impl<'a> ModifyInputsContext<'a> { } }) } - // Gets the node id of a node with a specific reference that is upstream from the layer node, and creates it if it does not exist + /// Gets the node id of a node with a specific reference that is upstream from the layer node, and creates it if it does not exist + /// The returned node is based on the selection dots in the layer. The right most dot will always insert/access the path that flows directly into the layer + /// Each dot after that represents an existing path node + /// If there is an existing upstream node, then it will always be returned first. pub fn existing_node_id(&mut self, reference: &'static str) -> Option { // Start from the layer node or export let output_layer = self.get_output_layer()?; - let layer_input_type = self.network_interface.input_type(&InputConnector::node(output_layer.to_node(), 1), &[]).0.nested_type(); let upstream = self .network_interface @@ -249,8 +253,6 @@ impl<'a> ModifyInputsContext<'a> { // Take until another layer node is found (but not the first layer node) let mut existing_node_id = None; for upstream_node in upstream.collect::>() { - let upstream_node_input_type = self.network_interface.input_type(&InputConnector::node(upstream_node, 0), &[]).0.nested_type(); - // Check if this is the node we have been searching for. if self.network_interface.reference(&upstream_node, &[]).is_some_and(|node_reference| node_reference == reference) { existing_node_id = Some(upstream_node); @@ -261,8 +263,7 @@ impl<'a> ModifyInputsContext<'a> { self.layer_node.map(|layer| layer.to_node()) == Some(node_id) || self.network_interface.network(&[]).unwrap().exports.iter().any(|export| export.as_node() == Some(node_id)) }; - // If the type changes then break?? This should at least be after checking if the node is correct (otherwise the brush tool breaks.) - if !is_traversal_start(upstream_node) && (self.network_interface.is_layer(&upstream_node, &[]) || upstream_node_input_type != layer_input_type) { + if !is_traversal_start(upstream_node) && (self.network_interface.is_layer(&upstream_node, &[])) { break; } } @@ -278,6 +279,20 @@ impl<'a> ModifyInputsContext<'a> { log::error!("Node type {} does not exist in ModifyInputsContext::existing_node_id", reference); return None; }; + // If inserting a path node, insert a flatten vector elements if the type is a graphic group. + // TODO: Allow the path node to operate on Graphic Group data by utilizing the reference for each vector data in a group. + if node_definition.identifier == "Path" { + let layer_input_type = self.network_interface.input_type(&InputConnector::node(output_layer.to_node(), 1), &[]).0.nested_type(); + if layer_input_type == concrete!(GraphicGroup) { + let Some(flatten_vector_elements_definition) = resolve_document_node_type("Flatten Vector Elements") else { + log::error!("Flatten Vector Elements does not exist in ModifyInputsContext::existing_node_id"); + return None; + }; + let node_id = NodeId::new(); + self.network_interface.insert_node(node_id, flatten_vector_elements_definition.default_node_template(), &[]); + self.network_interface.move_node_to_chain_start(&node_id, output_layer, &[]); + } + } let node_id = NodeId::new(); self.network_interface.insert_node(node_id, node_definition.default_node_template(), &[]); self.network_interface.move_node_to_chain_start(&node_id, output_layer, &[]); diff --git a/editor/src/messages/tool/common_functionality/shape_editor.rs b/editor/src/messages/tool/common_functionality/shape_editor.rs index 796c1412..8dd0087f 100644 --- a/editor/src/messages/tool/common_functionality/shape_editor.rs +++ b/editor/src/messages/tool/common_functionality/shape_editor.rs @@ -6,7 +6,6 @@ use crate::messages::portfolio::document::utility_types::network_interface::Node use crate::messages::prelude::*; use bezier_rs::{Bezier, BezierHandles, TValue}; -use dyn_any::DynAny; use graphene_core::transform::Transform; use graphene_core::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType}; @@ -1071,11 +1070,7 @@ impl ShapeState { continue; }; - for point in self.selected_points() { - if let Some(_) = point.as_anchor() { - continue; - } - + for point in self.selected_points().filter(|point| point.as_handle().is_some()) { let anchor = point.get_anchor(&vector_data); if let Some(handles) = point.get_handle_pair(&vector_data) { points_to_select.push((layer, anchor, Some(handles[1].to_manipulator_point()))); diff --git a/node-graph/gcore/src/vector/vector_nodes.rs b/node-graph/gcore/src/vector/vector_nodes.rs index 1e889ac1..5a49d1a3 100644 --- a/node-graph/gcore/src/vector/vector_nodes.rs +++ b/node-graph/gcore/src/vector/vector_nodes.rs @@ -547,7 +547,9 @@ async fn flatten_vector_elements( graphic_group_input: impl Node, ) -> VectorData { let graphic_group = graphic_group_input.eval(footprint).await; - + // A node based solution to support passing through vector data could be a network node with a cache node connected to + // a flatten vector elements connected to an if else node, another connection from the cache directly + // To the if else node, and another connection from the cache to a matches type node connected to the if else node. fn concat_group(graphic_group: &GraphicGroup, current_transform: DAffine2, result: &mut VectorData) { for (element, reference) in graphic_group.iter() { match element {