From 388d51deacfaec74e7a8ccbe295747106d66aaf2 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Mon, 7 Aug 2023 14:59:58 +0200 Subject: [PATCH] Add Vector Repeat Node (#1371) * Implement skeleton for repeat node * Implemen RepeatNode --- .../document_node_types.rs | 13 +++++++++ .../node_properties.rs | 7 +++++ node-graph/gcore/src/vector/vector_nodes.rs | 28 +++++++++++++++++++ .../interpreted-executor/src/node_registry.rs | 1 + 4 files changed, 49 insertions(+) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 2f6a99f9d..f73d31e57 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -1749,6 +1749,19 @@ fn static_nodes() -> Vec { properties: node_properties::stroke_properties, ..Default::default() }, + DocumentNodeType { + name: "Repeat", + category: "Vector", + identifier: NodeImplementation::proto("graphene_core::vector::RepeatNode<_, _>"), + inputs: vec![ + DocumentInputType::value("Vector Data", TaggedValue::VectorData(graphene_core::vector::VectorData::empty()), true), + DocumentInputType::value("Direction", TaggedValue::DVec2((100., 0.).into()), false), + DocumentInputType::value("Count", TaggedValue::U32(10), false), + ], + outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::Subpath)], + properties: node_properties::repeat_properties, + ..Default::default() + }, DocumentNodeType { name: "Image Segmentation", category: "Image Adjustments", diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index e95e3b6bd..1f906de3e 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -1583,6 +1583,13 @@ pub fn stroke_properties(document_node: &DocumentNode, node_id: NodeId, _context ] } +pub fn repeat_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let direction = vec2_widget(document_node, node_id, 1, "Direction", "X", "Y", " px", add_blank_assist); + let count = number_widget(document_node, node_id, 2, "Count", NumberInput::default().min(1.), true); + + vec![direction, LayoutGroup::Row { widgets: count }] +} + /// Fill Node Widgets LayoutGroup pub fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let fill_type_index = 1; diff --git a/node-graph/gcore/src/vector/vector_nodes.rs b/node-graph/gcore/src/vector/vector_nodes.rs index be86ea513..638de2a0d 100644 --- a/node-graph/gcore/src/vector/vector_nodes.rs +++ b/node-graph/gcore/src/vector/vector_nodes.rs @@ -1,6 +1,7 @@ use super::style::{Fill, FillType, Gradient, GradientType, Stroke}; use super::VectorData; use crate::{Color, Node}; +use bezier_rs::Subpath; use glam::{DAffine2, DVec2}; #[derive(Debug, Clone, Copy)] @@ -71,3 +72,30 @@ fn set_vector_data_stroke( }); vector_data } + +#[derive(Debug, Clone, Copy)] +pub struct RepeatNode { + direction: Direction, + count: Count, +} + +#[node_macro::node_fn(RepeatNode)] +fn repeat_vector_data(mut vector_data: VectorData, direction: DVec2, count: u32) -> VectorData { + // repeat the vector data + let VectorData { subpaths, transform, .. } = &vector_data; + + let mut new_subpaths: Vec> = Vec::with_capacity(subpaths.len() * count as usize); + let inverse = transform.inverse(); + let direction = inverse.transform_vector2(direction); + for i in 0..count { + let transform = DAffine2::from_translation(direction * i as f64); + log::debug!("transform: {:?}", transform); + for mut subpath in subpaths.clone() { + subpath.apply_transform(transform); + new_subpaths.push(subpath); + } + } + + vector_data.subpaths = new_subpaths; + vector_data +} diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index 58e8a3a96..ffc09a709 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -526,6 +526,7 @@ fn node_registry() -> HashMap, input: ImageFrame, params: [DAffine2]), register_node!(graphene_core::vector::SetFillNode<_, _, _, _, _, _, _>, input: VectorData, params: [graphene_core::vector::style::FillType, Option, graphene_core::vector::style::GradientType, DVec2, DVec2, DAffine2, Vec<(f64, Option)>]), register_node!(graphene_core::vector::SetStrokeNode<_, _, _, _, _, _, _>, input: VectorData, params: [Option, f32, Vec, f32, graphene_core::vector::style::LineCap, graphene_core::vector::style::LineJoin, f32]), + register_node!(graphene_core::vector::RepeatNode<_, _>, input: VectorData, params: [DVec2, u32]), register_node!(graphene_core::vector::generator_nodes::UnitCircleGenerator, input: (), params: []), register_node!( graphene_core::vector::generator_nodes::PathGenerator<_>,