Skip to content

Commit 1edfe57

Browse files
committed
Add stroke scaling option to Stroke node (#2960)
Add a "Scaling" field to the Stroke node that allows users to toggle whether strokes should scale with shape transformations or maintain a constant visual width. * Add StrokeScaling enum with ScaleWithShape and NonScaling options * Add new "Scaling" parameter to the Stroke node * Update document migration to handle the new parameter * Fix migration bug that caused index out of bounds error * Remove duplicate apply_stroke call in shape_tool.rs Closes #2960
1 parent 3cc9dd7 commit 1edfe57

File tree

6 files changed

+41
-6
lines changed

6 files changed

+41
-6
lines changed

editor/src/messages/portfolio/document/node_graph/node_properties.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use graphene_std::vector::misc::GridType;
2727
use graphene_std::vector::misc::{ArcType, MergeByDistanceAlgorithm};
2828
use graphene_std::vector::misc::{CentroidType, PointSpacingType};
2929
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops};
30-
use graphene_std::vector::style::{GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};
30+
use graphene_std::vector::style::{GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, StrokeScaling};
3131
use graphene_std::{GraphicGroupTable, NodeInputDecleration};
3232

3333
pub(crate) fn string_properties(text: &str) -> Vec<LayoutGroup> {
@@ -1807,6 +1807,9 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
18071807
let dash_lengths = array_of_number_widget(ParameterWidgetsInfo::new(node_id, DashLengthsInput::INDEX, true, context), TextInput::default().centered(true));
18081808
let number_input = disabled_number_input;
18091809
let dash_offset = number_widget(ParameterWidgetsInfo::new(node_id, DashOffsetInput::INDEX, true, context), number_input);
1810+
let scaling = enum_choice::<StrokeScaling>()
1811+
.for_socket(ParameterWidgetsInfo::new(node_id, ScalingInput::INDEX, true, context))
1812+
.property_row();
18101813

18111814
vec![
18121815
color,
@@ -1818,6 +1821,7 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
18181821
paint_order,
18191822
LayoutGroup::Row { widgets: dash_lengths },
18201823
LayoutGroup::Row { widgets: dash_offset },
1824+
scaling,
18211825
]
18221826
}
18231827

editor/src/messages/portfolio/document_migration.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use graph_craft::document::{DocumentNodeImplementation, NodeInput, value::Tagged
1212
use graphene_std::ProtoNodeIdentifier;
1313
use graphene_std::text::{TextAlign, TypesettingConfig};
1414
use graphene_std::uuid::NodeId;
15-
use graphene_std::vector::style::{PaintOrder, StrokeAlign};
15+
use graphene_std::vector::style::{PaintOrder, StrokeAlign, StrokeScaling};
1616
use graphene_std::vector::{VectorData, VectorDataTable};
1717
use std::collections::HashMap;
1818

@@ -574,6 +574,21 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
574574
document.network_interface.set_input(&InputConnector::node(*node_id, 9), old_inputs[4].clone(), network_path);
575575
}
576576

577+
// Upgrade Stroke node to add "Scaling" parameter
578+
if reference == "Stroke" && inputs_count == 10 {
579+
let mut node_template = resolve_document_node_type(reference)?.default_node_template();
580+
let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut node_template)?;
581+
582+
// Restore all existing inputs
583+
for (index, input) in old_inputs.into_iter().enumerate() {
584+
document.network_interface.set_input(&InputConnector::node(*node_id, index), input, network_path);
585+
}
586+
587+
// Add the new scaling parameter at index 10
588+
let scaling_input = NodeInput::value(TaggedValue::StrokeScaling(StrokeScaling::ScaleWithShape), false);
589+
document.network_interface.set_input(&InputConnector::node(*node_id, 10), scaling_input, network_path);
590+
}
591+
577592
// Rename the old "Splines from Points" node to "Spline" and upgrade it to the new "Spline" node
578593
if reference == "Splines from Points" {
579594
document.network_interface.set_reference(node_id, network_path, Some("Spline".to_string()));

editor/src/messages/tool/tool_messages/shape_tool.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,6 @@ impl Fsm for ShapeToolFsmState {
642642
tool_data.line_data.editing_layer = Some(layer);
643643
}
644644
}
645-
tool_options.stroke.apply_stroke(tool_options.line_weight, layer, defered_responses);
646-
647645
tool_options.stroke.apply_stroke(tool_options.line_weight, layer, defered_responses);
648646
tool_data.data.layer = Some(layer);
649647

node-graph/gcore/src/vector/style.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,21 @@ impl PaintOrder {
260260
}
261261
}
262262

263+
#[repr(C)]
264+
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
265+
#[widget(Radio)]
266+
pub enum StrokeScaling {
267+
#[default]
268+
ScaleWithShape,
269+
NonScaling,
270+
}
271+
272+
impl StrokeScaling {
273+
pub fn is_non_scaling(self) -> bool {
274+
self == Self::NonScaling
275+
}
276+
}
277+
263278
fn daffine2_identity() -> DAffine2 {
264279
DAffine2::IDENTITY
265280
}

node-graph/gcore/src/vector/vector_nodes.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::vector::algorithms::bezpath_algorithms::{eval_pathseg_euclidean, is_l
1414
use crate::vector::algorithms::merge_by_distance::MergeByDistanceExt;
1515
use crate::vector::misc::{MergeByDistanceAlgorithm, PointSpacingType};
1616
use crate::vector::misc::{handles_to_segment, segment_to_handles};
17-
use crate::vector::style::{PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};
17+
use crate::vector::style::{PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, StrokeScaling};
1818
use crate::vector::{FillId, RegionId};
1919
use crate::{CloneVarArgs, Color, Context, Ctx, ExtractAll, GraphicElement, GraphicGroupTable, OwnedContextImpl};
2020

@@ -191,6 +191,8 @@ async fn stroke<C: Into<Option<Color>> + 'n + Send, V>(
191191
/// The phase offset distance from the starting point of the dash pattern.
192192
#[unit(" px")]
193193
dash_offset: f64,
194+
/// Whether the stroke should scale with shape transformations or maintain a constant visual width.
195+
scaling: StrokeScaling,
194196
) -> Instances<V>
195197
where
196198
Instances<V>: VectorDataTableIterMut + 'n + Send,
@@ -205,7 +207,7 @@ where
205207
join_miter_limit: miter_limit,
206208
align,
207209
transform: DAffine2::IDENTITY,
208-
non_scaling: false,
210+
non_scaling: scaling.is_non_scaling(),
209211
paint_order,
210212
};
211213

node-graph/graph-craft/src/document/value.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ tagged_value! {
242242
StrokeJoin(graphene_core::vector::style::StrokeJoin),
243243
StrokeAlign(graphene_core::vector::style::StrokeAlign),
244244
PaintOrder(graphene_core::vector::style::PaintOrder),
245+
StrokeScaling(graphene_core::vector::style::StrokeScaling),
245246
FillType(graphene_core::vector::style::FillType),
246247
FillChoice(graphene_core::vector::style::FillChoice),
247248
GradientType(graphene_core::vector::style::GradientType),

0 commit comments

Comments
 (0)