mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-03 21:08:18 +00:00
Add seed parameters to all nodes with RNG
This commit is contained in:
parent
e647ca9f91
commit
c39032ab54
7 changed files with 141 additions and 60 deletions
|
@ -10,28 +10,40 @@ use glam::{DAffine2, DVec2};
|
|||
use rand::{Rng, SeedableRng};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct AssignColorsNode<Fill, Stroke, Gradient, Reverse, Randomize, RepeatEvery> {
|
||||
pub struct AssignColorsNode<Fill, Stroke, Gradient, Reverse, Randomize, Seed, RepeatEvery> {
|
||||
fill: Fill,
|
||||
stroke: Stroke,
|
||||
gradient: Gradient,
|
||||
reverse: Reverse,
|
||||
randomize: Randomize,
|
||||
seed: Seed,
|
||||
repeat_every: RepeatEvery,
|
||||
}
|
||||
|
||||
#[node_macro::node_fn(AssignColorsNode)]
|
||||
fn assign_colors_node(group: GraphicGroup, fill: bool, stroke: bool, gradient: GradientStops, reverse: bool, randomize: bool, repeat_every: u32) -> GraphicGroup {
|
||||
fn assign_colors_node(group: GraphicGroup, fill: bool, stroke: bool, gradient: GradientStops, reverse: bool, randomize: bool, seed: u32, repeat_every: u32) -> GraphicGroup {
|
||||
let mut group = group;
|
||||
let vector_data_list: Vec<_> = group.iter_mut().filter_map(|element| element.as_vector_data_mut()).collect();
|
||||
let list = (vector_data_list.len(), vector_data_list.into_iter());
|
||||
|
||||
assign_colors(list, fill, stroke, gradient, reverse, randomize, repeat_every);
|
||||
assign_colors(
|
||||
list,
|
||||
AlignColorsOptions {
|
||||
fill,
|
||||
stroke,
|
||||
gradient,
|
||||
reverse,
|
||||
randomize,
|
||||
seed,
|
||||
repeat_every,
|
||||
},
|
||||
);
|
||||
|
||||
group
|
||||
}
|
||||
|
||||
#[node_macro::node_impl(AssignColorsNode)]
|
||||
fn assign_colors_node(vector_data: VectorData, fill: bool, stroke: bool, gradient: GradientStops, reverse: bool, randomize: bool, repeat_every: u32) -> GraphicGroup {
|
||||
fn assign_colors_node(vector_data: VectorData, fill: bool, stroke: bool, gradient: GradientStops, reverse: bool, randomize: bool, seed: u32, repeat_every: u32) -> GraphicGroup {
|
||||
let mut vector_data_list: Vec<_> = vector_data
|
||||
.region_bezier_paths()
|
||||
.map(|(_, subpath)| {
|
||||
|
@ -44,7 +56,18 @@ fn assign_colors_node(vector_data: VectorData, fill: bool, stroke: bool, gradien
|
|||
.collect();
|
||||
let list = (vector_data_list.len(), vector_data_list.iter_mut().map(|element| element.as_vector_data_mut().unwrap()));
|
||||
|
||||
assign_colors(list, fill, stroke, gradient, reverse, randomize, repeat_every);
|
||||
assign_colors(
|
||||
list,
|
||||
AlignColorsOptions {
|
||||
fill,
|
||||
stroke,
|
||||
gradient,
|
||||
reverse,
|
||||
randomize,
|
||||
seed,
|
||||
repeat_every,
|
||||
},
|
||||
);
|
||||
|
||||
let mut group = GraphicGroup::new(vector_data_list);
|
||||
group.transform = vector_data.transform;
|
||||
|
@ -53,27 +76,37 @@ fn assign_colors_node(vector_data: VectorData, fill: bool, stroke: bool, gradien
|
|||
group
|
||||
}
|
||||
|
||||
fn assign_colors<'a>((length, vector_data): (usize, impl Iterator<Item = &'a mut VectorData>), fill: bool, stroke: bool, gradient: GradientStops, reverse: bool, randomize: bool, repeat_every: u32) {
|
||||
let gradient = if reverse { gradient.reversed() } else { gradient };
|
||||
struct AlignColorsOptions {
|
||||
fill: bool,
|
||||
stroke: bool,
|
||||
gradient: GradientStops,
|
||||
reverse: bool,
|
||||
randomize: bool,
|
||||
seed: u32,
|
||||
repeat_every: u32,
|
||||
}
|
||||
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(0);
|
||||
fn assign_colors<'a>((length, vector_data): (usize, impl Iterator<Item = &'a mut VectorData>), options: AlignColorsOptions) {
|
||||
let gradient = if options.reverse { options.gradient.reversed() } else { options.gradient };
|
||||
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(options.seed as u64);
|
||||
|
||||
for (i, vector_data) in vector_data.enumerate() {
|
||||
let factor = match randomize {
|
||||
let factor = match options.randomize {
|
||||
true => rng.gen::<f64>(),
|
||||
false => match repeat_every {
|
||||
false => match options.repeat_every {
|
||||
0 => i as f64 / (length - 1) as f64,
|
||||
1 => 0.,
|
||||
_ => i as f64 % repeat_every as f64 / (repeat_every - 1) as f64,
|
||||
_ => i as f64 % options.repeat_every as f64 / (options.repeat_every - 1) as f64,
|
||||
},
|
||||
};
|
||||
|
||||
let color = gradient.evalute(factor);
|
||||
|
||||
if fill {
|
||||
if options.fill {
|
||||
vector_data.style.set_fill(Fill::Solid(color));
|
||||
}
|
||||
if stroke {
|
||||
if options.stroke {
|
||||
if let Some(stroke) = vector_data.style.stroke().and_then(|stroke| stroke.with_color(&Some(color))) {
|
||||
vector_data.style.set_stroke(stroke);
|
||||
}
|
||||
|
@ -273,15 +306,18 @@ impl ConcatElement for GraphicGroup {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CopyToPoints<Points, Instance, RandomScaleMin, RandomScaleMax, RandomScaleBias, RandomRotation> {
|
||||
pub struct CopyToPoints<Points, Instance, RandomScaleMin, RandomScaleMax, RandomScaleBias, RandomScaleSeed, RandomRotation, RandomRotationSeed> {
|
||||
points: Points,
|
||||
instance: Instance,
|
||||
random_scale_min: RandomScaleMin,
|
||||
random_scale_max: RandomScaleMax,
|
||||
random_scale_bias: RandomScaleBias,
|
||||
random_scale_seed: RandomScaleSeed,
|
||||
random_rotation: RandomRotation,
|
||||
random_rotation_seed: RandomRotationSeed,
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[node_macro::node_fn(CopyToPoints)]
|
||||
async fn copy_to_points<I: GraphicElementRendered + Default + ConcatElement + TransformMut + Send>(
|
||||
footprint: Footprint,
|
||||
|
@ -290,7 +326,9 @@ async fn copy_to_points<I: GraphicElementRendered + Default + ConcatElement + Tr
|
|||
random_scale_min: f64,
|
||||
random_scale_max: f64,
|
||||
random_scale_bias: f64,
|
||||
random_scale_seed: u32,
|
||||
random_rotation: f64,
|
||||
random_rotation_seed: u32,
|
||||
) -> I {
|
||||
let points = self.points.eval(footprint).await;
|
||||
let instance = self.instance.eval(footprint).await;
|
||||
|
@ -301,8 +339,8 @@ async fn copy_to_points<I: GraphicElementRendered + Default + ConcatElement + Tr
|
|||
let instance_bounding_box = instance.bounding_box(DAffine2::IDENTITY).unwrap_or_default();
|
||||
let instance_center = -0.5 * (instance_bounding_box[0] + instance_bounding_box[1]);
|
||||
|
||||
let mut scale_rng = rand::rngs::StdRng::seed_from_u64(0);
|
||||
let mut rotation_rng = rand::rngs::StdRng::seed_from_u64(0);
|
||||
let mut scale_rng = rand::rngs::StdRng::seed_from_u64(random_scale_seed as u64);
|
||||
let mut rotation_rng = rand::rngs::StdRng::seed_from_u64(random_rotation_seed as u64);
|
||||
|
||||
let do_scale = random_scale_difference.abs() > 1e-6;
|
||||
let do_rotation = random_rotation.abs() > 1e-6;
|
||||
|
@ -425,13 +463,14 @@ async fn sample_points(
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct PoissonDiskPoints<SeparationDiskDiameter> {
|
||||
pub struct PoissonDiskPoints<SeparationDiskDiameter, Seed> {
|
||||
separation_disk_diameter: SeparationDiskDiameter,
|
||||
seed: Seed,
|
||||
}
|
||||
|
||||
#[node_macro::node_fn(PoissonDiskPoints)]
|
||||
fn poisson_disk_points(vector_data: VectorData, separation_disk_diameter: f64) -> VectorData {
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(0);
|
||||
fn poisson_disk_points(vector_data: VectorData, separation_disk_diameter: f64, seed: u32) -> VectorData {
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(seed as u64);
|
||||
let mut result = VectorData::empty();
|
||||
for mut subpath in vector_data.stroke_bezier_paths() {
|
||||
if subpath.manipulator_groups().len() < 3 {
|
||||
|
@ -745,7 +784,9 @@ mod test {
|
|||
random_scale_min: FutureWrapperNode(ClonedNode(1.)),
|
||||
random_scale_max: FutureWrapperNode(ClonedNode(1.)),
|
||||
random_scale_bias: FutureWrapperNode(ClonedNode(0.)),
|
||||
random_scale_seed: FutureWrapperNode(ClonedNode(0)),
|
||||
random_rotation: FutureWrapperNode(ClonedNode(0.)),
|
||||
random_rotation_seed: FutureWrapperNode(ClonedNode(0)),
|
||||
}
|
||||
.eval(Footprint::default())
|
||||
.await;
|
||||
|
@ -798,6 +839,7 @@ mod test {
|
|||
fn poisson() {
|
||||
let sample_points = PoissonDiskPoints {
|
||||
separation_disk_diameter: ClonedNode(10. * std::f64::consts::SQRT_2),
|
||||
seed: ClonedNode(0),
|
||||
}
|
||||
.eval(VectorData::from_subpath(Subpath::new_ellipse(DVec2::NEG_ONE * 50., DVec2::ONE * 50.)));
|
||||
assert!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue