mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 13:30:48 +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
2
demo-artwork/procedural-string-lights.graphite
generated
2
demo-artwork/procedural-string-lights.graphite
generated
File diff suppressed because one or more lines are too long
2
demo-artwork/red-dress.graphite
generated
2
demo-artwork/red-dress.graphite
generated
File diff suppressed because one or more lines are too long
|
@ -3521,7 +3521,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
category: "Vector: Style",
|
||||
node_template: NodeTemplate {
|
||||
document_node: DocumentNode {
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::vector::AssignColorsNode<_, _, _, _, _, _>"),
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::vector::AssignColorsNode<_, _, _, _, _, _, _>"),
|
||||
inputs: vec![
|
||||
NodeInput::value(TaggedValue::GraphicGroup(graphene_core::GraphicGroup::default()), true),
|
||||
NodeInput::value(TaggedValue::Bool(true), false),
|
||||
|
@ -3530,6 +3530,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
NodeInput::value(TaggedValue::Bool(false), false),
|
||||
NodeInput::value(TaggedValue::Bool(false), false),
|
||||
NodeInput::value(TaggedValue::U32(0), false),
|
||||
NodeInput::value(TaggedValue::U32(0), false),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -3541,6 +3542,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
"Gradient".to_string(),
|
||||
"Reverse".to_string(),
|
||||
"Randomize".to_string(),
|
||||
"Seed".to_string(),
|
||||
"Repeat Every".to_string(),
|
||||
],
|
||||
output_names: vec!["Vector Group".to_string()],
|
||||
|
@ -3745,14 +3747,16 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
node_template: NodeTemplate {
|
||||
document_node: DocumentNode {
|
||||
// TODO: Wrap this implementation with a document node that has a cache node so the output is cached?
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::vector::CopyToPoints<_, _, _, _, _, _>"),
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::vector::CopyToPoints<_, _, _, _, _, _, _, _>"),
|
||||
inputs: vec![
|
||||
NodeInput::value(TaggedValue::VectorData(graphene_core::vector::VectorData::empty()), true),
|
||||
NodeInput::value(TaggedValue::VectorData(graphene_core::vector::VectorData::empty()), true),
|
||||
NodeInput::value(TaggedValue::F64(1.), false),
|
||||
NodeInput::value(TaggedValue::F64(1.), false),
|
||||
NodeInput::value(TaggedValue::F64(0.), false),
|
||||
NodeInput::value(TaggedValue::U32(0), false),
|
||||
NodeInput::value(TaggedValue::F64(0.), false),
|
||||
NodeInput::value(TaggedValue::U32(0), false),
|
||||
],
|
||||
manual_composition: Some(concrete!(Footprint)),
|
||||
..Default::default()
|
||||
|
@ -3764,7 +3768,9 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
"Random Scale Min".to_string(),
|
||||
"Random Scale Max".to_string(),
|
||||
"Random Scale Bias".to_string(),
|
||||
"Random Scale Seed".to_string(),
|
||||
"Random Rotation".to_string(),
|
||||
"Random Rotation Seed".to_string(),
|
||||
],
|
||||
output_names: vec!["Vector".to_string()],
|
||||
..Default::default()
|
||||
|
@ -3876,8 +3882,12 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
exports: vec![NodeInput::node(NodeId(1), 0)],
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::network(concrete!(graphene_core::vector::VectorData), 0), NodeInput::network(concrete!(f64), 1)],
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::vector::PoissonDiskPoints<_>"),
|
||||
inputs: vec![
|
||||
NodeInput::network(concrete!(graphene_core::vector::VectorData), 0),
|
||||
NodeInput::network(concrete!(f64), 1),
|
||||
NodeInput::network(concrete!(u32), 2),
|
||||
],
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::vector::PoissonDiskPoints<_, _>"),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
|
@ -3896,6 +3906,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
inputs: vec![
|
||||
NodeInput::value(TaggedValue::VectorData(graphene_core::vector::VectorData::empty()), true),
|
||||
NodeInput::value(TaggedValue::F64(10.), false),
|
||||
NodeInput::value(TaggedValue::U32(0), false),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -3926,7 +3937,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
},
|
||||
..Default::default()
|
||||
}),
|
||||
input_names: vec!["Vector Data".to_string(), "Separation Disk Diameter".to_string()],
|
||||
input_names: vec!["Vector Data".to_string(), "Separation Disk Diameter".to_string(), "Seed".to_string()],
|
||||
output_names: vec!["Vector".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
|
|
|
@ -1825,7 +1825,7 @@ impl NodeGraphMessageHandler {
|
|||
fn build_wire_path_locations(output_position: DVec2, input_position: DVec2, vertical_out: bool, vertical_in: bool) -> Vec<DVec2> {
|
||||
let horizontal_gap = (output_position.x - input_position.x).abs();
|
||||
let vertical_gap = (output_position.y - input_position.y).abs();
|
||||
// TODO: Finish this commented out code replacement for the code below it based on this diagram: <https://files.keavon.com/-/InsubstantialElegantQueenant/capture.png>
|
||||
// TODO: Finish this commented out code replacement for the code below it based on this diagram: <https://files.keavon.com/-/SuperbWideFoxterrier/capture.png>
|
||||
// // Straight: stacking lines which are always straight, or a straight horizontal wire between two aligned nodes
|
||||
// if ((verticalOut && vertical_in) || (!verticalOut && !vertical_in && vertical_gap === 0)) {
|
||||
// return [
|
||||
|
|
|
@ -122,7 +122,7 @@ fn text_area_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
|
|||
widgets
|
||||
}
|
||||
|
||||
fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> Vec<WidgetHolder> {
|
||||
fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, checkbox_input: CheckboxInput, blank_assist: bool) -> Vec<WidgetHolder> {
|
||||
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
|
||||
|
||||
let Some(input) = document_node.inputs.get(index) else {
|
||||
|
@ -132,7 +132,8 @@ fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
|||
if let Some(&TaggedValue::Bool(x)) = &input.as_non_exposed_value() {
|
||||
widgets.extend_from_slice(&[
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
CheckboxInput::new(x)
|
||||
checkbox_input
|
||||
.checked(x)
|
||||
.on_update(update_value(|x: &CheckboxInput| TaggedValue::Bool(x.checked), node_id, index))
|
||||
.on_commit(commit_value)
|
||||
.widget_holder(),
|
||||
|
@ -372,7 +373,7 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
|||
LayoutGroup::Row { widgets }
|
||||
}
|
||||
|
||||
fn vec_f64_input(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, text_props: TextInput, blank_assist: bool) -> Vec<WidgetHolder> {
|
||||
fn vec_f64_input(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, text_input: TextInput, blank_assist: bool) -> Vec<WidgetHolder> {
|
||||
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Number, blank_assist);
|
||||
|
||||
let from_string = |string: &str| {
|
||||
|
@ -392,7 +393,7 @@ fn vec_f64_input(document_node: &DocumentNode, node_id: NodeId, index: usize, na
|
|||
if let Some(TaggedValue::VecF64(x)) = &input.as_non_exposed_value() {
|
||||
widgets.extend_from_slice(&[
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
text_props
|
||||
text_input
|
||||
.value(x.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", "))
|
||||
.on_update(optionally_update_value(move |x: &TextInput| from_string(&x.value), node_id, index))
|
||||
.widget_holder(),
|
||||
|
@ -990,7 +991,7 @@ pub fn vector2_properties(document_node: &DocumentNode, node_id: NodeId, _contex
|
|||
}
|
||||
|
||||
pub fn boolean_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let widgets = bool_widget(document_node, node_id, 0, "Bool", true);
|
||||
let widgets = bool_widget(document_node, node_id, 0, "Bool", CheckboxInput::default(), true);
|
||||
|
||||
vec![LayoutGroup::Row { widgets }]
|
||||
}
|
||||
|
@ -1065,7 +1066,7 @@ pub fn noise_pattern_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|||
|
||||
// All
|
||||
let clip = LayoutGroup::Row {
|
||||
widgets: bool_widget(document_node, node_id, 0, "Clip", true),
|
||||
widgets: bool_widget(document_node, node_id, 0, "Clip", CheckboxInput::default(), true),
|
||||
};
|
||||
let seed = number_widget(document_node, node_id, 1, "Seed", NumberInput::default().min(0.).is_integer(true), true);
|
||||
let scale = number_widget(document_node, node_id, 2, "Scale", NumberInput::default().min(0.).disabled(!coherent_noise_active), true);
|
||||
|
@ -1204,7 +1205,7 @@ pub fn hue_saturation_properties(document_node: &DocumentNode, node_id: NodeId,
|
|||
pub fn brightness_contrast_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let brightness = number_widget(document_node, node_id, 1, "Brightness", NumberInput::default().min(-150.).max(150.), true);
|
||||
let contrast = number_widget(document_node, node_id, 2, "Contrast", NumberInput::default().min(-100.).max(100.), true);
|
||||
let use_legacy = bool_widget(document_node, node_id, 3, "Use Legacy", true);
|
||||
let use_legacy = bool_widget(document_node, node_id, 3, "Use Legacy", CheckboxInput::default(), true);
|
||||
|
||||
vec![
|
||||
LayoutGroup::Row { widgets: brightness },
|
||||
|
@ -1239,7 +1240,7 @@ pub fn gradient_map_properties(document_node: &DocumentNode, node_id: NodeId, _c
|
|||
let reverse_index = 2;
|
||||
|
||||
let gradient_row = color_widget(document_node, node_id, gradient_index, "Gradient", ColorButton::default().allow_none(false), true);
|
||||
let reverse_row = bool_widget(document_node, node_id, reverse_index, "Reverse", true);
|
||||
let reverse_row = bool_widget(document_node, node_id, reverse_index, "Reverse", CheckboxInput::default(), true);
|
||||
|
||||
vec![gradient_row, LayoutGroup::Row { widgets: reverse_row }]
|
||||
}
|
||||
|
@ -1250,18 +1251,20 @@ pub fn assign_colors_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|||
let gradient_index = 3;
|
||||
let reverse_index = 4;
|
||||
let randomize_index = 5;
|
||||
let repeat_every_index = 6;
|
||||
let seed_index = 6;
|
||||
let repeat_every_index = 7;
|
||||
|
||||
let fill_row = bool_widget(document_node, node_id, fill_index, "Fill", true);
|
||||
let stroke_row = bool_widget(document_node, node_id, stroke_index, "Stroke", true);
|
||||
let fill_row = bool_widget(document_node, node_id, fill_index, "Fill", CheckboxInput::default(), true);
|
||||
let stroke_row = bool_widget(document_node, node_id, stroke_index, "Stroke", CheckboxInput::default(), true);
|
||||
let gradient_row = color_widget(document_node, node_id, gradient_index, "Gradient", ColorButton::default().allow_none(false), true);
|
||||
let reverse_row = bool_widget(document_node, node_id, reverse_index, "Reverse", true);
|
||||
let randomize_row = bool_widget(document_node, node_id, randomize_index, "Randomize", true);
|
||||
let reverse_row = bool_widget(document_node, node_id, reverse_index, "Reverse", CheckboxInput::default(), true);
|
||||
let randomize_enabled = if let Some(&TaggedValue::Bool(randomize_enabled)) = &document_node.inputs[randomize_index].as_value() {
|
||||
randomize_enabled
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let randomize_row = bool_widget(document_node, node_id, randomize_index, "Randomize", CheckboxInput::default(), true);
|
||||
let seed_row = number_widget(document_node, node_id, seed_index, "Seed", NumberInput::default().min(0.).int().disabled(!randomize_enabled), true);
|
||||
let repeat_every_row = number_widget(
|
||||
document_node,
|
||||
node_id,
|
||||
|
@ -1277,6 +1280,7 @@ pub fn assign_colors_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|||
gradient_row,
|
||||
LayoutGroup::Row { widgets: reverse_row },
|
||||
LayoutGroup::Row { widgets: randomize_row },
|
||||
LayoutGroup::Row { widgets: seed_row },
|
||||
LayoutGroup::Row { widgets: repeat_every_row },
|
||||
]
|
||||
}
|
||||
|
@ -1299,7 +1303,7 @@ pub fn vibrance_properties(document_node: &DocumentNode, node_id: NodeId, _conte
|
|||
pub fn channel_mixer_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
// Monochrome
|
||||
let monochrome_index = 1;
|
||||
let monochrome = bool_widget(document_node, node_id, monochrome_index, "Monochrome", true);
|
||||
let monochrome = bool_widget(document_node, node_id, monochrome_index, "Monochrome", CheckboxInput::default(), true);
|
||||
let is_monochrome = if let Some(&TaggedValue::Bool(monochrome_choice)) = &document_node.inputs[monochrome_index].as_value() {
|
||||
monochrome_choice
|
||||
} else {
|
||||
|
@ -1721,7 +1725,7 @@ pub fn rectangle_properties(document_node: &DocumentNode, node_id: NodeId, _cont
|
|||
}
|
||||
|
||||
// Clamped
|
||||
let clamped = bool_widget(document_node, node_id, clamped_index, "Clamped", true);
|
||||
let clamped = bool_widget(document_node, node_id, clamped_index, "Clamped", CheckboxInput::default(), true);
|
||||
|
||||
vec![
|
||||
LayoutGroup::Row { widgets: size_x },
|
||||
|
@ -1758,7 +1762,7 @@ pub fn spline_properties(document_node: &DocumentNode, node_id: NodeId, _context
|
|||
}
|
||||
|
||||
pub fn logic_operator_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let widgets = bool_widget(document_node, node_id, 0, "Operand B", true);
|
||||
let widgets = bool_widget(document_node, node_id, 0, "Operand B", CheckboxInput::default(), true);
|
||||
vec![LayoutGroup::Row { widgets }]
|
||||
}
|
||||
|
||||
|
@ -2195,7 +2199,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
|||
LayoutGroup::Row { widgets }.with_tooltip("A negative text prompt can be used to list things like objects or colors to avoid")
|
||||
};
|
||||
let base_image = {
|
||||
let widgets = bool_widget(document_node, node_id, base_img_index, "Adapt Input Image", true);
|
||||
let widgets = bool_widget(document_node, node_id, base_img_index, "Adapt Input Image", CheckboxInput::default(), true);
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Generate an image based upon the bitmap data plugged into this node")
|
||||
};
|
||||
let image_creativity = {
|
||||
|
@ -2286,7 +2290,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
|||
// }
|
||||
|
||||
let improve_faces = {
|
||||
let widgets = bool_widget(document_node, node_id, faces_index, "Improve Faces", true);
|
||||
let widgets = bool_widget(document_node, node_id, faces_index, "Improve Faces", CheckboxInput::default(), true);
|
||||
LayoutGroup::Row { widgets }.with_tooltip(
|
||||
"Postprocess human (or human-like) faces to look subtly less distorted.\n\
|
||||
\n\
|
||||
|
@ -2294,7 +2298,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
|
|||
)
|
||||
};
|
||||
let tiling = {
|
||||
let widgets = bool_widget(document_node, node_id, tiling_index, "Tiling", true);
|
||||
let widgets = bool_widget(document_node, node_id, tiling_index, "Tiling", CheckboxInput::default(), true);
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Generate the image so its edges loop seamlessly to make repeatable patterns or textures")
|
||||
};
|
||||
layout.extend_from_slice(&[improve_faces, tiling]);
|
||||
|
@ -2413,12 +2417,20 @@ pub fn boolean_operation_properties(document_node: &DocumentNode, node_id: NodeI
|
|||
}
|
||||
|
||||
pub fn copy_to_points_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let instance = vector_widget(document_node, node_id, 1, "Instance", true);
|
||||
let instance_index = 1;
|
||||
let random_scale_min_index = 2;
|
||||
let random_scale_max_index = 3;
|
||||
let random_scale_bias_index = 4;
|
||||
let random_scale_seed_index = 5;
|
||||
let random_rotation_index = 6;
|
||||
let random_rotation_seed_index = 7;
|
||||
|
||||
let instance = vector_widget(document_node, node_id, instance_index, "Instance", true);
|
||||
|
||||
let random_scale_min = number_widget(
|
||||
document_node,
|
||||
node_id,
|
||||
2,
|
||||
random_scale_min_index,
|
||||
"Random Scale Min",
|
||||
NumberInput::default().min(0.).mode_range().range_min(Some(0.)).range_max(Some(2.)).unit("x"),
|
||||
true,
|
||||
|
@ -2426,7 +2438,7 @@ pub fn copy_to_points_properties(document_node: &DocumentNode, node_id: NodeId,
|
|||
let random_scale_max = number_widget(
|
||||
document_node,
|
||||
node_id,
|
||||
3,
|
||||
random_scale_max_index,
|
||||
"Random Scale Max",
|
||||
NumberInput::default().min(0.).mode_range().range_min(Some(0.)).range_max(Some(2.)).unit("x"),
|
||||
true,
|
||||
|
@ -2434,13 +2446,22 @@ pub fn copy_to_points_properties(document_node: &DocumentNode, node_id: NodeId,
|
|||
let random_scale_bias = number_widget(
|
||||
document_node,
|
||||
node_id,
|
||||
4,
|
||||
random_scale_bias_index,
|
||||
"Random Scale Bias",
|
||||
NumberInput::default().mode_range().range_min(Some(-50.)).range_max(Some(50.)),
|
||||
true,
|
||||
);
|
||||
let random_scale_seed = number_widget(document_node, node_id, random_scale_seed_index, "Random Scale Seed", NumberInput::default().int().min(0.), true);
|
||||
|
||||
let random_rotation = number_widget(document_node, node_id, 5, "Random Rotation", NumberInput::default().min(0.).max(360.).mode_range().unit("°"), true);
|
||||
let random_rotation = number_widget(
|
||||
document_node,
|
||||
node_id,
|
||||
random_rotation_index,
|
||||
"Random Rotation",
|
||||
NumberInput::default().min(0.).max(360.).mode_range().unit("°"),
|
||||
true,
|
||||
);
|
||||
let random_rotation_seed = number_widget(document_node, node_id, random_rotation_seed_index, "Random Rotation Seed", NumberInput::default().int().min(0.), true);
|
||||
|
||||
vec![
|
||||
LayoutGroup::Row { widgets: instance }.with_tooltip("Artwork to be copied and placed at each point"),
|
||||
|
@ -2448,7 +2469,9 @@ pub fn copy_to_points_properties(document_node: &DocumentNode, node_id: NodeId,
|
|||
LayoutGroup::Row { widgets: random_scale_max }.with_tooltip("Maximum range of randomized sizes given to each instance"),
|
||||
LayoutGroup::Row { widgets: random_scale_bias }
|
||||
.with_tooltip("Bias for the probability distribution of randomized sizes (0 is uniform, negatives favor more of small sizes, positives favor more of large sizes)"),
|
||||
LayoutGroup::Row { widgets: random_scale_seed }.with_tooltip("Seed to determine unique variations on all the randomized instance sizes"),
|
||||
LayoutGroup::Row { widgets: random_rotation }.with_tooltip("Range of randomized angles given to each instance, in degrees ranging from furthest clockwise to counterclockwise"),
|
||||
LayoutGroup::Row { widgets: random_rotation_seed }.with_tooltip("Seed to determine unique variations on all the randomized instance angles"),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -2456,7 +2479,7 @@ pub fn sample_points_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|||
let spacing = number_widget(document_node, node_id, 1, "Spacing", NumberInput::default().min(1.).unit(" px"), true);
|
||||
let start_offset = number_widget(document_node, node_id, 2, "Start Offset", NumberInput::default().min(0.).unit(" px"), true);
|
||||
let stop_offset = number_widget(document_node, node_id, 3, "Stop Offset", NumberInput::default().min(0.).unit(" px"), true);
|
||||
let adaptive_spacing = bool_widget(document_node, node_id, 4, "Adaptive Spacing", true);
|
||||
let adaptive_spacing = bool_widget(document_node, node_id, 4, "Adaptive Spacing", CheckboxInput::default(), true);
|
||||
|
||||
vec![
|
||||
LayoutGroup::Row { widgets: spacing }.with_tooltip("Distance between each instance (exact if 'Adaptive Spacing' is disabled, approximate if enabled)"),
|
||||
|
@ -2467,16 +2490,21 @@ pub fn sample_points_properties(document_node: &DocumentNode, node_id: NodeId, _
|
|||
}
|
||||
|
||||
pub fn poisson_disk_points_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let separation_disk_diameter_index = 1;
|
||||
let seed_index = 2;
|
||||
|
||||
let spacing = number_widget(
|
||||
document_node,
|
||||
node_id,
|
||||
1,
|
||||
separation_disk_diameter_index,
|
||||
"Separation Disk Diameter",
|
||||
NumberInput::default().min(0.01).mode_range().range_min(Some(1.)).range_max(Some(100.)),
|
||||
true,
|
||||
);
|
||||
|
||||
vec![LayoutGroup::Row { widgets: spacing }]
|
||||
let seed = number_widget(document_node, node_id, seed_index, "Seed", NumberInput::default().int().min(0.), true);
|
||||
|
||||
vec![LayoutGroup::Row { widgets: spacing }, LayoutGroup::Row { widgets: seed }]
|
||||
}
|
||||
|
||||
pub fn morph_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
|
@ -2622,7 +2650,7 @@ pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _conte
|
|||
let location = vec2_widget(document_node, node_id, 2, "Location", "X", "Y", " px", None, add_blank_assist);
|
||||
let dimensions = vec2_widget(document_node, node_id, 3, "Dimensions", "W", "H", " px", None, add_blank_assist);
|
||||
let background = color_widget(document_node, node_id, 4, "Background", ColorButton::default().allow_none(false), true);
|
||||
let clip = bool_widget(document_node, node_id, 5, "Clip", true);
|
||||
let clip = bool_widget(document_node, node_id, 5, "Clip", CheckboxInput::default(), true);
|
||||
|
||||
let clip_row = LayoutGroup::Row { widgets: clip };
|
||||
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -679,8 +679,8 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
register_node!(graphene_core::vector::SetFillNode<_>, input: VectorData, params: [Color]),
|
||||
register_node!(graphene_core::vector::SetFillNode<_>, input: VectorData, params: [Option<Color>]),
|
||||
register_node!(graphene_core::vector::SetFillNode<_>, input: VectorData, params: [graphene_std::vector::style::Gradient]),
|
||||
register_node!(graphene_core::vector::AssignColorsNode<_, _, _, _, _, _>, input: GraphicGroup, params: [bool, bool, graphene_std::vector::style::GradientStops, bool, bool, u32]),
|
||||
register_node!(graphene_core::vector::AssignColorsNode<_, _, _, _, _, _>, input: VectorData, params: [bool, bool, graphene_std::vector::style::GradientStops, bool, bool, u32]),
|
||||
register_node!(graphene_core::vector::AssignColorsNode<_, _, _, _, _, _, _>, input: GraphicGroup, params: [bool, bool, graphene_std::vector::style::GradientStops, bool, bool, u32, u32]),
|
||||
register_node!(graphene_core::vector::AssignColorsNode<_, _, _, _, _, _, _>, input: VectorData, params: [bool, bool, graphene_std::vector::style::GradientStops, bool, bool, u32, u32]),
|
||||
register_node!(graphene_core::vector::SetStrokeNode<_, _, _, _, _, _, _>, input: VectorData, params: [Option<graphene_core::Color>, f64, Vec<f64>, f64, graphene_core::vector::style::LineCap, graphene_core::vector::style::LineJoin, f64]),
|
||||
register_node!(graphene_core::vector::RepeatNode<_, _, _>, input: VectorData, params: [DVec2, f64, u32]),
|
||||
register_node!(graphene_core::vector::BoundingBoxNode, input: VectorData, params: []),
|
||||
|
@ -748,10 +748,10 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
)],
|
||||
register_node!(graphene_std::raster::SampleNode<_>, input: Footprint, params: [ImageFrame<Color>]),
|
||||
register_node!(graphene_std::raster::MandelbrotNode, input: Footprint, params: []),
|
||||
async_node!(graphene_core::vector::CopyToPoints<_, _, _, _, _, _>, input: Footprint, output: VectorData, fn_params: [Footprint => VectorData, Footprint => VectorData, () => f64, () => f64, () => f64, () => f64]),
|
||||
async_node!(graphene_core::vector::CopyToPoints<_, _, _, _, _, _>, input: Footprint, output: GraphicGroup, fn_params: [Footprint => VectorData, Footprint => GraphicGroup, () => f64, () => f64, () => f64, () => f64]),
|
||||
async_node!(graphene_core::vector::CopyToPoints<_, _, _, _, _, _, _, _>, input: Footprint, output: VectorData, fn_params: [Footprint => VectorData, Footprint => VectorData, () => f64, () => f64, () => f64, () => u32, () => f64, () => u32]),
|
||||
async_node!(graphene_core::vector::CopyToPoints<_, _, _, _, _, _, _, _>, input: Footprint, output: GraphicGroup, fn_params: [Footprint => VectorData, Footprint => GraphicGroup, () => f64, () => f64, () => f64, () => u32, () => f64, () => u32]),
|
||||
async_node!(graphene_core::vector::SamplePoints<_, _, _, _, _, _>, input: Footprint, output: VectorData, fn_params: [Footprint => VectorData, () => f64, () => f64, () => f64, () => bool, Footprint => Vec<f64>]),
|
||||
register_node!(graphene_core::vector::PoissonDiskPoints<_>, input: VectorData, params: [f64]),
|
||||
register_node!(graphene_core::vector::PoissonDiskPoints<_, _>, input: VectorData, params: [f64, u32]),
|
||||
register_node!(graphene_core::vector::LengthsOfSegmentsOfSubpaths, input: VectorData, params: []),
|
||||
register_node!(graphene_core::vector::SplinesFromPointsNode, input: VectorData, params: []),
|
||||
async_node!(graphene_core::vector::AreaNode<_>, input: (), output: f64, fn_params: [Footprint => VectorData]),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue