Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the Fill and Stroke nodes to work on groups #2046

Merged
merged 4 commits into from
Oct 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 82 additions & 24 deletions node-graph/gcore/src/vector/vector_nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,27 @@ use bezier_rs::{Cap, Join, Subpath, SubpathTValue, TValue};
use glam::{DAffine2, DVec2};
use rand::{Rng, SeedableRng};

/// Implemented for types that can be converted to an iterator of vector data.
/// Used for the fill and stroke node so they can be used on VectorData or GraphicGroup
trait VectorIterMut {
fn vector_iter_mut(&mut self) -> impl ExactSizeIterator<Item = &mut VectorData>;
fn vector_iter_mut(&mut self) -> impl Iterator<Item = (&mut VectorData, DAffine2)>;
}

impl VectorIterMut for GraphicGroup {
fn vector_iter_mut(&mut self) -> impl ExactSizeIterator<Item = &mut VectorData> {
self.iter_mut().filter_map(|(element, _)| element.as_vector_data_mut()).collect::<Vec<_>>().into_iter()
fn vector_iter_mut(&mut self) -> impl Iterator<Item = (&mut VectorData, DAffine2)> {
let parent_transform = self.transform;
// Grab only the direct children (perhaps unintuitive?)
self.iter_mut().filter_map(|(element, _)| element.as_vector_data_mut()).map(move |vector| {
let transform = parent_transform * vector.transform;
(vector, transform)
})
}
}

impl VectorIterMut for VectorData {
fn vector_iter_mut(&mut self) -> impl ExactSizeIterator<Item = &mut VectorData> {
std::iter::once(self)
fn vector_iter_mut(&mut self) -> impl Iterator<Item = (&mut VectorData, DAffine2)> {
let transform = self.transform;
std::iter::once((self, transform))
}
}

Expand Down Expand Up @@ -51,13 +59,12 @@ async fn assign_colors<F: 'n + Send, T: VectorIterMut>(
repeat_every: u32,
) -> T {
let mut input = vector_group.eval(footprint).await;
let vector_data = input.vector_iter_mut();
let length = vector_data.len();
let length = input.vector_iter_mut().count();
let gradient = if reverse { gradient.reversed() } else { gradient };

let mut rng = rand::rngs::StdRng::seed_from_u64(seed.into());

for (i, vector_data) in vector_data.enumerate() {
for (i, (vector_data, _)) in input.vector_iter_mut().enumerate() {
let factor = match randomize {
true => rng.gen::<f64>(),
false => match repeat_every {
Expand All @@ -82,12 +89,23 @@ async fn assign_colors<F: 'n + Send, T: VectorIterMut>(
}

#[node_macro::node(category("Vector: Style"), path(graphene_core::vector))]
async fn fill<F: 'n + Send, T: Into<Fill> + 'n + Send>(
async fn fill<F: 'n + Send, FillTy: Into<Fill> + 'n + Send, TargetTy: VectorIterMut + 'n + Send>(
#[implementations(
(),
(),
(),
(),
(),
(),
(),
(),
Footprint,
Footprint,
Footprint,
Footprint,
Footprint,
Footprint,
Footprint,
Footprint,
)]
footprint: F,
Expand All @@ -96,9 +114,20 @@ async fn fill<F: 'n + Send, T: Into<Fill> + 'n + Send>(
() -> VectorData,
() -> VectorData,
() -> VectorData,
() -> GraphicGroup,
() -> GraphicGroup,
() -> GraphicGroup,
() -> GraphicGroup,
Footprint -> VectorData,
Footprint -> VectorData,
Footprint -> VectorData,
Footprint -> VectorData,
Footprint -> GraphicGroup,
Footprint -> GraphicGroup,
Footprint -> GraphicGroup,
Footprint -> GraphicGroup,
)]
vector_data: impl Node<F, Output = VectorData>,
vector_data: impl Node<F, Output = TargetTy>,
#[implementations(
Fill,
Option<Color>,
Expand All @@ -108,59 +137,88 @@ async fn fill<F: 'n + Send, T: Into<Fill> + 'n + Send>(
Option<Color>,
Color,
Gradient,
Fill,
Option<Color>,
Color,
Gradient,
Fill,
Option<Color>,
Color,
Gradient,
)]
#[default(Color::BLACK)]
fill: T,
fill: FillTy,
_backup_color: Option<Color>,
_backup_gradient: Gradient,
) -> VectorData {
let mut vector_data = vector_data.eval(footprint).await;
vector_data.style.set_fill(fill.into());
) -> TargetTy {
let mut target = vector_data.eval(footprint).await;
let fill: Fill = fill.into();
for (target, _transform) in target.vector_iter_mut() {
target.style.set_fill(fill.clone());
}

vector_data
target
}

#[node_macro::node(category("Vector: Style"), path(graphene_core::vector))]
async fn stroke<F: 'n + Send, T: Into<Option<Color>> + 'n + Send>(
async fn stroke<F: 'n + Send, ColourTy: Into<Option<Color>> + 'n + Send, TargetTy: VectorIterMut + 'n + Send>(
#[implementations(
(),
(),
(),
(),
Footprint,
Footprint,
Footprint,
Footprint,
)]
footprint: F,
#[implementations(
() -> VectorData,
() -> VectorData,
() -> GraphicGroup,
() -> GraphicGroup,
Footprint -> VectorData,
Footprint -> VectorData,
Footprint -> GraphicGroup,
Footprint -> GraphicGroup,
)]
vector_data: impl Node<F, Output = VectorData>,
vector_data: impl Node<F, Output = TargetTy>,
#[implementations(
Option<Color>,
Color,
Option<Color>,
Color,
Option<Color>,
Color,
Option<Color>,
Color,
)]
#[default(Color::BLACK)]
color: T,
color: ColourTy,
#[default(2.)] weight: f64,
dash_lengths: Vec<f64>,
dash_offset: f64,
line_cap: crate::vector::style::LineCap,
line_join: LineJoin,
#[default(4.)] miter_limit: f64,
) -> VectorData {
let mut vector_data = vector_data.eval(footprint).await;
vector_data.style.set_stroke(Stroke {
) -> TargetTy {
let mut target = vector_data.eval(footprint).await;
let stroke = Stroke {
color: color.into(),
weight,
dash_lengths,
dash_offset,
line_cap,
line_join,
line_join_miter_limit: miter_limit,
transform: vector_data.transform,
});
vector_data
transform: DAffine2::IDENTITY,
};
for (target, transform) in target.vector_iter_mut() {
target.style.set_stroke(Stroke { transform, ..stroke.clone() });
}

target
}

#[node_macro::node(category("Vector"), path(graphene_core::vector))]
Expand Down
Loading