Skip to content

Commit 9b2f38a

Browse files
committed
Add Table<GradientStops> gradient rendering
* Add SVG and Vello renderers for Table<GradientStops> * Add thumbnail rendering for Table<GradientStops> * Use row transform to map (0,0), (1,0) unit line to document space * Set 100px width for the initially created gradient * Add support of table gradients for the gradient tool
1 parent da45ab2 commit 9b2f38a

19 files changed

Lines changed: 511 additions & 71 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ use graphene_std::raster_types::{CPU, Raster};
1010
use graphene_std::subpath::Subpath;
1111
use graphene_std::table::Table;
1212
use graphene_std::text::{Font, TypesettingConfig};
13-
use graphene_std::vector::PointId;
14-
use graphene_std::vector::VectorModificationType;
1513
use graphene_std::vector::style::{Fill, Stroke};
1614
use graphene_std::{Artboard, Color};
15+
use graphene_std::vector::{GradientStops, PointId, VectorModificationType};
1716

1817
#[impl_message(Message, DocumentMessage, GraphOperation)]
1918
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
@@ -26,6 +25,11 @@ pub enum GraphOperationMessage {
2625
layer: LayerNodeIdentifier,
2726
fill: f64,
2827
},
28+
GradientTableSet {
29+
layer: LayerNodeIdentifier,
30+
stops: GradientStops,
31+
transform: DAffine2,
32+
},
2933
OpacitySet {
3034
layer: LayerNodeIdentifier,
3135
opacity: f64,

editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
4545
modify_inputs.blending_fill_set(fill);
4646
}
4747
}
48+
GraphOperationMessage::GradientTableSet { layer, stops, transform } => {
49+
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
50+
modify_inputs.gradient_table_set(stops, transform);
51+
}
52+
}
4853
GraphOperationMessage::OpacitySet { layer, opacity } => {
4954
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
5055
modify_inputs.opacity_set(opacity);

editor/src/messages/portfolio/document/graph_operation/utility_types.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ use graphene_std::brush::brush_stroke::BrushStroke;
1111
use graphene_std::raster::BlendMode;
1212
use graphene_std::raster_types::{CPU, Raster};
1313
use graphene_std::subpath::Subpath;
14-
use graphene_std::table::Table;
14+
use graphene_std::table::{Table, TableRow};
1515
use graphene_std::text::{Font, TypesettingConfig};
16-
use graphene_std::vector::Vector;
1716
use graphene_std::vector::style::{Fill, Stroke};
18-
use graphene_std::vector::{PointId, VectorModificationType};
17+
use graphene_std::vector::{GradientStops, PointId, Vector, VectorModificationType};
1918
use graphene_std::{Artboard, Color, Graphic, NodeInputDecleration};
2019

2120
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
@@ -457,6 +456,20 @@ impl<'a> ModifyInputsContext<'a> {
457456
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::F64(fill * 100.), false), false);
458457
}
459458

459+
pub fn gradient_table_set(&mut self, stops: GradientStops, transform: DAffine2) {
460+
let Some(gradient_node_id) = self.existing_proto_node_id(graphene_std::math_nodes::gradient_value::IDENTIFIER, true) else {
461+
return;
462+
};
463+
464+
let table = Table::new_from_row(TableRow {
465+
element: stops,
466+
transform,
467+
..Default::default()
468+
});
469+
let input_connector = InputConnector::node(gradient_node_id, 1);
470+
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::GradientTable(table), false), false);
471+
}
472+
460473
pub fn clip_mode_toggle(&mut self, clip_mode: Option<bool>) {
461474
let clip = !clip_mode.unwrap_or(false);
462475
let Some(clip_node_id) = self.existing_proto_node_id(graphene_std::blending_nodes::blending::IDENTIFIER, true) else {

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

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,20 +1153,37 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
11531153
.on_commit(commit_value)
11541154
.widget_instance(),
11551155
),
1156-
TaggedValue::GradientTable(gradient_table) => widgets.push(
1157-
color_button
1158-
.value(match gradient_table.iter().next() {
1159-
Some(row) => FillChoice::Gradient(row.element.clone()),
1160-
None => FillChoice::Gradient(GradientStops::default()),
1161-
})
1162-
.on_update(update_value(
1163-
|input: &ColorInput| TaggedValue::GradientTable(input.value.as_gradient().iter().map(|&gradient| TableRow::new_from_element(gradient.clone())).collect()),
1164-
node_id,
1165-
index,
1166-
))
1167-
.on_commit(commit_value)
1168-
.widget_instance(),
1169-
),
1156+
TaggedValue::GradientTable(gradient_table) => {
1157+
let existing_transform = gradient_table.iter().next().map(|row| *row.transform).unwrap_or_default();
1158+
1159+
widgets.push(
1160+
color_button
1161+
.value(match gradient_table.iter().next() {
1162+
Some(row) => FillChoice::Gradient(row.element.clone()),
1163+
None => FillChoice::Gradient(GradientStops::default()),
1164+
})
1165+
.on_update(update_value(
1166+
move |input: &ColorInput| {
1167+
TaggedValue::GradientTable(
1168+
input
1169+
.value
1170+
.as_gradient()
1171+
.iter()
1172+
.map(|&gradient| TableRow {
1173+
element: gradient.clone(),
1174+
transform: existing_transform,
1175+
..Default::default()
1176+
})
1177+
.collect(),
1178+
)
1179+
},
1180+
node_id,
1181+
index,
1182+
))
1183+
.on_commit(commit_value)
1184+
.widget_instance(),
1185+
)
1186+
}
11701187
x => warn!("Color {x:?}"),
11711188
}
11721189

editor/src/messages/tool/common_functionality/graph_modification_utils.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use graphene_std::table::Table;
1616
use graphene_std::text::{Font, TypesettingConfig};
1717
use graphene_std::vector::misc::ManipulatorPointId;
1818
use graphene_std::vector::style::{Fill, Gradient};
19-
use graphene_std::vector::{PointId, SegmentId, VectorModificationType};
19+
use graphene_std::vector::{GradientStops, PointId, SegmentId, VectorModificationType};
2020
use std::collections::VecDeque;
2121

2222
/// Returns the ID of the first Spline node in the horizontal flow which is not followed by a `Path` node, or `None` if none exists.
@@ -285,6 +285,17 @@ pub fn get_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkI
285285
Some(gradient.clone())
286286
}
287287

288+
/// Get the gradient table of a layer.
289+
pub fn get_gradient_table(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<Table<GradientStops>> {
290+
let gradient_table_index = 1;
291+
292+
let inputs = NodeGraphLayer::new(layer, network_interface).find_node_inputs(&DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_value::IDENTIFIER))?;
293+
let TaggedValue::GradientTable(gradient_table) = inputs.get(gradient_table_index)?.as_value()? else {
294+
return None;
295+
};
296+
Some(gradient_table.clone())
297+
}
298+
288299
/// Get the current fill of a layer from the closest "Fill" node.
289300
pub fn get_fill_color(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<Color> {
290301
let fill_index = 1;

0 commit comments

Comments
 (0)