Skip to content

Commit ff8fec6

Browse files
authored
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
1 parent b1399af commit ff8fec6

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

editor/src/messages/portfolio/document/graph_operation/utility_types.rs

+21-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::messages::portfolio::document::utility_types::network_interface::{sel
55
use crate::messages::prelude::*;
66

77
use bezier_rs::Subpath;
8+
use graph_craft::concrete;
89
use graph_craft::document::value::TaggedValue;
910
use graph_craft::document::{NodeId, NodeInput};
1011
use graphene_core::raster::{BlendMode, ImageFrame};
@@ -16,6 +17,7 @@ use graphene_core::{Artboard, Color};
1617

1718
use glam::{DAffine2, DVec2, IVec2};
1819
use graphene_std::vector::VectorData;
20+
use graphene_std::GraphicGroup;
1921

2022
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
2123
pub enum TransformIn {
@@ -236,11 +238,13 @@ impl<'a> ModifyInputsContext<'a> {
236238
}
237239
})
238240
}
239-
// 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
241+
/// 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
242+
/// 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
243+
/// Each dot after that represents an existing path node
244+
/// If there is an existing upstream node, then it will always be returned first.
240245
pub fn existing_node_id(&mut self, reference: &'static str) -> Option<NodeId> {
241246
// Start from the layer node or export
242247
let output_layer = self.get_output_layer()?;
243-
let layer_input_type = self.network_interface.input_type(&InputConnector::node(output_layer.to_node(), 1), &[]).0.nested_type();
244248

245249
let upstream = self
246250
.network_interface
@@ -249,8 +253,6 @@ impl<'a> ModifyInputsContext<'a> {
249253
// Take until another layer node is found (but not the first layer node)
250254
let mut existing_node_id = None;
251255
for upstream_node in upstream.collect::<Vec<_>>() {
252-
let upstream_node_input_type = self.network_interface.input_type(&InputConnector::node(upstream_node, 0), &[]).0.nested_type();
253-
254256
// Check if this is the node we have been searching for.
255257
if self.network_interface.reference(&upstream_node, &[]).is_some_and(|node_reference| node_reference == reference) {
256258
existing_node_id = Some(upstream_node);
@@ -261,8 +263,7 @@ impl<'a> ModifyInputsContext<'a> {
261263
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))
262264
};
263265

264-
// If the type changes then break?? This should at least be after checking if the node is correct (otherwise the brush tool breaks.)
265-
if !is_traversal_start(upstream_node) && (self.network_interface.is_layer(&upstream_node, &[]) || upstream_node_input_type != layer_input_type) {
266+
if !is_traversal_start(upstream_node) && (self.network_interface.is_layer(&upstream_node, &[])) {
266267
break;
267268
}
268269
}
@@ -278,6 +279,20 @@ impl<'a> ModifyInputsContext<'a> {
278279
log::error!("Node type {} does not exist in ModifyInputsContext::existing_node_id", reference);
279280
return None;
280281
};
282+
// If inserting a path node, insert a flatten vector elements if the type is a graphic group.
283+
// TODO: Allow the path node to operate on Graphic Group data by utilizing the reference for each vector data in a group.
284+
if node_definition.identifier == "Path" {
285+
let layer_input_type = self.network_interface.input_type(&InputConnector::node(output_layer.to_node(), 1), &[]).0.nested_type();
286+
if layer_input_type == concrete!(GraphicGroup) {
287+
let Some(flatten_vector_elements_definition) = resolve_document_node_type("Flatten Vector Elements") else {
288+
log::error!("Flatten Vector Elements does not exist in ModifyInputsContext::existing_node_id");
289+
return None;
290+
};
291+
let node_id = NodeId::new();
292+
self.network_interface.insert_node(node_id, flatten_vector_elements_definition.default_node_template(), &[]);
293+
self.network_interface.move_node_to_chain_start(&node_id, output_layer, &[]);
294+
}
295+
}
281296
let node_id = NodeId::new();
282297
self.network_interface.insert_node(node_id, node_definition.default_node_template(), &[]);
283298
self.network_interface.move_node_to_chain_start(&node_id, output_layer, &[]);

editor/src/messages/tool/common_functionality/shape_editor.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::messages::portfolio::document::utility_types::network_interface::Node
66
use crate::messages::prelude::*;
77

88
use bezier_rs::{Bezier, BezierHandles, TValue};
9-
use dyn_any::DynAny;
109
use graphene_core::transform::Transform;
1110
use graphene_core::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType};
1211

@@ -1071,11 +1070,7 @@ impl ShapeState {
10711070
continue;
10721071
};
10731072

1074-
for point in self.selected_points() {
1075-
if let Some(_) = point.as_anchor() {
1076-
continue;
1077-
}
1078-
1073+
for point in self.selected_points().filter(|point| point.as_handle().is_some()) {
10791074
let anchor = point.get_anchor(&vector_data);
10801075
if let Some(handles) = point.get_handle_pair(&vector_data) {
10811076
points_to_select.push((layer, anchor, Some(handles[1].to_manipulator_point())));

node-graph/gcore/src/vector/vector_nodes.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,9 @@ async fn flatten_vector_elements<F: 'n + Send>(
547547
graphic_group_input: impl Node<F, Output = GraphicGroup>,
548548
) -> VectorData {
549549
let graphic_group = graphic_group_input.eval(footprint).await;
550-
550+
// A node based solution to support passing through vector data could be a network node with a cache node connected to
551+
// a flatten vector elements connected to an if else node, another connection from the cache directly
552+
// To the if else node, and another connection from the cache to a matches type node connected to the if else node.
551553
fn concat_group(graphic_group: &GraphicGroup, current_transform: DAffine2, result: &mut VectorData) {
552554
for (element, reference) in graphic_group.iter() {
553555
match element {

0 commit comments

Comments
 (0)