Skip to content

Commit 5133e30

Browse files
YohYamasakiKeavon
authored andcommitted
Add Table<GradientStops> gradient rendering (#3989)
* 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 * Fix after review * Thumbnail rendering of artboard with infinite gradient layer * Hide radial gradient's reverse direction button for gradient table * Remove unused imports * Format * Fix conflict with spread method * Code review * Fix thumbnails * Connect up gradient_type and spread_method to attributes --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
1 parent f06df3d commit 5133e30

19 files changed

Lines changed: 614 additions & 91 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/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Bumped past the default 128 because the deeply-generic message-passing types pull in wgpu/naga
2+
// trait chains that overflow the trait resolver under `--tests`. Set to the same value the compiler suggests.
3+
#![recursion_limit = "256"]
4+
15
extern crate graphite_proc_macros;
26

37
// `macro_use` puts these macros into scope for all descendant code files

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
@@ -9,10 +9,10 @@ use graphene_std::color::Color;
99
use graphene_std::raster::BlendMode;
1010
use graphene_std::raster_types::Image;
1111
use graphene_std::subpath::Subpath;
12+
use graphene_std::table::Table;
1213
use graphene_std::text::{Font, TypesettingConfig};
13-
use graphene_std::vector::PointId;
14-
use graphene_std::vector::VectorModificationType;
1514
use graphene_std::vector::style::{Fill, Stroke};
15+
use graphene_std::vector::{GradientStops, PointId, VectorModificationType};
1616

1717
#[impl_message(Message, DocumentMessage, GraphOperation)]
1818
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
@@ -25,6 +25,10 @@ pub enum GraphOperationMessage {
2525
layer: LayerNodeIdentifier,
2626
fill: f64,
2727
},
28+
GradientTableSet {
29+
layer: LayerNodeIdentifier,
30+
gradient_table: Table<GradientStops>,
31+
},
2832
OpacitySet {
2933
layer: LayerNodeIdentifier,
3034
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, gradient_table } => {
49+
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
50+
modify_inputs.gradient_table_set(gradient_table);
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: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ use graphene_std::raster_types::Image;
1313
use graphene_std::subpath::Subpath;
1414
use graphene_std::table::Table;
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, VectorModification, VectorModificationType};
17+
use graphene_std::vector::{GradientStops, PointId, Vector, VectorModification, VectorModificationType};
1918
use graphene_std::{Color, Graphic, NodeInputDecleration};
2019

2120
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
@@ -461,6 +460,15 @@ impl<'a> ModifyInputsContext<'a> {
461460
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::F64(fill * 100.), false), false);
462461
}
463462

463+
pub fn gradient_table_set(&mut self, gradient_table: Table<GradientStops>) {
464+
let Some(gradient_node_id) = self.existing_proto_node_id(graphene_std::math_nodes::gradient_value::IDENTIFIER, true) else {
465+
return;
466+
};
467+
468+
let input_connector = InputConnector::node(gradient_node_id, graphene_std::math_nodes::gradient_value::GradientInput::INDEX);
469+
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::GradientTable(gradient_table), false), false);
470+
}
471+
464472
pub fn clip_mode_toggle(&mut self, clip_mode: Option<bool>) {
465473
let clip = !clip_mode.unwrap_or(false);
466474
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: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use glam::{DAffine2, DVec2};
1313
use graph_craft::document::value::TaggedValue;
1414
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
1515
use graph_craft::{Type, concrete};
16+
use graphene_std::ATTR_TRANSFORM;
1617
use graphene_std::NodeInputDecleration;
1718
use graphene_std::animation::RealTimeMode;
1819
use graphene_std::extract_xy::XY;
@@ -1154,20 +1155,33 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
11541155
.on_commit(commit_value)
11551156
.widget_instance(),
11561157
),
1157-
TaggedValue::GradientTable(gradient_table) => widgets.push(
1158-
color_button
1159-
.value(match gradient_table.element(0) {
1160-
Some(gradient) => FillChoice::Gradient(gradient.clone()),
1161-
None => FillChoice::Gradient(GradientStops::default()),
1162-
})
1163-
.on_update(update_value(
1164-
|input: &ColorInput| TaggedValue::GradientTable(input.value.as_gradient().iter().map(|&gradient| TableRow::new_from_element(gradient.clone())).collect()),
1165-
node_id,
1166-
index,
1167-
))
1168-
.on_commit(commit_value)
1169-
.widget_instance(),
1170-
),
1158+
TaggedValue::GradientTable(gradient_table) => {
1159+
let existing_transform: DAffine2 = gradient_table.attribute_cloned_or_default(ATTR_TRANSFORM, 0);
1160+
1161+
widgets.push(
1162+
color_button
1163+
.value(match gradient_table.element(0) {
1164+
Some(gradient) => FillChoice::Gradient(gradient.clone()),
1165+
None => FillChoice::Gradient(GradientStops::default()),
1166+
})
1167+
.on_update(update_value(
1168+
move |input: &ColorInput| {
1169+
TaggedValue::GradientTable(
1170+
input
1171+
.value
1172+
.as_gradient()
1173+
.iter()
1174+
.map(|&gradient| TableRow::new_from_element(gradient.clone()).with_attribute(ATTR_TRANSFORM, existing_transform))
1175+
.collect(),
1176+
)
1177+
},
1178+
node_id,
1179+
index,
1180+
))
1181+
.on_commit(commit_value)
1182+
.widget_instance(),
1183+
)
1184+
}
11711185
x => warn!("Color {x:?}"),
11721186
}
11731187

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

Lines changed: 10 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.
@@ -280,6 +280,15 @@ pub fn get_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkI
280280
Some(gradient.clone())
281281
}
282282

283+
/// Get the gradient table of a layer.
284+
pub fn get_gradient_table(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<Table<GradientStops>> {
285+
let inputs = NodeGraphLayer::new(layer, network_interface).find_node_inputs(&DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_value::IDENTIFIER))?;
286+
let TaggedValue::GradientTable(gradient_table) = inputs.get(graphene_std::math_nodes::gradient_value::GradientInput::INDEX)?.as_value()? else {
287+
return None;
288+
};
289+
Some(gradient_table.clone())
290+
}
291+
283292
/// Get the current fill of a layer from the closest "Fill" node.
284293
pub fn get_fill_color(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<Color> {
285294
let fill_index = 1;

0 commit comments

Comments
 (0)