Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,8 @@ pub struct SpectrumInput {
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct SpectrumMarker {
/// Position (0..1) of the marker along the spectrum track.
/// Position of the marker along the spectrum track, normally from 0 to 1. A shifted or stretched non-cyclic ramp can
/// place it outside that range, where the track draws only the markers falling within its visible span.
position: f64,
/// Position (0..1) of the midpoint between this marker and the next, used only if `show_midpoints` is true.
/// The last marker's value controls the wrapped interval when `track_cyclic` is set, and is otherwise ignored.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use graphene_std::vector::misc::{
ArcType, BooleanOperation, BoxCorners, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType,
};
use graphene_std::vector::style::{
DashPattern, FillChoice, GradientForm, GradientHueDirection, GradientInterpolation, GradientRamp, GradientSpace, GradientSpread, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin,
DashPattern, FillChoice, GradientForm, GradientHueDirection, GradientInterpolation, GradientRamp, GradientSettings, GradientSpace, GradientSpread, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin,
};
use graphene_std::vector::{QRCodeErrorCorrectionLevel, Vector};
use graphene_std::{Artboard, Color, Context, Graphic};
Expand Down Expand Up @@ -102,6 +102,7 @@ impl DataPanelMessageHandler {
desired_path: &mut self.element_path,
network_interface: &*network_interface,
node_lookup_network_path: Vec::new(),
gradient_settings: GradientSettings::default(),
breadcrumbs: Vec::new(),
vector_table_tab: self.active_vector_table_tab,
};
Expand Down Expand Up @@ -173,6 +174,9 @@ struct LayoutData<'a> {
/// Defaults to root (`&[]`); `List<NodeId>` rendering temporarily sets it to the path's prefix so nested
/// layers (e.g. inside a Ctrl+M-merged custom subgraph) resolve correctly.
node_lookup_network_path: Vec<NodeId>,
/// The whole-ramp settings to preview a `Gradient` element with, since they live in the attributes beside it
/// rather than in the stop list itself. The enclosing `Item`/`List` sets it to the owning row's attributes.
gradient_settings: GradientSettings,
breadcrumbs: Vec<String>,
vector_table_tab: VectorTableTab,
}
Expand Down Expand Up @@ -385,7 +389,10 @@ impl<T: TableItemLayout> TableItemLayout for Item<T> {
let attribute_keys: Vec<String> = self.attributes().keys().map(str::to_string).collect();

// A single element, so no leading ID column, unlike the `List` table
let saved_gradient_settings = data.gradient_settings;
data.gradient_settings = GradientSettings::from_item_attributes(self);
let mut values = vec![self.element().value_widgets(PathStep::Element(0), data)];
data.gradient_settings = saved_gradient_settings;
for key in &attribute_keys {
let target = PathStep::Attribute { row: 0, key: key.clone() };
let cell = self.attributes().get_any(key).and_then(|any| dispatch_value_widgets(any, target, data)).unwrap_or_else(|| {
Expand Down Expand Up @@ -443,10 +450,13 @@ impl<T: TableItemLayout> TableItemLayout for List<T> {
let mut rows = (0..self.len())
.map(|index| {
let element = self.element(index).unwrap();
let saved_gradient_settings = data.gradient_settings;
data.gradient_settings = GradientSettings::from_list_row_attributes(self, index);
let mut values = vec![
vec![TextLabel::new(format!("{index}")).narrow(true).widget_instance()],
element.value_widgets(PathStep::Element(index), data),
];
data.gradient_settings = saved_gradient_settings;
for key in &attribute_keys {
let target = PathStep::Attribute { row: index, key: key.clone() };
let cell = self.attribute_any(key, index).and_then(|any| dispatch_value_widgets(any, target, data)).unwrap_or_else(|| {
Expand Down Expand Up @@ -752,14 +762,14 @@ impl TableItemLayout for Gradient {
self.value_page(data)
}
// The preview widget doesn't navigate, so a drill-in button beside it opens the newtype's underlying color list
fn value_widgets(&self, target: PathStep, _data: &LayoutData) -> Vec<WidgetInstance> {
fn value_widgets(&self, target: PathStep, data: &LayoutData) -> Vec<WidgetInstance> {
vec![
TextButton::new(self.as_color_list().identifier())
.on_update(move |_| DataPanelMessage::PushToElementPath { step: target.clone() }.into())
.narrow(true)
.widget_instance(),
Separator::new(SeparatorStyle::Related).widget_instance(),
ColorInput::new(FillChoice::<SRGBA8>::Gradient(GradientRamp::from(self)))
ColorInput::new(FillChoice::<SRGBA8>::Gradient(GradientRamp::from(self).with_settings(data.gradient_settings)))
.menu_direction(Some(MenuDirection::Top))
.disabled(true)
.narrow(true)
Expand Down
68 changes: 36 additions & 32 deletions frontend/src/components/widgets/inputs/SpectrumInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -414,42 +414,46 @@
</LayoutRow>
<LayoutRow class="midpoint-track">
{#each midpointPositions as midpoint, index}
<svg
class="midpoint"
class:active={index === activeMarkerIndex && activeMarkerIsMidpoint}
style:--midpoint-position={midpoint}
on:pointerdown={(e) => midpointPointerDown(e, index)}
on:dblclick={() => midpointDoubleClick(index)}
data-gradient-midpoint
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
>
<polygon points="0,4 4,0 8,4 4,8" />
</svg>
{#if midpoint >= 0 && midpoint <= 1}
<svg
class="midpoint"
class:active={index === activeMarkerIndex && activeMarkerIsMidpoint}
style:--midpoint-position={midpoint}
on:pointerdown={(e) => midpointPointerDown(e, index)}
on:dblclick={() => midpointDoubleClick(index)}
data-gradient-midpoint
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 8 8"
>
<polygon points="0,4 4,0 8,4 4,8" />
</svg>
{/if}
{/each}
</LayoutRow>
<LayoutRow class="marker-track" bind:this={markerTrackElement}>
{#each markers as marker, index}
<svg
class="marker"
class:active={index === activeMarkerIndex && !activeMarkerIsMidpoint}
style:--marker-position={marker.position}
style:--marker-color={marker.handleColorCSS}
on:pointerdown={(e) => markerPointerDown(e, index)}
on:dblclick={() => markerDoubleClick(index)}
data-gradient-marker
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 12 12"
>
<path class="inner-fill" d="M10,11.5H2c-0.8,0-1.5-0.7-1.5-1.5V6.8c0-0.4,0.2-0.8,0.4-1.1L6,0.7l5.1,5.1c0.3,0.3,0.4,0.7,0.4,1.1V10C11.5,10.8,10.8,11.5,10,11.5z" />
{#if disabled}
<path class="disabled-fill" d="M10,11.5H2c-0.8,0-1.5-0.7-1.5-1.5V6.8c0-0.4,0.2-0.8,0.4-1.1L6,0.7l5.1,5.1c0.3,0.3,0.4,0.7,0.4,1.1V10C11.5,10.8,10.8,11.5,10,11.5z" />
{/if}
<path
class="outer-border"
d="M6,1.4L1.3,6.1C1.1,6.3,1,6.6,1,6.8V10c0,0.6,0.4,1,1,1h8c0.6,0,1-0.4,1-1V6.8c0-0.3-0.1-0.5-0.3-0.7L6,1.4M6,0l5.4,5.4C11.8,5.8,12,6.3,12,6.8V10c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V6.8c0-0.5,0.2-1,0.6-1.4L6,0z"
/>
</svg>
{#if marker.position >= 0 && marker.position <= 1}
Comment thread
Keavon marked this conversation as resolved.
<svg
class="marker"
class:active={index === activeMarkerIndex && !activeMarkerIsMidpoint}
style:--marker-position={marker.position}
style:--marker-color={marker.handleColorCSS}
on:pointerdown={(e) => markerPointerDown(e, index)}
on:dblclick={() => markerDoubleClick(index)}
data-gradient-marker
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 12 12"
>
<path class="inner-fill" d="M10,11.5H2c-0.8,0-1.5-0.7-1.5-1.5V6.8c0-0.4,0.2-0.8,0.4-1.1L6,0.7l5.1,5.1c0.3,0.3,0.4,0.7,0.4,1.1V10C11.5,10.8,10.8,11.5,10,11.5z" />
{#if disabled}
<path class="disabled-fill" d="M10,11.5H2c-0.8,0-1.5-0.7-1.5-1.5V6.8c0-0.4,0.2-0.8,0.4-1.1L6,0.7l5.1,5.1c0.3,0.3,0.4,0.7,0.4,1.1V10C11.5,10.8,10.8,11.5,10,11.5z" />
{/if}
<path
class="outer-border"
d="M6,1.4L1.3,6.1C1.1,6.3,1,6.6,1,6.8V10c0,0.6,0.4,1,1,1h8c0.6,0,1-0.4,1-1V6.8c0-0.3-0.1-0.5-0.3-0.7L6,1.4M6,0l5.4,5.4C11.8,5.8,12,6.3,12,6.8V10c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2V6.8c0-0.5,0.2-1,0.6-1.4L6,0z"
/>
</svg>
{/if}
{/each}
</LayoutRow>
</LayoutCol>
Expand Down
6 changes: 3 additions & 3 deletions node-graph/libraries/rendering/src/render_ext.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::renderer::{ClearGuardPlacement, RenderParams, format_transform_matrix, gradient_placement, gradient_settings_at, spread_adjusted_samples, transform_is_invertible};
use crate::renderer::{ClearGuardPlacement, RenderParams, format_transform_matrix, gradient_placement, spread_adjusted_samples, transform_is_invertible};
use crate::{Render, RenderSvgSegmentList, SvgRender};
use core_types::color::SRGBA8;
use core_types::list::List;
Expand All @@ -10,7 +10,7 @@ use graphic_types::vector_types::gradient::GradientForm;
use graphic_types::vector_types::vector::style::{PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
use std::fmt::Write;
use vector_types::Gradient;
use vector_types::gradient::GradientSpread;
use vector_types::gradient::{GradientSettings, GradientSpread};

#[derive(Copy, Clone, PartialEq)]
pub enum PaintTarget {
Expand Down Expand Up @@ -95,7 +95,7 @@ impl RenderExt for List<Gradient> {
let Some(stops) = self.element(0) else { return 0 };
let gradient_form: GradientForm = self.attribute_cloned_or_default(ATTR_GRADIENT_FORM, 0);
let local_gradient_transform: DAffine2 = self.attribute_cloned_or_default(ATTR_TRANSFORM, 0);
let settings = gradient_settings_at(self, 0);
let settings = GradientSettings::from_list_row_attributes(self, 0);

let (samples, _) = spread_adjusted_samples(stops, settings, gradient_form, ClearGuardPlacement::SvgStopOrder);

Expand Down
21 changes: 5 additions & 16 deletions node-graph/libraries/rendering/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ 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_CYCLIC, ATTR_GRADIENT_FORM, ATTR_GRADIENT_HUE_DIRECTION, ATTR_GRADIENT_INTERPOLATION, ATTR_GRADIENT_SPACE, ATTR_GRADIENT_SPREAD, 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,
ATTR_FONT_SIZE, ATTR_GRADIENT_FORM, 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;
use glam::{DAffine2, DMat2, DVec2};
Expand Down Expand Up @@ -496,23 +496,12 @@ fn peniko_extend(gradient_spread: GradientSpread) -> peniko::Extend {
}
}

/// The whole-ramp settings attributes carried by the gradient at `index` of the list.
pub(crate) fn gradient_settings_at(list: &List<Gradient>, index: usize) -> GradientSettings {
GradientSettings {
spread: list.attribute_cloned_or_default(ATTR_GRADIENT_SPREAD, index),
cyclic: list.attribute_cloned_or_default(ATTR_GRADIENT_CYCLIC, index),
space: list.attribute_cloned_or_default(ATTR_GRADIENT_SPACE, index),
hue_direction: list.attribute_cloned_or_default(ATTR_GRADIENT_HUE_DIRECTION, index),
interpolation: list.attribute_cloned_or_default(ATTR_GRADIENT_INTERPOLATION, index),
}
}

fn create_peniko_gradient_brush(gradient_list: &List<Gradient>, multiplied_transform: &DAffine2) -> Option<(peniko::Brush, DAffine2)> {
let stops = gradient_list.element(0)?;

let gradient_form: GradientForm = gradient_list.attribute_cloned_or_default(ATTR_GRADIENT_FORM, 0);
let gradient_transform: DAffine2 = gradient_list.attribute_cloned_or_default(ATTR_TRANSFORM, 0);
let settings = gradient_settings_at(gradient_list, 0);
let settings = GradientSettings::from_list_row_attributes(gradient_list, 0);

let (samples, span) = spread_adjusted_samples(stops, settings, gradient_form, ClearGuardPlacement::VelloRampTexels);

Expand Down Expand Up @@ -2195,7 +2184,7 @@ impl Render for List<Gradient> {
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 gradient_form: GradientForm = self.attribute_cloned_or_default(ATTR_GRADIENT_FORM, index);
let settings = gradient_settings_at(self, index);
let settings = GradientSettings::from_list_row_attributes(self, index);
let tag = if thumbnail_rect.is_some() { "rect" } else { "polyline" };
render.leaf_tag(tag, |attributes| {
if let Some((min, size)) = thumbnail_rect {
Expand Down Expand Up @@ -2288,7 +2277,7 @@ impl Render for List<Gradient> {
let blend_mode = blend_mode_attr.to_peniko();
let opacity = (opacity_attr * if render_params.for_mask { 1. } else { opacity_fill_attr }) as f32;

let settings = gradient_settings_at(self, index);
let settings = GradientSettings::from_list_row_attributes(self, index);
let (samples, span) = spread_adjusted_samples(gradient, settings, gradient_form, ClearGuardPlacement::VelloRampTexels);

let stops = peniko_color_stops(&samples);
Expand Down
Loading
Loading