diff --git a/editor/src/messages/color_picker/color_picker_message.rs b/editor/src/messages/color_picker/color_picker_message.rs index 7cd658e820..ab7ab9a296 100644 --- a/editor/src/messages/color_picker/color_picker_message.rs +++ b/editor/src/messages/color_picker/color_picker_message.rs @@ -1,6 +1,6 @@ use crate::messages::layout::utility_types::widgets::input_widgets::{SpectrumInputUpdate, VisualColorPickersInputUpdate}; use crate::messages::prelude::*; -use graphene_std::vector::style::{FillChoice, GradientSpreadMethod}; +use graphene_std::vector::style::{FillChoice, GradientSpread}; /// Identifies which RGB channel a numeric input change targets. #[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] @@ -47,8 +47,8 @@ pub enum ColorPickerMessage { /// `SpectrumInput` change: marker move/insert/delete, midpoint move/reset, or active marker selection changed. GradientUpdate { update: SpectrumInputUpdate }, - /// Spread method choice from the gradient "Ends" selection. - SetSpreadMethod { spread_method: GradientSpreadMethod }, + /// Gradient spread choice from the gradient "Ends" selection. + SetGradientSpread { gradient_spread: GradientSpread }, /// Tell the frontend to start an undo transaction (forwarded as a `FrontendMessage` it bridges out to the picker's parent). StartTransaction, diff --git a/editor/src/messages/color_picker/color_picker_message_handler.rs b/editor/src/messages/color_picker/color_picker_message_handler.rs index 31ed4ef464..a74ec14cd9 100644 --- a/editor/src/messages/color_picker/color_picker_message_handler.rs +++ b/editor/src/messages/color_picker/color_picker_message_handler.rs @@ -5,7 +5,7 @@ use crate::messages::prelude::*; use graphene_std::Color; use graphene_std::color::SRGBA8; use graphene_std::core_types::misc::parse_css_color; -use graphene_std::vector::style::{FillChoice, Gradient, GradientRamp, GradientSpreadMethod, GradientStops}; +use graphene_std::vector::style::{FillChoice, Gradient, GradientRamp, GradientSpread, GradientStops}; /// Bounds for a midpoint position (relative to the interval between two adjacent gradient stops). const MIN_MIDPOINT: f64 = 0.01; @@ -29,7 +29,7 @@ pub struct ColorPickerMessageHandler { // When set, the picker is editing a gradient: the visual pickers and inputs target the active stop's color. gradient: Option, - spread_method: GradientSpreadMethod, + gradient_spread: GradientSpread, active_marker_index: Option, active_marker_is_midpoint: bool, @@ -51,7 +51,7 @@ impl Default for ColorPickerMessageHandler { old_alpha: 1., old_is_none: true, gradient: None, - spread_method: GradientSpreadMethod::default(), + gradient_spread: GradientSpread::default(), active_marker_index: None, active_marker_is_midpoint: false, allow_none: true, @@ -72,13 +72,13 @@ impl MessageHandler for ColorPickerMessageHandler { FillChoice::None => { self.set_new_hsva(0., 0., 0., 1., true); self.gradient = None; - self.spread_method = GradientSpreadMethod::default(); + self.gradient_spread = GradientSpread::default(); self.active_marker_index = None; self.active_marker_is_midpoint = false; } FillChoice::Solid(color) => { self.gradient = None; - self.spread_method = GradientSpreadMethod::default(); + self.gradient_spread = GradientSpread::default(); self.active_marker_index = None; self.active_marker_is_midpoint = false; self.adopt_color(color); @@ -86,7 +86,7 @@ impl MessageHandler for ColorPickerMessageHandler { FillChoice::Gradient(ramp) => { self.active_marker_index = Some(0); self.active_marker_is_midpoint = false; - self.spread_method = ramp.spread_method; + self.gradient_spread = ramp.gradient_spread; let gradient = Gradient::from(ramp); let first_color = gradient.color(0).unwrap_or(Color::BLACK); self.gradient = Some(gradient); @@ -192,13 +192,13 @@ impl MessageHandler for ColorPickerMessageHandler { self.send_layouts(responses); } ColorPickerMessage::GradientUpdate { update } => self.apply_gradient_update(update, responses), - ColorPickerMessage::SetSpreadMethod { spread_method } => { + ColorPickerMessage::SetGradientSpread { gradient_spread } => { let Some(gradient) = &self.gradient else { return }; responses.add(FrontendMessage::ColorPickerStartHistoryTransaction); - self.spread_method = spread_method; + self.gradient_spread = gradient_spread; responses.add(FrontendMessage::ColorPickerColorChanged { value: FillChoice::Gradient(GradientRamp { - spread_method, + gradient_spread, ..GradientRamp::from(gradient) }), }); @@ -289,7 +289,7 @@ impl ColorPickerMessageHandler { gradient.set_color(active_index as usize, color); responses.add(FrontendMessage::ColorPickerColorChanged { value: FillChoice::Gradient(GradientRamp { - spread_method: self.spread_method, + gradient_spread: self.gradient_spread, ..GradientRamp::from(&*gradient) }), }); @@ -419,7 +419,7 @@ impl ColorPickerMessageHandler { responses.add(FrontendMessage::ColorPickerColorChanged { value: FillChoice::Gradient(GradientRamp { - spread_method: self.spread_method, + gradient_spread: self.gradient_spread, ..GradientRamp::from(&gradient) }), }); @@ -621,21 +621,21 @@ impl ColorPickerMessageHandler { .widget_instance(), ])); - // Gradient ends spread method (only present when the picker is in gradient mode) + // Gradient spread (only present when the picker is in gradient mode) if self.gradient.is_some() { - let entries = [GradientSpreadMethod::Pad, GradientSpreadMethod::Reflect, GradientSpreadMethod::Repeat] + let entries = [GradientSpread::Pad, GradientSpread::Reflect, GradientSpread::Repeat] .into_iter() - .map(|spread_method| { - RadioEntryData::new(format!("{spread_method:?}")) - .label(spread_method.to_string()) - .on_update(move |_| ColorPickerMessage::SetSpreadMethod { spread_method }.into()) + .map(|gradient_spread| { + RadioEntryData::new(format!("{gradient_spread:?}")) + .label(gradient_spread.to_string()) + .on_update(move |_| ColorPickerMessage::SetGradientSpread { gradient_spread }.into()) }) .collect(); groups.push(LayoutGroup::row(vec![ - TextLabel::new("Ends").tooltip_label("Spread Method").tooltip_description(ENDS_DESCRIPTION).widget_instance(), + TextLabel::new("Ends").tooltip_label("Gradient Spread").tooltip_description(ENDS_DESCRIPTION).widget_instance(), Separator::new(SeparatorStyle::Related).widget_instance(), - RadioInput::new(entries).selected_index(Some(self.spread_method as u32)).disabled(self.disabled).widget_instance(), + RadioInput::new(entries).selected_index(Some(self.gradient_spread as u32)).disabled(self.disabled).widget_instance(), ])); } diff --git a/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs b/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs index 7133bd5af0..4b091c4c8a 100644 --- a/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs +++ b/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs @@ -24,7 +24,7 @@ use graphene_std::transform::{ReferencePoint, ScaleType}; use graphene_std::vector::misc::{ ArcType, BooleanOperation, BoxCorners, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType, }; -use graphene_std::vector::style::{DashPattern, FillChoice, GradientRamp, GradientSpreadMethod, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin}; +use graphene_std::vector::style::{DashPattern, FillChoice, GradientRamp, GradientSpread, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin}; use graphene_std::vector::{QRCodeErrorCorrectionLevel, Vector}; use graphene_std::{Artboard, Color, Context, Graphic}; use std::any::Any; @@ -213,7 +213,7 @@ fn generate_layout(introspected_data: &Arc, List, List, - List, + List, List, List, List, @@ -266,7 +266,7 @@ fn generate_layout(introspected_data: &Arc, Item, Item, - Item, + Item, Item, Item, Item, @@ -1002,7 +1002,7 @@ macro_rules! impl_table_item_layout_for_choice_enum { impl_table_item_layout_for_choice_enum!( BlendMode, GradientType, - GradientSpreadMethod, + GradientSpread, StrokeJoin, StrokeAlign, StrokeCap, @@ -1214,7 +1214,7 @@ macro_rules! known_item_types { BoxCorners, BlendMode, GradientType, - GradientSpreadMethod, + GradientSpread, StrokeJoin, StrokeAlign, StrokeCap, diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs index 8ef3f3827e..131a8036fe 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs @@ -10,7 +10,7 @@ use graphene_std::raster::BlendMode; use graphene_std::raster_types::Image; use graphene_std::subpath::Subpath; use graphene_std::text::{Font, TypesettingConfig}; -use graphene_std::vector::style::{GradientSpreadMethod, GradientType, Stroke}; +use graphene_std::vector::style::{GradientSpread, GradientType, Stroke}; use graphene_std::vector::{Gradient, PointId, VectorModificationType}; #[impl_message(Message, DocumentMessage, GraphOperation)] @@ -25,7 +25,7 @@ pub enum GraphOperationMessage { #[serde(skip)] gradient: Gradient, gradient_type: GradientType, - spread_method: GradientSpreadMethod, + gradient_spread: GradientSpread, transform: DAffine2, }, BlendingFillSet { @@ -53,9 +53,9 @@ pub enum GraphOperationMessage { layer: LayerNodeIdentifier, gradient_type: GradientType, }, - GradientSpreadMethodSet { + GradientSpreadSet { layer: LayerNodeIdentifier, - spread_method: GradientSpreadMethod, + gradient_spread: GradientSpread, }, OpacitySet { layer: LayerNodeIdentifier, diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs index 2ef9ad5b1f..290ac1f85d 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs @@ -13,7 +13,7 @@ use graph_craft::document::{NodeId, NodeInput}; use graph_craft::list; use graphene_std::renderer::convert_usvg_path::convert_usvg_path; use graphene_std::text::{Font, TypesettingConfig}; -use graphene_std::vector::style::{Gradient, GradientSpreadMethod, GradientStop, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin}; +use graphene_std::vector::style::{Gradient, GradientSpread, GradientStop, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin}; use graphene_std::{Artboard, Color}; #[derive(ExtractField)] @@ -43,11 +43,11 @@ impl MessageHandler> for layer, gradient, gradient_type, - spread_method, + gradient_spread, transform, } => { if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) { - modify_inputs.fill_gradient_set(gradient, gradient_type, spread_method, transform); + modify_inputs.fill_gradient_set(gradient, gradient_type, gradient_spread, transform); } } GraphOperationMessage::BlendingFillSet { layer, fill } => { @@ -80,9 +80,9 @@ impl MessageHandler> for modify_inputs.gradient_type_set(gradient_type); } } - GraphOperationMessage::GradientSpreadMethodSet { layer, spread_method } => { + GraphOperationMessage::GradientSpreadSet { layer, gradient_spread } => { if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) { - modify_inputs.gradient_spread_method_set(spread_method); + modify_inputs.gradient_spread_set(gradient_spread); } } GraphOperationMessage::OpacitySet { layer, opacity } => { @@ -805,11 +805,11 @@ fn apply_usvg_stroke(stroke: &usvg::Stroke, modify_inputs: &mut ModifyInputsCont } } -fn convert_spread_method(spread_method: usvg::SpreadMethod) -> GradientSpreadMethod { +fn convert_gradient_spread(spread_method: usvg::SpreadMethod) -> GradientSpread { match spread_method { - usvg::SpreadMethod::Pad => GradientSpreadMethod::Pad, - usvg::SpreadMethod::Reflect => GradientSpreadMethod::Reflect, - usvg::SpreadMethod::Repeat => GradientSpreadMethod::Repeat, + usvg::SpreadMethod::Pad => GradientSpread::Pad, + usvg::SpreadMethod::Reflect => GradientSpread::Reflect, + usvg::SpreadMethod::Repeat => GradientSpread::Repeat, } } @@ -836,8 +836,8 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, g Gradient::new(stops) } }; - let spread_method = convert_spread_method(linear.spread_method()); - modify_inputs.fill_gradient_set(gradient, gradient_type, spread_method, transform); + let gradient_spread = convert_gradient_spread(linear.spread_method()); + modify_inputs.fill_gradient_set(gradient, gradient_type, gradient_spread, transform); } usvg::Paint::RadialGradient(radial) => { let gradient_transform = usvg_transform(radial.transform()); @@ -860,9 +860,9 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, g Gradient::new(stops) } }; - let spread_method = convert_spread_method(radial.spread_method()); + let gradient_spread = convert_gradient_spread(radial.spread_method()); - modify_inputs.fill_gradient_set(gradient, gradient_type, spread_method, transform); + modify_inputs.fill_gradient_set(gradient, gradient_type, gradient_spread, transform); } usvg::Paint::Pattern(_) => warn!("SVG patterns are not currently supported"), }; diff --git a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs index 609b836a84..4f88862780 100644 --- a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs +++ b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs @@ -16,7 +16,7 @@ use graphene_std::raster::BlendMode; use graphene_std::raster_types::Image; use graphene_std::subpath::Subpath; use graphene_std::text::{Font, TypesettingConfig}; -use graphene_std::vector::style::{GradientSpreadMethod, GradientType, Stroke}; +use graphene_std::vector::style::{GradientSpread, GradientType, Stroke}; use graphene_std::vector::{Gradient, GradientRamp, PointId, Vector, VectorModification, VectorModificationType}; use graphene_std::{Artboard, Color, Graphic}; @@ -403,14 +403,14 @@ impl<'a> ModifyInputsContext<'a> { self.set_input_with_refresh(input_connector, NodeInput::value(fill_value, false), false); } - pub fn fill_gradient_set(&mut self, gradient: Gradient, gradient_type: GradientType, spread_method: GradientSpreadMethod, transform: DAffine2) { + pub fn fill_gradient_set(&mut self, gradient: Gradient, gradient_type: GradientType, gradient_spread: GradientSpread, transform: DAffine2) { let Some(fill_node_id) = self.existing_proto_node_id(graphene_std::vector_nodes::fill::IDENTIFIER, true) else { return; }; let backup_input_connector = InputConnector::node(fill_node_id, graphene_std::vector::fill::BackupGradientInput); let ramp = GradientRamp::from(gradient); - let ramp = GradientRamp { spread_method, ..ramp }; + let ramp = GradientRamp { gradient_spread, ..ramp }; self.set_input_with_refresh(backup_input_connector, NodeInput::value(TaggedValue::GradientRamp(ramp.clone()), false), true); // Skip the rerender on all but the last input so the whole update triggers a single graph run @@ -676,20 +676,20 @@ impl<'a> ModifyInputsContext<'a> { self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::GradientType(gradient_type), false), false); } - /// Write the spread method to the last 'Spread Method' node in the chain, inserting one only when the value differs + /// Write the gradient spread to the last 'Gradient Spread' node in the chain, inserting one only when the value differs /// from the default (`Pad`). - pub fn gradient_spread_method_set(&mut self, spread_method: GradientSpreadMethod) { + pub fn gradient_spread_set(&mut self, gradient_spread: GradientSpread) { let Some(output_layer) = self.get_output_layer() else { return }; let target_input = gradient_chain_target_input(output_layer, self.network_interface); - let identifier = graphene_std::math_nodes::spread_method::IDENTIFIER; - let create_if_nonexistent = spread_method != GradientSpreadMethod::default(); + let identifier = graphene_std::math_nodes::gradient_spread::IDENTIFIER; + let create_if_nonexistent = gradient_spread != GradientSpread::default(); let Some(node_id) = self.existing_proto_node_id_at(&target_input, identifier, create_if_nonexistent) else { return; }; - let input_connector = InputConnector::node(node_id, graphene_std::math_nodes::spread_method::SpreadMethodInput); - self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::GradientSpreadMethod(spread_method), false), false); + let input_connector = InputConnector::node(node_id, graphene_std::math_nodes::gradient_spread::GradientSpreadInput); + self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::GradientSpread(gradient_spread), false), false); } pub fn clip_mode_toggle(&mut self, clip_mode: Option) { 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 884ef60697..08b01973ab 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -33,7 +33,7 @@ use graphene_std::vector::misc::{ ArcType, BoxCorners, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType, }; use graphene_std::vector::style::{ - FillChoice, Gradient, GradientRamp, GradientSpreadMethod, GradientStops, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, build_transform_with_y_preservation, + FillChoice, Gradient, GradientRamp, GradientSpread, GradientStops, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, build_transform_with_y_preservation, }; use graphene_std::vector::{QRCodeErrorCorrectionLevel, VectorModification}; use graphene_std::{NodeParameter, ParameterRef}; @@ -302,7 +302,7 @@ pub(crate) fn property_from_type( // AUTO-GENERATED ENUM TYPES // ========================= Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), @@ -2401,7 +2401,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte Gradient { gradient: Gradient, gradient_type: GradientType, - spread_method: GradientSpreadMethod, + gradient_spread: GradientSpread, transform: DAffine2, /// Whether the transform input holds a plain value (so the "Reverse Direction" button may write to it) rather than a wire. transform_is_value: bool, @@ -2431,7 +2431,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte Some(gradient) => ResolvedFill::Gradient { gradient: gradient.stops, gradient_type: gradient.gradient_type, - spread_method: gradient.spread_method, + gradient_spread: gradient.gradient_spread, transform: gradient.transform, transform_is_value: gradient.transform_is_value, }, @@ -2459,9 +2459,9 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte }; match &fill { - ResolvedFill::Gradient { gradient: stops, spread_method, .. } => { + ResolvedFill::Gradient { gradient: stops, gradient_spread, .. } => { let stops = stops.clone(); - let spread_method = *spread_method; + let gradient_spread = *gradient_spread; let reverse_button = IconButton::new("Reverse", 24) .tooltip_label("Reverse Stops") @@ -2469,7 +2469,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte .on_update(update_value( move |_| { TaggedValue::GradientRamp(GradientRamp { - spread_method, + gradient_spread, ..GradientRamp::from(stops.reversed()) }) }, @@ -2491,8 +2491,8 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte FillChoice::::None } } - ResolvedFill::Gradient { gradient: stops, spread_method, .. } => FillChoice::::Gradient(GradientRamp { - spread_method: *spread_method, + ResolvedFill::Gradient { gradient: stops, gradient_spread, .. } => FillChoice::::Gradient(GradientRamp { + gradient_spread: *gradient_spread, ..GradientRamp::from(stops) }), ResolvedFill::Other => FillChoice::::None, diff --git a/editor/src/messages/portfolio/document/storage_tests/round_trip_tests.rs b/editor/src/messages/portfolio/document/storage_tests/round_trip_tests.rs index 0d1a03b1d8..57029d0746 100644 --- a/editor/src/messages/portfolio/document/storage_tests/round_trip_tests.rs +++ b/editor/src/messages/portfolio/document/storage_tests/round_trip_tests.rs @@ -813,11 +813,11 @@ async fn legacy_four_input_fill_migrates_to_the_split_transform_shape() { } #[tokio::test] -async fn eight_input_fill_migrates_spread_method_into_the_ramp() { +async fn eight_input_fill_migrates_the_spread_input_into_the_ramp() { use graph_craft::document::value::TaggedValue; - use graphene_std::vector::style::GradientSpreadMethod; + use graphene_std::vector::style::GradientSpread; - // A minimal document from the era when spread method was the Fill node's own sixth input, here set to Repeat + // A minimal document from the era when the gradient spread was the Fill node's own sixth input (tagged `GradientSpreadMethod`), here set to Repeat const EIGHT_INPUT_DOCUMENT: &str = r#"{"network_interface":{"network":{"exports":[{"Node":{"node_id":1,"output_index":0,"lambda":false}}],"nodes":[[1,{"inputs":[{"Value":{"tagged_value":{"GraphicGroup":{"instance":[],"transform":[],"alpha_blending":[],"source_node_id":[]}},"exposed":true}},{"Value":{"tagged_value":{"GradientRamp":{"stops":{"color":[{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0},{"red":1.0,"green":1.0,"blue":1.0,"alpha":1.0}]}}},"exposed":false}},{"Value":{"tagged_value":{"Color":{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0}},"exposed":false}},{"Value":{"tagged_value":{"GradientRamp":{"stops":{"color":[{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0},{"red":1.0,"green":1.0,"blue":1.0,"alpha":1.0}]}}},"exposed":false}},{"Value":{"tagged_value":{"GradientType":"Linear"},"exposed":false}},{"Value":{"tagged_value":{"GradientSpreadMethod":"Repeat"},"exposed":false}},{"Value":{"tagged_value":{"Bool":false},"exposed":false}},{"Value":{"tagged_value":{"DAffine2":[1.0,0.0,0.0,1.0,0.0,0.0]},"exposed":false}}],"manual_composition":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::vector::FillNode"}},"visible":true,"skip_deduplication":false}]],"scope_injections":[]},"network_metadata":{"persistent_metadata":{"node_metadata":[[1,{"persistent_metadata":{"reference":"Fill","display_name":"","input_properties":[{"input_data":{"input_name":"Content"},"widget_override":null},{"input_data":{"input_name":"Fill"},"widget_override":null},{"input_data":{"input_name":"Backup Color"},"widget_override":null},{"input_data":{"input_name":"Backup Gradient"},"widget_override":null},{"input_data":{"input_name":"Gradient Type"},"widget_override":null},{"input_data":{"input_name":"Spread Method"},"widget_override":null},{"input_data":{"input_name":"Has Transform"},"widget_override":null},{"input_data":{"input_name":"Transform"},"widget_override":null}],"output_names":[""],"has_primary_output":true,"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,0]}}},"network_metadata":null}}]],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}},"collapsed":[],"name":"eight_input_fill.graphite","commit_hash":"0000000000000000000000000000000000000000","document_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"document_mode":"DesignMode","view_mode":"Normal","overlays_visibility_settings":{"all":true,"artboard_name":true,"compass_rose":true,"quick_measurement":true,"transform_measurement":true,"transform_cage":true,"hover_outline":true,"selection_outline":true,"pivot":true,"path":true,"anchors":true,"handles":true},"rulers_visible":true,"snapping_state":{"snapping_enabled":true,"grid_snapping":false,"artboards":true,"tolerance":8.0,"bounding_box":{"center_point":true,"corner_point":true,"edge_midpoint":true,"align_with_edges":true,"distribute_evenly":true},"path":{"anchor_point":true,"line_midpoint":true,"along_path":true,"normal_to_path":true,"tangent_to_path":true,"path_intersection_point":true,"align_with_anchor_point":true,"perpendicular_from_endpoint":true},"grid":{"origin":[0.0,0.0],"grid_type":{"Rectangular":{"spacing":[1.0,1.0]}},"grid_color":{"red":0.6,"green":0.6,"blue":0.6,"alpha":1.0},"dot_display":false}},"graph_view_overlay_open":false,"graph_fade_artwork_percentage":80.0}"#; // Deserializing alone must succeed, so a failure below is attributable to the migrations @@ -843,17 +843,13 @@ async fn eight_input_fill_migrates_spread_method_into_the_ramp() { let Some(TaggedValue::GradientRamp(ramp)) = paint else { panic!("the fill input should keep its gradient ramp value, but became {paint:?}"); }; - assert_eq!(ramp.spread_method, GradientSpreadMethod::Repeat, "the spread method input's value should fold into the fill ramp"); + assert_eq!(ramp.gradient_spread, GradientSpread::Repeat, "the spread input's value should fold into the fill ramp"); let backup = fill_node.input_value(graphene_std::vector::fill::BackupGradientInput); let Some(TaggedValue::GradientRamp(backup_ramp)) = backup else { panic!("the backup gradient input should keep its gradient ramp value, but became {backup:?}"); }; - assert_eq!( - backup_ramp.spread_method, - GradientSpreadMethod::Repeat, - "the spread method input's value should fold into the backup ramp" - ); + assert_eq!(backup_ramp.gradient_spread, GradientSpread::Repeat, "the spread input's value should fold into the backup ramp"); let has_transform = fill_node.input_value(graphene_std::vector::fill::HasTransformInput); assert!( diff --git a/editor/src/messages/portfolio/document_migration.rs b/editor/src/messages/portfolio/document_migration.rs index de615ae976..e3fc5bef11 100644 --- a/editor/src/messages/portfolio/document_migration.rs +++ b/editor/src/messages/portfolio/document_migration.rs @@ -17,7 +17,7 @@ use graphene_std::text::{TextAlign, TypesettingConfig}; use graphene_std::transform::ScaleType; use graphene_std::uuid::NodeId; use graphene_std::vector::graphic_types; -use graphene_std::vector::style::{GradientRamp, GradientSpreadMethod, PaintOrder, StrokeAlign}; +use graphene_std::vector::style::{GradientRamp, GradientSpread, PaintOrder, StrokeAlign}; use std::collections::HashMap; use std::f64::consts::PI; use std::ops::Range; @@ -167,6 +167,10 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[ "graphic_nodes::graphic::ExtractElementNode", ], }, + NodeReplacement { + node: graphene_std::graphic::read_attribute_gradient_spread::IDENTIFIER, + aliases: &["graphic_nodes::graphic::ReadAttributeSpreadMethodNode"], + }, NodeReplacement { node: graphene_std::graphic::remove_at_index::IDENTIFIER, aliases: &["graphic_nodes::graphic::OmitElementNode"], @@ -262,6 +266,10 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[ node: graphene_std::math_nodes::footprint_value::IDENTIFIER, aliases: &["graphene_math_nodes::FootprintValueNode", "graphene_core::ops::FootprintValueNode"], }, + NodeReplacement { + node: graphene_std::math_nodes::gradient_spread::IDENTIFIER, + aliases: &["math_nodes::SpreadMethodNode"], + }, NodeReplacement { node: graphene_std::math_nodes::gradient_value::IDENTIFIER, aliases: &[ @@ -1406,10 +1414,10 @@ fn migrate_corner_radius_input(input: &NodeInput) -> Option { Some(NodeInput::value(TaggedValue::BoxCorners(values), *exposed)) } -/// Rewrites a gradient ramp value input to carry the given spread method, which used to live in the Fill node's retired `_spread_method` input. -fn fold_spread_method_into_ramp_input(input: &NodeInput, spread_method: GradientSpreadMethod) -> NodeInput { +/// Rewrites a gradient ramp value input to carry the given gradient spread, which used to live in the Fill node's retired `_spread_method` input. +fn fold_gradient_spread_into_ramp_input(input: &NodeInput, gradient_spread: GradientSpread) -> NodeInput { match input.as_value() { - Some(TaggedValue::GradientRamp(ramp)) => NodeInput::value(TaggedValue::GradientRamp(GradientRamp { spread_method, ..ramp.clone() }), input.is_exposed()), + Some(TaggedValue::GradientRamp(ramp)) => NodeInput::value(TaggedValue::GradientRamp(GradientRamp { gradient_spread, ..ramp.clone() }), input.is_exposed()), _ => input.clone(), } } @@ -1635,7 +1643,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], graphic_types::migrations::legacy::LegacyFill::None => TaggedValue::no_paint(), graphic_types::migrations::legacy::LegacyFill::Solid(color) => TaggedValue::Color(*color), graphic_types::migrations::legacy::LegacyFill::Gradient(gradient) => TaggedValue::GradientRamp(GradientRamp { - spread_method: gradient.spread_method, + gradient_spread: gradient.spread_method, ..gradient.stops.clone() }), }; @@ -1682,7 +1690,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], &InputConnector::node_at_index(*node_id, 3), NodeInput::value( TaggedValue::GradientRamp(GradientRamp { - spread_method: g.spread_method, + gradient_spread: g.spread_method, ..g.stops.clone() }), false, @@ -1723,20 +1731,20 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], // Fill split its `Option` placement into a `_has_transform` bool immediately before the `_transform` matrix. The modern // shape is also 7 inputs, so this era is identified by its `_spread_method` input at 5 or its optional transform at 6. let is_pre_transform_split_fill = inputs_count == 7 - && (matches!(node.inputs.get(5).and_then(|input| input.as_value()), Some(TaggedValue::GradientSpreadMethod(_))) + && (matches!(node.inputs.get(5).and_then(|input| input.as_value()), Some(TaggedValue::GradientSpread(_))) || matches!(node.inputs.get(6).and_then(|input| input.as_value()), Some(TaggedValue::LegacyOptionalDAffine2(_)))); if reference == DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER) && is_pre_transform_split_fill { 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)?; - let spread_method = match old_inputs.get(5).and_then(|input| input.as_value()) { - Some(&TaggedValue::GradientSpreadMethod(value)) => value, - _ => GradientSpreadMethod::default(), + let gradient_spread = match old_inputs.get(5).and_then(|input| input.as_value()) { + Some(&TaggedValue::GradientSpread(value)) => value, + _ => GradientSpread::default(), }; for (index, input) in old_inputs.iter().enumerate().take(5) { let input = if index == 1 || index == 3 { - fold_spread_method_into_ramp_input(input, spread_method) + fold_gradient_spread_into_ramp_input(input, gradient_spread) } else { input.clone() }; @@ -1767,19 +1775,19 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], inputs_count = 7; } - // The Fill node's `_spread_method` input moved into the `GradientRamp` value's own `spread_method` field + // The Fill node's `_spread_method` input moved into the `GradientRamp` value's own `gradient_spread` field if reference == DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER) && inputs_count == 8 { 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)?; - let spread_method = match old_inputs.get(5).and_then(|input| input.as_value()) { - Some(&TaggedValue::GradientSpreadMethod(value)) => value, - _ => GradientSpreadMethod::default(), + let gradient_spread = match old_inputs.get(5).and_then(|input| input.as_value()) { + Some(&TaggedValue::GradientSpread(value)) => value, + _ => GradientSpread::default(), }; for (index, input) in old_inputs.iter().enumerate().take(5) { let input = if index == 1 || index == 3 { - fold_spread_method_into_ramp_input(input, spread_method) + fold_gradient_spread_into_ramp_input(input, gradient_spread) } else { input.clone() }; diff --git a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs index 287f45aa2d..e7e4fba40d 100644 --- a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs +++ b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs @@ -14,7 +14,7 @@ use graphene_std::subpath::Subpath; use graphene_std::text::{Font, TypesettingConfig}; use graphene_std::vector::misc::ManipulatorPointId; use graphene_std::vector::style::{FillChoice, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, initial_gradient_transform_for_bounding_box}; -use graphene_std::vector::{Gradient, GradientSpreadMethod, GradientType, PointId, SegmentId, VectorModificationType}; +use graphene_std::vector::{Gradient, GradientSpread, GradientType, PointId, SegmentId, VectorModificationType}; use graphene_std::{NodeParameter, ParameterRef}; use std::collections::VecDeque; @@ -660,7 +660,7 @@ pub fn set_stroke_weight_for_selected_layers(weight: f64, document: &DocumentMes pub struct FillNodeGradient { pub stops: Gradient, pub gradient_type: GradientType, - pub spread_method: GradientSpreadMethod, + pub gradient_spread: GradientSpread, pub transform: DAffine2, /// Whether the transform input holds a plain value (so it may be written to) rather than a wire. pub transform_is_value: bool, @@ -673,7 +673,7 @@ pub fn read_fill_node_gradient(fill_node: &DocumentNode, bounding_box: impl FnOn let TaggedValue::GradientRamp(ramp) = fill_node.input(fill::FillInput)?.as_value()? else { return None; }; - let spread_method = ramp.spread_method; + let gradient_spread = ramp.gradient_spread; let stops = Gradient::from(ramp); let gradient_type = match fill_node.input(fill::GradientTypeInput).and_then(|input| input.as_value()) { Some(&TaggedValue::GradientType(value)) => value, @@ -690,7 +690,7 @@ pub fn read_fill_node_gradient(fill_node: &DocumentNode, bounding_box: impl FnOn Some(FillNodeGradient { stops, gradient_type, - spread_method, + gradient_spread, transform, transform_is_value: transform_input.is_some(), }) @@ -839,7 +839,7 @@ pub fn set_fill_for_selected_layers(fill_choice: FillChoice, document: &Document layer, gradient: Gradient::from(ramp), gradient_type, - spread_method: ramp.spread_method, + gradient_spread: ramp.gradient_spread, transform, }); } diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index d3b91113bc..82eda73c4e 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -16,7 +16,7 @@ use glam::DMat2; use graph_craft::document::value::TaggedValue; use graphene_std::color::SRGBA8; use graphene_std::raster::color::Color; -use graphene_std::vector::style::{FillChoice, Gradient, GradientRamp, GradientSpreadMethod, GradientStop, GradientType, build_transform_with_y_preservation}; +use graphene_std::vector::style::{FillChoice, Gradient, GradientRamp, GradientSpread, GradientStop, GradientType, build_transform_with_y_preservation}; #[derive(Default, ExtractField)] pub struct GradientTool { @@ -28,7 +28,7 @@ pub struct GradientTool { #[derive(Default)] pub struct GradientOptions { gradient_type: GradientType, - spread_method: GradientSpreadMethod, + gradient_spread: GradientSpread, } #[impl_message(Message, ToolMessage, Gradient)] @@ -136,8 +136,8 @@ impl<'a> MessageHandler> for Grad } ToolMessage::Gradient(GradientToolMessage::UpdateRamp { ramp }) => { let ramp = GradientRamp::from(&ramp); - self.options.spread_method = ramp.spread_method; - apply_stops_update(&mut self.data, context, responses, Gradient::from(&ramp), ramp.spread_method); + self.options.gradient_spread = ramp.gradient_spread; + apply_stops_update(&mut self.data, context, responses, Gradient::from(&ramp), ramp.gradient_spread); } ToolMessage::Gradient(GradientToolMessage::CloseStopColorPicker) => { if self.data.color_picker_transaction_open { @@ -171,8 +171,8 @@ impl<'a> MessageHandler> for Grad self.options.gradient_type = appearance.gradient_type; needs_refresh = true; } - if self.options.spread_method != appearance.spread_method { - self.options.spread_method = appearance.spread_method; + if self.options.gradient_spread != appearance.gradient_spread { + self.options.gradient_spread = appearance.gradient_spread; needs_refresh = true; } } @@ -263,7 +263,7 @@ impl LayoutHolder for GradientTool { ]) }); let stops_widget = ColorInput::new(FillChoice::Gradient(GradientRamp { - spread_method: self.options.spread_method, + gradient_spread: self.options.gradient_spread, ..GradientRamp::from(&stops_value) })) .allow_none(false) @@ -363,7 +363,7 @@ fn resolve_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkI gradient.stops, GradientAppearance { gradient_type: gradient.gradient_type, - spread_method: gradient.spread_method, + gradient_spread: gradient.gradient_spread, transform: gradient.transform, }, GradientSource::Direct, @@ -382,22 +382,22 @@ fn resolve_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkI struct GradientAppearance { transform: DAffine2, gradient_type: GradientType, - spread_method: GradientSpreadMethod, + gradient_spread: GradientSpread, } -/// Resolve the gradient transform, type, and spread method by walking the chain feeding the layer. Transform composes all -/// 'Transform' nodes. Type and spread method come from the closest-to-layer node of each kind, or the type default. +/// Resolve the gradient transform, type, and gradient spread by walking the chain feeding the layer. Transform composes all +/// 'Transform' nodes. Type and gradient spread come from the closest-to-layer node of each kind, or the type default. fn read_gradient_chain_state(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> GradientAppearance { let target_input = gradient_chain_target_input(layer, network_interface); let walk_from = network_interface.upstream_output_connector(&target_input, &[]).and_then(|out| out.node_id()).unwrap_or(layer.to_node()); let transform_reference = DefinitionIdentifier::ProtoNode(graphene_std::transform_nodes::transform::IDENTIFIER); let gradient_type_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_type::IDENTIFIER); - let spread_method_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::spread_method::IDENTIFIER); + let gradient_spread_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_spread::IDENTIFIER); let mut transforms_downstream_to_upstream: Vec = Vec::new(); let mut gradient_type: Option = None; - let mut spread_method: Option = None; + let mut gradient_spread: Option = None; for node_id in network_interface .upstream_flow_back_from_nodes(vec![walk_from], &[], FlowType::HorizontalFlow) @@ -416,11 +416,11 @@ fn read_gradient_chain_state(layer: LayerNodeIdentifier, network_interface: &Nod && let Some(TaggedValue::GradientType(value)) = document_node.inputs.get(1).and_then(|input| input.as_value()) { gradient_type = Some(*value); - } else if reference == spread_method_reference - && spread_method.is_none() - && let Some(TaggedValue::GradientSpreadMethod(value)) = document_node.inputs.get(1).and_then(|input| input.as_value()) + } else if reference == gradient_spread_reference + && gradient_spread.is_none() + && let Some(TaggedValue::GradientSpread(value)) = document_node.inputs.get(1).and_then(|input| input.as_value()) { - spread_method = Some(*value); + gradient_spread = Some(*value); } } @@ -430,7 +430,7 @@ fn read_gradient_chain_state(layer: LayerNodeIdentifier, network_interface: &Nod GradientAppearance { transform: composed_transform, gradient_type: gradient_type.unwrap_or_default(), - spread_method: spread_method.unwrap_or_default(), + gradient_spread: gradient_spread.unwrap_or_default(), } } @@ -766,7 +766,7 @@ impl SelectedGradient { layer, gradient: self.gradient.clone(), gradient_type: self.appearance.gradient_type, - spread_method: self.appearance.spread_method, + gradient_spread: self.appearance.gradient_spread, transform: self.appearance.transform, }); } @@ -801,9 +801,9 @@ fn dispatch_gradient_chain_writes(layer: LayerNodeIdentifier, gradient: &Gradien layer, gradient_type: appearance.gradient_type, }); - responses.add(GraphOperationMessage::GradientSpreadMethodSet { + responses.add(GraphOperationMessage::GradientSpreadSet { layer, - spread_method: appearance.spread_method, + gradient_spread: appearance.gradient_spread, }); } @@ -1483,7 +1483,7 @@ impl Fsm for GradientToolFsmState { GradientAppearance { transform: DAffine2::IDENTITY, gradient_type: tool_options.gradient_type, - spread_method: tool_options.spread_method, + gradient_spread: tool_options.gradient_spread, }, GradientSource::Direct, ), @@ -1836,7 +1836,7 @@ fn apply_gradient_update( layer, gradient, gradient_type: appearance.gradient_type, - spread_method: appearance.spread_method, + gradient_spread: appearance.gradient_spread, transform: appearance.transform, }); } @@ -1860,7 +1860,7 @@ fn apply_gradient_update( /// Set new gradient stops on every selected layer's gradient. Unlike `apply_gradient_update`, this doesn't open its own /// transaction so it can be called repeatedly during a color picker drag and have all the changes coalesced into a /// single undo entry by the surrounding 'on_commit' callback. -fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessageContext, responses: &mut VecDeque, new_gradient: Gradient, spread_method: GradientSpreadMethod) { +fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessageContext, responses: &mut VecDeque, new_gradient: Gradient, gradient_spread: GradientSpread) { let selected_layers: Vec<_> = context .document .network_interface @@ -1876,14 +1876,14 @@ fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessa if get_upstream_gradient_value_node_id(layer, &context.document.network_interface).is_some() { responses.add(GraphOperationMessage::GradientStopsSet { layer, stops: new_gradient.clone() }); - responses.add(GraphOperationMessage::GradientSpreadMethodSet { layer, spread_method }); + responses.add(GraphOperationMessage::GradientSpreadSet { layer, gradient_spread }); updated_any_layer = true; } else if let Some((_gradient, appearance, _source)) = resolve_gradient(layer, &context.document.network_interface) { responses.add(GraphOperationMessage::FillGradientSet { layer, gradient: new_gradient.clone(), gradient_type: appearance.gradient_type, - spread_method, + gradient_spread, transform: appearance.transform, }); updated_any_layer = true; @@ -1892,7 +1892,7 @@ fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessa if let Some(selected_gradient) = &mut data.selected_gradient { selected_gradient.gradient = new_gradient.clone(); - selected_gradient.appearance.spread_method = spread_method; + selected_gradient.appearance.gradient_spread = gradient_spread; } // When no selected layer had a gradient to update, the user is editing the tool's default gradient instead. @@ -1989,14 +1989,14 @@ mod test_gradient { use graph_craft::document::NodeInput; use graph_craft::document::value::TaggedValue; use graphene_std::color::SRGBA8; - use graphene_std::vector::style::{GradientSpreadMethod, build_transform_with_y_preservation}; + use graphene_std::vector::style::{GradientSpread, build_transform_with_y_preservation}; use graphene_std::vector::{Gradient, GradientRamp, GradientStop, fill}; use super::gradient_space_transform; struct ResolvedGradient { stops: Gradient, - spread_method: GradientSpreadMethod, + gradient_spread: GradientSpread, transform: DAffine2, } @@ -2004,7 +2004,7 @@ mod test_gradient { fn new(stops: Gradient, appearance: super::GradientAppearance) -> Self { Self { stops, - spread_method: appearance.spread_method, + gradient_spread: appearance.gradient_spread, transform: appearance.transform, } } @@ -2032,8 +2032,8 @@ mod test_gradient { let fill_node_id = get_fill_node_id_with_direct_fill_input(layer, &document.network_interface)?; let fill_node = document.network_interface.document_network().nodes.get(&fill_node_id)?; - let (stops, spread_method) = match fill_node.input(fill::FillInput)?.as_value()? { - TaggedValue::GradientRamp(ramp) => (Gradient::from(ramp), ramp.spread_method), + let (stops, gradient_spread) = match fill_node.input(fill::FillInput)?.as_value()? { + TaggedValue::GradientRamp(ramp) => (Gradient::from(ramp), ramp.gradient_spread), _ => return None, }; @@ -2045,7 +2045,7 @@ mod test_gradient { let gradient = ResolvedGradient { stops, - spread_method, + gradient_spread, transform: local_transform, }; @@ -2575,77 +2575,77 @@ mod test_gradient { assert_eq!(editor.active_document().metadata().all_layers().count(), 0, "Expected the layer to be deleted after drawing a gradient"); } - /// Build the JS-boundary ramp the stops swatch's picker would send when choosing a new spread method. - fn ramp_with_spread(stops: &Gradient, spread_method: GradientSpreadMethod) -> GradientRamp { + /// Build the JS-boundary ramp the stops swatch's picker would send when choosing a new gradient spread. + fn ramp_with_spread(stops: &Gradient, gradient_spread: GradientSpread) -> GradientRamp { GradientRamp::::from(&GradientRamp { - spread_method, + gradient_spread, ..GradientRamp::from(stops) }) } #[tokio::test] - async fn change_spread_method() { + async fn change_gradient_spread() { let mut editor = EditorTestUtils::create(); editor.new_document().await; editor.drag_tool(ToolType::Rectangle, 0., 0., 100., 100., ModifierKeys::empty()).await; editor.drag_tool(ToolType::Gradient, 10., 10., 90., 90., ModifierKeys::empty()).await; - // Verify default spread method is Pad + // Verify default gradient spread is Pad let (gradient, _) = get_gradient_from_fill(&mut editor).await; - assert_eq!(gradient.spread_method, GradientSpreadMethod::Pad); + assert_eq!(gradient.gradient_spread, GradientSpread::Pad); - // Update spread method to Repeat + // Update the gradient spread to Repeat editor .handle_message(GradientToolMessage::UpdateRamp { - ramp: ramp_with_spread(&gradient.stops, GradientSpreadMethod::Repeat), + ramp: ramp_with_spread(&gradient.stops, GradientSpread::Repeat), }) .await; let (gradient, _) = get_gradient_from_fill(&mut editor).await; - assert_eq!(gradient.spread_method, GradientSpreadMethod::Repeat); + assert_eq!(gradient.gradient_spread, GradientSpread::Repeat); - // Update spread method to Reflect + // Update the gradient spread to Reflect editor .handle_message(GradientToolMessage::UpdateRamp { - ramp: ramp_with_spread(&gradient.stops, GradientSpreadMethod::Reflect), + ramp: ramp_with_spread(&gradient.stops, GradientSpread::Reflect), }) .await; let (gradient, _) = get_gradient_from_fill(&mut editor).await; - assert_eq!(gradient.spread_method, GradientSpreadMethod::Reflect); + assert_eq!(gradient.gradient_spread, GradientSpread::Reflect); } #[tokio::test] - async fn change_spread_method_chain() { + async fn change_gradient_spread_chain() { let mut editor = EditorTestUtils::create(); editor.new_document().await; let layer = create_fill_gradient_chain_layer(&mut editor).await; editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![layer.to_node()] }).await; editor.select_tool(ToolType::Gradient).await; - // Verify default spread method is Pad + // Verify default gradient spread is Pad let (gradient, _) = get_gradient_from_chain(&mut editor).await; - assert_eq!(gradient.spread_method, GradientSpreadMethod::Pad); + assert_eq!(gradient.gradient_spread, GradientSpread::Pad); - // Update spread method to Repeat + // Update the gradient spread to Repeat editor .handle_message(GradientToolMessage::UpdateRamp { - ramp: ramp_with_spread(&gradient.stops, GradientSpreadMethod::Repeat), + ramp: ramp_with_spread(&gradient.stops, GradientSpread::Repeat), }) .await; let (gradient, _) = get_gradient_from_chain(&mut editor).await; - assert_eq!(gradient.spread_method, GradientSpreadMethod::Repeat); + assert_eq!(gradient.gradient_spread, GradientSpread::Repeat); - // Update spread method to Reflect + // Update the gradient spread to Reflect editor .handle_message(GradientToolMessage::UpdateRamp { - ramp: ramp_with_spread(&gradient.stops, GradientSpreadMethod::Reflect), + ramp: ramp_with_spread(&gradient.stops, GradientSpread::Reflect), }) .await; let (gradient, _) = get_gradient_from_chain(&mut editor).await; - assert_eq!(gradient.spread_method, GradientSpreadMethod::Reflect); + assert_eq!(gradient.gradient_spread, GradientSpread::Reflect); } #[tokio::test] @@ -2797,7 +2797,7 @@ mod test_gradient { // graph space rather than stranded at the origin. #[tokio::test] async fn gradient_chain_node_on_fill_secondary_input_takes_feeder_slot() { - use graphene_std::vector::style::GradientSpreadMethod; + use graphene_std::vector::style::GradientSpread; let mut editor = EditorTestUtils::create(); editor.new_document().await; @@ -2855,17 +2855,17 @@ mod test_gradient { .await; let feeder_position = editor.active_document_mut().network_interface.position(&gradient_value_id, &[]).expect("Gradient Value position"); - // Set the spread method through the tool, which splices a 'Spread Method' node onto the Fill's fill input wire. + // Set the gradient spread through the tool, which splices a 'Gradient Spread' node onto the Fill's fill input wire. editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![layer.to_node()] }).await; editor.select_tool(ToolType::Gradient).await; let stops = get_gradient_stops(layer, &editor.active_document().network_interface).expect("the chain layer should resolve its gradient stops"); editor .handle_message(GradientToolMessage::UpdateRamp { - ramp: ramp_with_spread(&stops, GradientSpreadMethod::Reflect), + ramp: ramp_with_spread(&stops, GradientSpread::Reflect), }) .await; - let spread_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::spread_method::IDENTIFIER); + let spread_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_spread::IDENTIFIER); let spread_node_id = { let network_interface = &editor.active_document().network_interface; network_interface @@ -2874,10 +2874,10 @@ mod test_gradient { .keys() .copied() .find(|node_id| network_interface.reference(node_id, &[]).as_ref() == Some(&spread_reference)) - .expect("Spread Method node should have been inserted") + .expect("Gradient Spread node should have been inserted") }; - let spread_position = editor.active_document_mut().network_interface.position(&spread_node_id, &[]).expect("Spread Method position"); + let spread_position = editor.active_document_mut().network_interface.position(&spread_node_id, &[]).expect("Gradient Spread position"); let feeder_position_after = editor.active_document_mut().network_interface.position(&gradient_value_id, &[]).expect("Gradient Value position after"); assert_eq!(spread_position, feeder_position, "the inserted node should occupy the feeder's former slot, not the graph origin"); diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index acdf5100d7..c62baf6c42 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -552,7 +552,8 @@ tagged_value! { StrokeAlign(vector::style::StrokeAlign), PaintOrder(vector::style::PaintOrder), GradientType(vector::style::GradientType), - GradientSpreadMethod(vector::style::GradientSpreadMethod), + #[serde(alias = "GradientSpreadMethod")] // TODO: Eventually remove this document upgrade code + GradientSpread(vector::style::GradientSpread), ReferencePoint(vector::ReferencePoint), CentroidType(vector::misc::CentroidType), BooleanOperation(vector::misc::BooleanOperation), @@ -1021,7 +1022,7 @@ mod paint_default_parsing { #[cfg(test)] mod gradient_shape_migration { - use graphic_types::vector_types::GradientSpreadMethod; + use graphic_types::vector_types::GradientSpread; use super::*; @@ -1042,7 +1043,7 @@ mod gradient_shape_migration { let mut gradient = Gradient::from(vec![Color::BLACK, Color::WHITE]); gradient.set_positions(&[0.2, 0.9]); let value = TaggedValue::GradientRamp(GradientRamp { - spread_method: GradientSpreadMethod::Reflect, + gradient_spread: GradientSpread::Reflect, ..GradientRamp::from(gradient) }); diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index a7e38e3d9e..042094c377 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -24,7 +24,7 @@ use graphene_std::transform::{Footprint, ReferencePoint, ScaleType}; use graphene_std::vector::misc::{ ArcType, BooleanOperation, BoxCorners, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType, }; -use graphene_std::vector::style::{DashPattern, GradientSpreadMethod, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin}; +use graphene_std::vector::style::{DashPattern, GradientSpread, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin}; use graphene_std::vector::{QRCodeErrorCorrectionLevel, Vector, VectorModification}; use graphene_std::{Artboard, Context, Graphic, NodeIO, NodeIOTypes, ProtoNodeIdentifier, concrete, fn_type_fut, future}; use node_registry_macros::async_node; @@ -75,7 +75,7 @@ fn node_registry() -> HashMap, input: Context, fn_params: [Context => List]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => List]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => List]), - async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => List]), + async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => List]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Item]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => ListDyn]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Item]), @@ -109,7 +109,7 @@ fn node_registry() -> HashMap, input: Context, fn_params: [Context => List]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => List]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => List]), - async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => List]), + async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => List]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Item]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Item]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Item]), @@ -332,7 +332,7 @@ fn node_registry() -> HashMap HashMap)); @@ -536,7 +536,7 @@ fn node_registry() -> HashMap), attribute_value_node!(Item), attribute_value_node!(Item), - attribute_value_node!(Item), + attribute_value_node!(Item), attribute_value_node!(Item), attribute_value_node!(List), attribute_value_node!(List), diff --git a/node-graph/libraries/core-types/src/lib.rs b/node-graph/libraries/core-types/src/lib.rs index a596f4736d..b36488034a 100644 --- a/node-graph/libraries/core-types/src/lib.rs +++ b/node-graph/libraries/core-types/src/lib.rs @@ -25,8 +25,8 @@ pub use graphene_hash; pub use graphene_hash::CacheHash; pub use list::{ ATTR_BACKGROUND, ATTR_BLEND_MODE, ATTR_CLIP, ATTR_CLIPPING_MASK, ATTR_DIMENSIONS, ATTR_EDITOR_CLICK_TARGET, ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_EDITOR_TEXT_FRAME, ATTR_END, - ATTR_FONT, ATTR_FONT_SIZE, ATTR_GRADIENT_TYPE, ATTR_LETTER_SPACING, ATTR_LETTER_TILT, ATTR_LINE_HEIGHT, ATTR_LOCATION, ATTR_MAX_HEIGHT, ATTR_MAX_WIDTH, ATTR_NAME, ATTR_OPACITY, ATTR_OPACITY_FILL, - ATTR_SPREAD_METHOD, ATTR_START, ATTR_TEXT_ALIGN, ATTR_TRANSFORM, ATTR_TYPE, + ATTR_FONT, ATTR_FONT_SIZE, ATTR_GRADIENT_SPREAD, ATTR_GRADIENT_TYPE, ATTR_LETTER_SPACING, ATTR_LETTER_TILT, ATTR_LINE_HEIGHT, ATTR_LOCATION, ATTR_MAX_HEIGHT, ATTR_MAX_WIDTH, ATTR_NAME, + ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_START, ATTR_TEXT_ALIGN, ATTR_TRANSFORM, ATTR_TYPE, }; pub use memo::MemoHash; pub use no_std_types::AsU32; diff --git a/node-graph/libraries/core-types/src/list.rs b/node-graph/libraries/core-types/src/list.rs index 741a8dcd94..298a4decc4 100644 --- a/node-graph/libraries/core-types/src/list.rs +++ b/node-graph/libraries/core-types/src/list.rs @@ -55,9 +55,9 @@ pub const ATTR_DIMENSIONS: &str = "dimensions"; pub const ATTR_BACKGROUND: &str = "background"; /// `bool` for whether an artboard clips content to its bounds. pub const ATTR_CLIP: &str = "clip"; -// TODO: Consider adding "spread_method_left" and "spread_method_right" override attributes to allow setting different spread methods on each side of a gradient -/// Gradient's `GradientSpreadMethod` (`Pad`, `Reflect`, or `Repeat`). -pub const ATTR_SPREAD_METHOD: &str = "spread_method"; +// TODO: Consider adding "gradient_spread_left" and "gradient_spread_right" override attributes to allow setting different gradient spreads on each side of a gradient +/// Gradient's `GradientSpread` (`Pad`, `Reflect`, or `Repeat`). +pub const ATTR_GRADIENT_SPREAD: &str = "gradient_spread"; /// Gradient's `GradientType` (`Linear` or `Radial`). pub const ATTR_GRADIENT_TYPE: &str = "gradient_type"; /// Gradient stop's `f64` position from 0 to 1 along the gradient, on the `List` inside a `Gradient`. @@ -1229,7 +1229,7 @@ impl CacheHash for List { self.element.cache_hash(state); // Hash every attribute attribute (key + values) rather than just the well-known ones, so changes to user-defined keys - // (e.g., gradient_type, spread_method) invalidate downstream graph caches as expected + // (e.g., gradient_type, gradient_spread) invalidate downstream graph caches as expected for (key, attribute) in &self.attributes.attributes { std::hash::Hash::hash(key.as_str(), state); attribute.cache_hash_dyn(state); diff --git a/node-graph/libraries/graphic-types/src/graphic.rs b/node-graph/libraries/graphic-types/src/graphic.rs index e5197f8e55..13f1fe7740 100644 --- a/node-graph/libraries/graphic-types/src/graphic.rs +++ b/node-graph/libraries/graphic-types/src/graphic.rs @@ -666,8 +666,8 @@ mod tests { #[cfg(test)] mod graphic_is_opaque_tests { - use core_types::ATTR_SPREAD_METHOD; - use vector_types::{GradientSpreadMethod, GradientStop}; + use core_types::ATTR_GRADIENT_SPREAD; + use vector_types::{GradientSpread, GradientStop}; use super::*; @@ -678,7 +678,7 @@ mod graphic_is_opaque_tests { fn gradient_graphic(gradient: Gradient) -> Graphic { let mut gradient_list = List::new_from_element(gradient); - gradient_list.set_attribute(ATTR_SPREAD_METHOD, 0, GradientSpreadMethod::Pad); + gradient_list.set_attribute(ATTR_GRADIENT_SPREAD, 0, GradientSpread::Pad); Graphic::Gradient(gradient_list) } diff --git a/node-graph/libraries/graphic-types/src/lib.rs b/node-graph/libraries/graphic-types/src/lib.rs index 2613b89d4f..32cd9d2614 100644 --- a/node-graph/libraries/graphic-types/src/lib.rs +++ b/node-graph/libraries/graphic-types/src/lib.rs @@ -33,7 +33,7 @@ pub mod migrations { pub start: DVec2, pub end: DVec2, #[serde(default)] - pub spread_method: vector::style::GradientSpreadMethod, + pub spread_method: vector::style::GradientSpread, #[serde(default)] pub absolute: bool, #[serde(default)] diff --git a/node-graph/libraries/rendering/src/render_ext.rs b/node-graph/libraries/rendering/src/render_ext.rs index 3d60aae7af..5de1cabee4 100644 --- a/node-graph/libraries/rendering/src/render_ext.rs +++ b/node-graph/libraries/rendering/src/render_ext.rs @@ -3,14 +3,14 @@ use crate::{Render, RenderSvgSegmentList, SvgRender}; use core_types::color::SRGBA8; use core_types::list::List; use core_types::uuid::generate_uuid; -use core_types::{ATTR_GRADIENT_TYPE, ATTR_SPREAD_METHOD, ATTR_TRANSFORM, Color}; +use core_types::{ATTR_GRADIENT_SPREAD, ATTR_GRADIENT_TYPE, ATTR_TRANSFORM, Color}; use glam::{DAffine2, DVec2}; use graphic_types::Graphic; use graphic_types::vector_types::gradient::GradientType; use graphic_types::vector_types::vector::style::{PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin}; use std::fmt::Write; use vector_types::Gradient; -use vector_types::gradient::GradientSpreadMethod; +use vector_types::gradient::GradientSpread; #[derive(Copy, Clone, PartialEq)] pub enum PaintTarget { @@ -95,7 +95,7 @@ impl RenderExt for List { let Some(stops) = self.element(0) else { return 0 }; let gradient_type: GradientType = self.attribute_cloned_or_default(ATTR_GRADIENT_TYPE, 0); let local_gradient_transform: DAffine2 = self.attribute_cloned_or_default(ATTR_TRANSFORM, 0); - let spread_method: GradientSpreadMethod = self.attribute_cloned_or_default(ATTR_SPREAD_METHOD, 0); + let gradient_spread: GradientSpread = self.attribute_cloned_or_default(ATTR_GRADIENT_SPREAD, 0); for (position, color, original_midpoint) in stops.interpolated_samples() { stop.push_str(" { format!(r#" gradientTransform="{gradient_transform}""#) }; - let spread_method = if spread_method == GradientSpreadMethod::Pad { + let gradient_spread = if gradient_spread == GradientSpread::Pad { String::new() } else { - format!(r#" spreadMethod="{}""#, spread_method.svg_name()) + format!(r#" spreadMethod="{}""#, gradient_spread.svg_name()) }; let gradient_id = generate_uuid(); @@ -146,14 +146,14 @@ impl RenderExt for List { GradientType::Linear => { let _ = write!( svg_defs, - r#"{}"#, + r#"{}"#, gradient_id, stop ); } GradientType::Radial => { let _ = write!( svg_defs, - r#"{}"#, + r#"{}"#, gradient_id, stop ); } diff --git a/node-graph/libraries/rendering/src/renderer.rs b/node-graph/libraries/rendering/src/renderer.rs index 8decdc80ad..9dc06ea02c 100644 --- a/node-graph/libraries/rendering/src/renderer.rs +++ b/node-graph/libraries/rendering/src/renderer.rs @@ -14,7 +14,7 @@ use core_types::transform::Footprint; use core_types::uuid::{NodeId, generate_uuid}; use core_types::{ ATTR_BACKGROUND, ATTR_BLEND_MODE, ATTR_CLIP, ATTR_CLIPPING_MASK, ATTR_DIMENSIONS, ATTR_EDITOR_CLICK_TARGET, ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_EDITOR_TEXT_FRAME, ATTR_FONT, - ATTR_FONT_SIZE, ATTR_GRADIENT_TYPE, ATTR_LETTER_SPACING, ATTR_LETTER_TILT, ATTR_LINE_HEIGHT, ATTR_LOCATION, ATTR_MAX_HEIGHT, ATTR_MAX_WIDTH, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_SPREAD_METHOD, + ATTR_FONT_SIZE, ATTR_GRADIENT_SPREAD, ATTR_GRADIENT_TYPE, ATTR_LETTER_SPACING, ATTR_LETTER_TILT, ATTR_LINE_HEIGHT, ATTR_LOCATION, ATTR_MAX_HEIGHT, ATTR_MAX_WIDTH, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TEXT_ALIGN, ATTR_TRANSFORM, }; use dyn_any::DynAny; @@ -39,7 +39,7 @@ use std::fmt::Write; use std::hash::Hash; use std::ops::Deref; use std::sync::{Arc, LazyLock}; -use vector_types::gradient::GradientSpreadMethod; +use vector_types::gradient::GradientSpread; use vello::*; #[derive(Clone, Copy, Debug, PartialEq)] @@ -424,7 +424,7 @@ fn create_peniko_gradient_brush(gradient_list: &List, multiplied_trans let gradient_type: GradientType = gradient_list.attribute_cloned_or_default(ATTR_GRADIENT_TYPE, 0); let gradient_transform: DAffine2 = gradient_list.attribute_cloned_or_default(ATTR_TRANSFORM, 0); - let spread_method: GradientSpreadMethod = gradient_list.attribute_cloned_or_default(ATTR_SPREAD_METHOD, 0); + let gradient_spread: GradientSpread = gradient_list.attribute_cloned_or_default(ATTR_GRADIENT_SPREAD, 0); let peniko_stops = peniko_color_stops(stops); @@ -446,10 +446,10 @@ fn create_peniko_gradient_brush(gradient_list: &List, multiplied_trans } .into(), }, - extend: match spread_method { - GradientSpreadMethod::Pad => peniko::Extend::Pad, - GradientSpreadMethod::Reflect => peniko::Extend::Reflect, - GradientSpreadMethod::Repeat => peniko::Extend::Repeat, + extend: match gradient_spread { + GradientSpread::Pad => peniko::Extend::Pad, + GradientSpread::Reflect => peniko::Extend::Reflect, + GradientSpread::Repeat => peniko::Extend::Repeat, }, stops: peniko_stops, interpolation_alpha_space: peniko::InterpolationAlphaSpace::Premultiplied, @@ -2094,7 +2094,7 @@ impl Render for List { let blend_mode: BlendMode = self.attribute_cloned_or_default(ATTR_BLEND_MODE, index); let opacity_attr: f64 = self.attribute_cloned_or(ATTR_OPACITY, index, 1.); let opacity_fill_attr: f64 = self.attribute_cloned_or(ATTR_OPACITY_FILL, index, 1.); - let spread_method: GradientSpreadMethod = self.attribute_cloned_or_default(ATTR_SPREAD_METHOD, index); + let gradient_spread: GradientSpread = self.attribute_cloned_or_default(ATTR_GRADIENT_SPREAD, index); let gradient_type: GradientType = self.attribute_cloned_or_default(ATTR_GRADIENT_TYPE, index); let tag = if thumbnail_rect.is_some() { "rect" } else { "polyline" }; render.leaf_tag(tag, |attributes| { @@ -2133,10 +2133,10 @@ impl Render for List { }; let gradient_id = generate_uuid(); - let spread_method_attribute = if spread_method == GradientSpreadMethod::Pad { + let gradient_spread_attribute = if gradient_spread == GradientSpread::Pad { String::new() } else { - format!(r#" spreadMethod="{}""#, spread_method.svg_name()) + format!(r#" spreadMethod="{}""#, gradient_spread.svg_name()) }; // The unit gradient line is the +X unit vector in local space, before the item's transform is applied @@ -2144,13 +2144,13 @@ impl Render for List { GradientType::Linear => { let _ = write!( &mut attributes.0.svg_defs, - r#"{stop_string}"# + r#"{stop_string}"# ); } GradientType::Radial => { let _ = write!( &mut attributes.0.svg_defs, - r#"{stop_string}"# + r#"{stop_string}"# ); } } @@ -2176,10 +2176,10 @@ impl Render for List { return; } - for (((index, gradient), spread_method), gradient_type) in self + for (((index, gradient), gradient_spread), gradient_type) in self .iter_element_values() .enumerate() - .zip(self.iter_attribute_values_or_default::(ATTR_SPREAD_METHOD)) + .zip(self.iter_attribute_values_or_default::(ATTR_GRADIENT_SPREAD)) .zip(self.iter_attribute_values_or_default::(ATTR_GRADIENT_TYPE)) { let transform: DAffine2 = self.attribute_cloned_or_default(ATTR_TRANSFORM, index); @@ -2193,10 +2193,10 @@ impl Render for List { let stops = peniko_color_stops(gradient); - let extend = match spread_method { - GradientSpreadMethod::Pad => peniko::Extend::Pad, - GradientSpreadMethod::Reflect => peniko::Extend::Reflect, - GradientSpreadMethod::Repeat => peniko::Extend::Repeat, + let extend = match gradient_spread { + GradientSpread::Pad => peniko::Extend::Pad, + GradientSpread::Reflect => peniko::Extend::Reflect, + GradientSpread::Repeat => peniko::Extend::Repeat, }; // The unit gradient line is the +X unit vector in local space, before the item's transform is applied. diff --git a/node-graph/libraries/vector-types/src/gradient.rs b/node-graph/libraries/vector-types/src/gradient.rs index 2423005766..a6156010ae 100644 --- a/node-graph/libraries/vector-types/src/gradient.rs +++ b/node-graph/libraries/vector-types/src/gradient.rs @@ -1,6 +1,6 @@ use core_types::Color; use core_types::color::SRGBA8; -use core_types::list::{ATTR_MIDPOINT, ATTR_POSITION, ATTR_SPREAD_METHOD, Item, List}; +use core_types::list::{ATTR_GRADIENT_SPREAD, ATTR_MIDPOINT, ATTR_POSITION, Item, List}; use core_types::render_complexity::RenderComplexity; use dyn_any::DynAny; use glam::{DAffine2, DVec2}; @@ -102,9 +102,9 @@ impl GradientStops { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GradientRamp { pub stops: GradientStops, - #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "GradientSpreadMethod::is_default"))] + #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "GradientSpread::is_default"))] #[cfg_attr(feature = "wasm", tsify(optional))] - pub spread_method: GradientSpreadMethod, + pub gradient_spread: GradientSpread, } unsafe impl dyn_any::StaticType for GradientRamp { @@ -115,7 +115,7 @@ impl From> for GradientRamp { fn from(stops: GradientStops) -> Self { Self { stops, - spread_method: Default::default(), + gradient_spread: Default::default(), } } } @@ -124,7 +124,7 @@ impl From<&Gradient> for GradientRamp { fn from(gradient: &Gradient) -> Self { Self { stops: gradient.into(), - spread_method: Default::default(), + gradient_spread: Default::default(), } } } @@ -152,8 +152,8 @@ impl From<&GradientRamp> for Gradient { impl From for Item { fn from(ramp: GradientRamp) -> Self { let mut item = Item::new_from_element(Gradient::from(ramp.stops)); - if !ramp.spread_method.is_default() { - item.set_attribute(ATTR_SPREAD_METHOD, ramp.spread_method); + if !ramp.gradient_spread.is_default() { + item.set_attribute(ATTR_GRADIENT_SPREAD, ramp.gradient_spread); } item } @@ -163,7 +163,7 @@ impl From<&Item> for GradientRamp { fn from(item: &Item) -> Self { Self { stops: item.element().into(), - spread_method: item.attribute_cloned_or_default(ATTR_SPREAD_METHOD), + gradient_spread: item.attribute_cloned_or_default(ATTR_GRADIENT_SPREAD), } } } @@ -189,7 +189,7 @@ impl From<&GradientRamp> for GradientRamp { fn from(ramp: &GradientRamp) -> Self { Self { stops: ramp.into(), - spread_method: ramp.spread_method, + gradient_spread: ramp.gradient_spread, } } } @@ -198,7 +198,7 @@ impl From<&Gradient> for GradientRamp { fn from(gradient: &Gradient) -> Self { Self { stops: gradient.into(), - spread_method: Default::default(), + gradient_spread: Default::default(), } } } @@ -206,7 +206,7 @@ impl From<&Gradient> for GradientRamp { impl From<&GradientRamp> for GradientRamp { fn from(ramp: &GradientRamp) -> Self { Self { - spread_method: ramp.spread_method, + gradient_spread: ramp.gradient_spread, ..Self::from(&ramp.stops) } } @@ -600,12 +600,12 @@ impl Gradient { stops } - /// Samples the gradient's color at `t`. Given a `t` outside the 0 to 1 range, the `spread_method` determines how the gradient extends. - pub fn evaluate(&self, t: f64, spread_method: GradientSpreadMethod) -> Color { - let t = match spread_method { - GradientSpreadMethod::Pad => t.clamp(0., 1.), - GradientSpreadMethod::Repeat => t.rem_euclid(1.), - GradientSpreadMethod::Reflect => { + /// Samples the gradient's color at `t`. Given a `t` outside the 0 to 1 range, the `gradient_spread` determines how the gradient extends. + pub fn evaluate(&self, t: f64, gradient_spread: GradientSpread) -> Color { + let t = match gradient_spread { + GradientSpread::Pad => t.clamp(0., 1.), + GradientSpread::Repeat => t.rem_euclid(1.), + GradientSpread::Reflect => { let cycle = t.rem_euclid(2.); if cycle > 1. { 2. - cycle } else { cycle } } @@ -784,7 +784,7 @@ impl Gradient { #[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, graphene_hash::CacheHash, DynAny, node_macro::ChoiceType)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[widget(Radio)] -pub enum GradientSpreadMethod { +pub enum GradientSpread { /// Extends the end colors outward. #[default] Pad, @@ -795,12 +795,12 @@ pub enum GradientSpreadMethod { // TODO: Add a "Clear" variant that returns transparent black outside the gradient's range } -impl GradientSpreadMethod { +impl GradientSpread { pub fn svg_name(&self) -> &'static str { match self { - GradientSpreadMethod::Pad => "pad", - GradientSpreadMethod::Reflect => "reflect", - GradientSpreadMethod::Repeat => "repeat", + GradientSpread::Pad => "pad", + GradientSpread::Reflect => "reflect", + GradientSpread::Repeat => "repeat", } } @@ -905,39 +905,39 @@ mod tests { } #[test] - fn spread_method_serializes_only_when_not_default() { + fn gradient_spread_serializes_only_when_not_default() { let default_spread = GradientRamp::from(Gradient::from(vec![Color::BLACK, Color::WHITE])); let json = serde_json::to_string(&default_spread).unwrap(); - assert!(!json.contains("spread_method"), "the default Pad spread method must not serialize: {json}"); + assert!(!json.contains("gradient_spread"), "the default Pad gradient spread must not serialize: {json}"); assert_eq!(serde_json::from_str::(&json).unwrap(), default_spread); let repeating = GradientRamp { - spread_method: GradientSpreadMethod::Repeat, + gradient_spread: GradientSpread::Repeat, ..default_spread.clone() }; let json = serde_json::to_string(&repeating).unwrap(); - assert!(json.contains(r#""spread_method":"Repeat""#), "a non-default spread method must serialize: {json}"); + assert!(json.contains(r#""gradient_spread":"Repeat""#), "a non-default gradient spread must serialize: {json}"); assert_eq!(serde_json::from_str::(&json).unwrap(), repeating); } #[test] - fn spread_method_round_trips_through_the_item_attribute() { + fn gradient_spread_round_trips_through_the_item_attribute() { let ramp = GradientRamp { - spread_method: GradientSpreadMethod::Repeat, + gradient_spread: GradientSpread::Repeat, ..GradientRamp::from(Gradient::from(vec![Color::BLACK, Color::WHITE])) }; let item = Item::::from(ramp.clone()); assert_eq!( - item.attribute_cloned_or_default::(ATTR_SPREAD_METHOD), - GradientSpreadMethod::Repeat, - "the runtime item should carry the spread method as its attribute" + item.attribute_cloned_or_default::(ATTR_GRADIENT_SPREAD), + GradientSpread::Repeat, + "the runtime item should carry the gradient spread as its attribute" ); assert_eq!(GradientRamp::from(&item), ramp); let padded = Item::::from(GradientRamp::from(Gradient::from(vec![Color::BLACK, Color::WHITE]))); assert!( - padded.attribute::(ATTR_SPREAD_METHOD).is_none(), + padded.attribute::(ATTR_GRADIENT_SPREAD).is_none(), "the default Pad must stay absent rather than materialize" ); } diff --git a/node-graph/libraries/vector-types/src/lib.rs b/node-graph/libraries/vector-types/src/lib.rs index f37151a44e..b0d89e9d45 100644 --- a/node-graph/libraries/vector-types/src/lib.rs +++ b/node-graph/libraries/vector-types/src/lib.rs @@ -8,7 +8,7 @@ pub mod vector; // Re-export commonly used types at the crate root pub use core_types as gcore; -pub use gradient::{Gradient, GradientRamp, GradientSpreadMethod, GradientStop, GradientType}; +pub use gradient::{Gradient, GradientRamp, GradientSpread, GradientStop, GradientType}; pub use math::{QuadExt, RectExt}; pub use subpath::Subpath; pub use vector::Vector; diff --git a/node-graph/nodes/graphic/src/graphic.rs b/node-graph/nodes/graphic/src/graphic.rs index f467008f32..ef8fb37bcc 100644 --- a/node-graph/nodes/graphic/src/graphic.rs +++ b/node-graph/nodes/graphic/src/graphic.rs @@ -9,7 +9,7 @@ use rand::SeedableRng; use rand::seq::SliceRandom; use raster_types::{CPU, GPU, Raster}; use std::cmp::Ordering; -use vector_types::gradient::{GradientSpreadMethod, GradientType}; +use vector_types::gradient::{GradientSpread, GradientType}; use vector_types::{Gradient, ReferencePoint}; /// Returns the list with the item at the specified index removed. @@ -568,7 +568,7 @@ async fn write_attribute( List, List, List, - List, + List, )] content: List, /// The attribute name (key) to write or replace. @@ -730,18 +730,18 @@ fn read_attribute_gradient_type( result } -/// Reads a named `GradientSpreadMethod` attribute from the input list, outputting each value as an element of a new `GradientSpreadMethod[]`. +/// Reads a named `GradientSpread` attribute from the input list, outputting each value as an element of a new `GradientSpread[]`. #[node_macro::node(category("Attributes: Read"))] -fn read_attribute_spread_method( +fn read_attribute_gradient_spread( _: impl Ctx, content: ListDyn, /// The attribute name (key) to read. name: Item, -) -> List { +) -> List { let name = name.into_element(); let mut result = List::with_capacity(content.len()); for index in 0..content.len() { - let Some(value) = content.attribute::(&name, index) else { continue }; + let Some(value) = content.attribute::(&name, index) else { continue }; result.push(Item::new_from_element(*value)); } result diff --git a/node-graph/nodes/math/src/lib.rs b/node-graph/nodes/math/src/lib.rs index 9bda897f82..7429b5dae2 100644 --- a/node-graph/nodes/math/src/lib.rs +++ b/node-graph/nodes/math/src/lib.rs @@ -1387,9 +1387,9 @@ fn gradient_type(_: impl Ctx, gradient: Item, gradient_type: Item, spread_method: Item) -> Item { +fn gradient_spread(_: impl Ctx, gradient: Item, gradient_spread: Item) -> Item { let mut gradient = gradient; - gradient.set_attribute(core_types::ATTR_SPREAD_METHOD, *spread_method.element()); + gradient.set_attribute(core_types::ATTR_GRADIENT_SPREAD, *gradient_spread.element()); gradient } @@ -1417,11 +1417,11 @@ fn gradient_midpoints(_: impl Ctx, gradient: Item, midpoints: List, position: Item) -> Item { - let spread_method = gradient.attribute_cloned_or_default::(core_types::ATTR_SPREAD_METHOD); - let color = gradient.element().evaluate(*position.element(), spread_method); + let gradient_spread = gradient.attribute_cloned_or_default::(core_types::ATTR_GRADIENT_SPREAD); + let color = gradient.element().evaluate(*position.element(), gradient_spread); Item::new_from_element(color) } diff --git a/node-graph/nodes/path-bool/src/lib.rs b/node-graph/nodes/path-bool/src/lib.rs index bcfed58a5a..69d6165114 100644 --- a/node-graph/nodes/path-bool/src/lib.rs +++ b/node-graph/nodes/path-bool/src/lib.rs @@ -1,10 +1,10 @@ use core_types::list::{ATTR_FILL, Item, ItemAttributeValues, List}; use core_types::{ - ATTR_BLEND_MODE, ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_GRADIENT_TYPE, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_SPREAD_METHOD, ATTR_TRANSFORM, Color, Ctx, + ATTR_BLEND_MODE, ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_GRADIENT_SPREAD, ATTR_GRADIENT_TYPE, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TRANSFORM, Color, Ctx, }; use glam::{DAffine2, DVec2}; use graphic_types::graphic::{bake_paint_transforms, set_paint_attribute}; -use graphic_types::vector_types::gradient::{GradientSpreadMethod, GradientType}; +use graphic_types::vector_types::gradient::{GradientSpread, GradientType}; use graphic_types::vector_types::subpath::{ManipulatorGroup, Subpath}; use graphic_types::vector_types::vector::PointId; use graphic_types::vector_types::vector::algorithms::merge_by_distance::MergeByDistanceExt; @@ -286,8 +286,8 @@ fn flatten_vector(graphic_list: &List) -> List { if let Some(gradient_type) = attributes.remove::(ATTR_GRADIENT_TYPE) { gradient_paint.set_attribute(ATTR_GRADIENT_TYPE, 0, gradient_type); } - if let Some(spread_method) = attributes.remove::(ATTR_SPREAD_METHOD) { - gradient_paint.set_attribute(ATTR_SPREAD_METHOD, 0, spread_method); + if let Some(gradient_spread) = attributes.remove::(ATTR_GRADIENT_SPREAD) { + gradient_paint.set_attribute(ATTR_GRADIENT_SPREAD, 0, gradient_spread); } set_paint_attribute(&mut attributes, ATTR_FILL, gradient_paint); diff --git a/node-graph/nodes/raster/src/gradient_map.rs b/node-graph/nodes/raster/src/gradient_map.rs index 96ef236867..e11cfc8433 100644 --- a/node-graph/nodes/raster/src/gradient_map.rs +++ b/node-graph/nodes/raster/src/gradient_map.rs @@ -22,14 +22,14 @@ async fn gradient_map + Send>( reverse: Item, ) -> Item { let mut image = image; - let spread_method = gradient.attribute_cloned_or_default::(core_types::ATTR_SPREAD_METHOD); + let gradient_spread = gradient.attribute_cloned_or_default::(core_types::ATTR_GRADIENT_SPREAD); let gradient = gradient.into_element(); let reverse = reverse.into_element(); image.element_mut().adjust(|color| { let intensity = color.luminance_rec_709(); let intensity = if reverse { 1. - intensity } else { intensity }; - gradient.evaluate(intensity as f64, spread_method) + gradient.evaluate(intensity as f64, gradient_spread) }); image