From 7d86bf4abf7edfe6a5d021075e050614bee07c13 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Sat, 2 Nov 2024 16:37:27 -0700 Subject: [PATCH] New node: Jitter Points --- node-graph/gcore/src/vector/vector_nodes.rs | 62 +++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/node-graph/gcore/src/vector/vector_nodes.rs b/node-graph/gcore/src/vector/vector_nodes.rs index 2bc8374b..a89a15a2 100644 --- a/node-graph/gcore/src/vector/vector_nodes.rs +++ b/node-graph/gcore/src/vector/vector_nodes.rs @@ -975,6 +975,68 @@ async fn splines_from_points( vector_data } +#[node_macro::node(category("Vector"), path(graphene_core::vector))] +async fn jitter_points( + #[implementations( + (), + Footprint, + )] + footprint: F, + #[implementations( + () -> VectorData, + Footprint -> VectorData, + )] + vector_data: impl Node, + #[default(5.)] amount: f64, + seed: SeedValue, +) -> VectorData { + let mut vector_data = vector_data.eval(footprint).await; + + let mut rng = rand::rngs::StdRng::seed_from_u64(seed.into()); + + let deltas = (0..vector_data.point_domain.positions().len()) + .map(|_| { + let angle = rng.gen::() * std::f64::consts::TAU; + DVec2::from_angle(angle) * rng.gen::() * amount + }) + .collect::>(); + let mut already_applied = vec![false; vector_data.point_domain.positions().len()]; + + for (handles, start, end) in vector_data.segment_domain.handles_and_points_mut() { + let start_delta = deltas[*start]; + let end_delta = deltas[*end]; + + if !already_applied[*start] { + let start_position = vector_data.point_domain.positions()[*start]; + let start_position = vector_data.transform.transform_point2(start_position); + vector_data.point_domain.set_position(*start, start_position + start_delta); + already_applied[*start] = true; + } + if !already_applied[*end] { + let end_position = vector_data.point_domain.positions()[*end]; + let end_position = vector_data.transform.transform_point2(end_position); + vector_data.point_domain.set_position(*end, end_position + end_delta); + already_applied[*end] = true; + } + + match handles { + bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => { + *handle_start = vector_data.transform.transform_point2(*handle_start) + start_delta; + *handle_end += vector_data.transform.transform_point2(*handle_end) + end_delta; + } + bezier_rs::BezierHandles::Quadratic { handle } => { + *handle += vector_data.transform.transform_point2(*handle) + (start_delta + end_delta) / 2.; + } + bezier_rs::BezierHandles::Linear => {} + } + } + + vector_data.transform = DAffine2::IDENTITY; + vector_data.style.set_stroke_transform(DAffine2::IDENTITY); + + vector_data +} + #[node_macro::node(category("Vector"), path(graphene_core::vector))] async fn morph( #[implementations(