diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_properties.rs index 29d8db6c49..ccdcaf6b85 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -27,7 +27,7 @@ use graphene_std::vector::misc::GridType; use graphene_std::vector::misc::{ArcType, MergeByDistanceAlgorithm}; use graphene_std::vector::misc::{CentroidType, PointSpacingType}; use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops}; -use graphene_std::vector::style::{GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin}; +use graphene_std::vector::style::{GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, StrokeScaling}; use graphene_std::{GraphicGroupTable, NodeInputDecleration}; pub(crate) fn string_properties(text: &str) -> Vec { @@ -1807,6 +1807,9 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) - let dash_lengths = array_of_number_widget(ParameterWidgetsInfo::new(node_id, DashLengthsInput::INDEX, true, context), TextInput::default().centered(true)); let number_input = disabled_number_input; let dash_offset = number_widget(ParameterWidgetsInfo::new(node_id, DashOffsetInput::INDEX, true, context), number_input); + let scaling = enum_choice::() + .for_socket(ParameterWidgetsInfo::new(node_id, ScalingInput::INDEX, true, context)) + .property_row(); vec![ color, @@ -1818,6 +1821,7 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) - paint_order, LayoutGroup::Row { widgets: dash_lengths }, LayoutGroup::Row { widgets: dash_offset }, + scaling, ] } diff --git a/editor/src/messages/portfolio/document_migration.rs b/editor/src/messages/portfolio/document_migration.rs index 37777a1b90..ea6dd210c1 100644 --- a/editor/src/messages/portfolio/document_migration.rs +++ b/editor/src/messages/portfolio/document_migration.rs @@ -12,7 +12,7 @@ use graph_craft::document::{DocumentNodeImplementation, NodeInput, value::Tagged use graphene_std::ProtoNodeIdentifier; use graphene_std::text::{TextAlign, TypesettingConfig}; use graphene_std::uuid::NodeId; -use graphene_std::vector::style::{PaintOrder, StrokeAlign}; +use graphene_std::vector::style::{PaintOrder, StrokeAlign, StrokeScaling}; use graphene_std::vector::{VectorData, VectorDataTable}; use std::collections::HashMap; @@ -574,6 +574,21 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], document.network_interface.set_input(&InputConnector::node(*node_id, 9), old_inputs[4].clone(), network_path); } + // Upgrade Stroke node to add "Scaling" parameter + if reference == "Stroke" && inputs_count == 10 { + let mut node_template = resolve_document_node_type(reference)?.default_node_template(); + let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut node_template)?; + + // Restore all existing inputs + for (index, input) in old_inputs.into_iter().enumerate() { + document.network_interface.set_input(&InputConnector::node(*node_id, index), input, network_path); + } + + // Add the new scaling parameter at index 10 + let scaling_input = NodeInput::value(TaggedValue::StrokeScaling(StrokeScaling::ScaleWithShape), false); + document.network_interface.set_input(&InputConnector::node(*node_id, 10), scaling_input, network_path); + } + // Rename the old "Splines from Points" node to "Spline" and upgrade it to the new "Spline" node if reference == "Splines from Points" { document.network_interface.set_reference(node_id, network_path, Some("Spline".to_string())); diff --git a/editor/src/messages/tool/tool_messages/shape_tool.rs b/editor/src/messages/tool/tool_messages/shape_tool.rs index 4c4ab4e4a1..a74014f42d 100644 --- a/editor/src/messages/tool/tool_messages/shape_tool.rs +++ b/editor/src/messages/tool/tool_messages/shape_tool.rs @@ -642,8 +642,6 @@ impl Fsm for ShapeToolFsmState { tool_data.line_data.editing_layer = Some(layer); } } - tool_options.stroke.apply_stroke(tool_options.line_weight, layer, defered_responses); - tool_options.stroke.apply_stroke(tool_options.line_weight, layer, defered_responses); tool_data.data.layer = Some(layer); diff --git a/node-graph/gcore/src/vector/style.rs b/node-graph/gcore/src/vector/style.rs index c1901ce905..e746feed38 100644 --- a/node-graph/gcore/src/vector/style.rs +++ b/node-graph/gcore/src/vector/style.rs @@ -260,6 +260,21 @@ impl PaintOrder { } } +#[repr(C)] +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)] +#[widget(Radio)] +pub enum StrokeScaling { + #[default] + ScaleWithShape, + NonScaling, +} + +impl StrokeScaling { + pub fn is_non_scaling(self) -> bool { + self == Self::NonScaling + } +} + fn daffine2_identity() -> DAffine2 { DAffine2::IDENTITY } diff --git a/node-graph/gcore/src/vector/vector_nodes.rs b/node-graph/gcore/src/vector/vector_nodes.rs index 235046d994..4446fa4918 100644 --- a/node-graph/gcore/src/vector/vector_nodes.rs +++ b/node-graph/gcore/src/vector/vector_nodes.rs @@ -14,7 +14,7 @@ use crate::vector::algorithms::bezpath_algorithms::{eval_pathseg_euclidean, is_l use crate::vector::algorithms::merge_by_distance::MergeByDistanceExt; use crate::vector::misc::{MergeByDistanceAlgorithm, PointSpacingType}; use crate::vector::misc::{handles_to_segment, segment_to_handles}; -use crate::vector::style::{PaintOrder, StrokeAlign, StrokeCap, StrokeJoin}; +use crate::vector::style::{PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, StrokeScaling}; use crate::vector::{FillId, RegionId}; use crate::{CloneVarArgs, Color, Context, Ctx, ExtractAll, GraphicElement, GraphicGroupTable, OwnedContextImpl}; @@ -191,6 +191,8 @@ async fn stroke> + 'n + Send, V>( /// The phase offset distance from the starting point of the dash pattern. #[unit(" px")] dash_offset: f64, + /// Whether the stroke should scale with shape transformations or maintain a constant visual width. + scaling: StrokeScaling, ) -> Instances where Instances: VectorDataTableIterMut + 'n + Send, @@ -205,7 +207,7 @@ where join_miter_limit: miter_limit, align, transform: DAffine2::IDENTITY, - non_scaling: false, + non_scaling: scaling.is_non_scaling(), paint_order, }; diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index d8e49d095c..911d01b6cb 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -242,6 +242,7 @@ tagged_value! { StrokeJoin(graphene_core::vector::style::StrokeJoin), StrokeAlign(graphene_core::vector::style::StrokeAlign), PaintOrder(graphene_core::vector::style::PaintOrder), + StrokeScaling(graphene_core::vector::style::StrokeScaling), FillType(graphene_core::vector::style::FillType), FillChoice(graphene_core::vector::style::FillChoice), GradientType(graphene_core::vector::style::GradientType),