Skip to content

Commit e3288ad

Browse files
committed
Add mesh gradient editing operations
1 parent 2ea101f commit e3288ad

5 files changed

Lines changed: 65 additions & 4 deletions

File tree

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use graphene_std::raster_types::Image;
1111
use graphene_std::subpath::Subpath;
1212
use graphene_std::text::{Font, TypesettingConfig};
1313
use graphene_std::vector::style::{GradientSpreadMethod, GradientType, Stroke};
14-
use graphene_std::vector::{Gradient, PointId, VectorModificationType};
14+
use graphene_std::vector::{Gradient, MeshGradient, PointId, VectorModificationType};
1515

1616
#[impl_message(Message, DocumentMessage, GraphOperation)]
1717
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
@@ -27,6 +27,10 @@ pub enum GraphOperationMessage {
2727
spread_method: GradientSpreadMethod,
2828
transform: DAffine2,
2929
},
30+
FillMeshGradientSet {
31+
layer: LayerNodeIdentifier,
32+
mesh_gradient: MeshGradient,
33+
},
3034
BlendingFillSet {
3135
layer: LayerNodeIdentifier,
3236
fill: f64,
@@ -47,6 +51,10 @@ pub enum GraphOperationMessage {
4751
layer: LayerNodeIdentifier,
4852
spread_method: GradientSpreadMethod,
4953
},
54+
MeshGradientSet {
55+
layer: LayerNodeIdentifier,
56+
mesh_gradient: MeshGradient,
57+
},
5058
OpacitySet {
5159
layer: LayerNodeIdentifier,
5260
opacity: f64,

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
4949
modify_inputs.fill_gradient_set(gradient, gradient_type, spread_method, transform);
5050
}
5151
}
52+
GraphOperationMessage::FillMeshGradientSet { layer, mesh_gradient } => {
53+
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
54+
modify_inputs.fill_mesh_gradient_set(mesh_gradient);
55+
}
56+
}
5257
GraphOperationMessage::BlendingFillSet { layer, fill } => {
5358
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
5459
modify_inputs.opacity_fill_set(fill);
@@ -74,6 +79,11 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
7479
modify_inputs.gradient_spread_method_set(spread_method);
7580
}
7681
}
82+
GraphOperationMessage::MeshGradientSet { layer, mesh_gradient } => {
83+
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
84+
modify_inputs.mesh_gradient_set(mesh_gradient);
85+
}
86+
}
7787
GraphOperationMessage::OpacitySet { layer, opacity } => {
7888
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
7989
modify_inputs.opacity_set(opacity);

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use crate::messages::portfolio::document::node_graph::document_node_definitions:
33
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
44
use crate::messages::portfolio::document::utility_types::network_interface::{self, FlowType, InputConnector, NodeNetworkInterface, OutputConnector};
55
use crate::messages::prelude::*;
6-
use crate::messages::tool::common_functionality::graph_modification_utils::{get_fill_input_node_id, get_upstream_gradient_value_node_id, gradient_chain_target_input};
6+
use crate::messages::tool::common_functionality::graph_modification_utils::{
7+
get_fill_input_node_id, get_fill_node_id_with_direct_fill_input, get_upstream_gradient_value_node_id, get_upstream_mesh_gradient_value_node_id, gradient_chain_target_input,
8+
};
79
use glam::{DAffine2, DVec2, IVec2};
810
use graph_craft::application_io::resource::ResourceId;
911
use graph_craft::document::value::TaggedValue;
@@ -16,7 +18,7 @@ use graphene_std::raster_types::Image;
1618
use graphene_std::subpath::Subpath;
1719
use graphene_std::text::{Font, TypesettingConfig};
1820
use graphene_std::vector::style::{GradientSpreadMethod, GradientType, Stroke};
19-
use graphene_std::vector::{Gradient, PointId, Vector, VectorModification, VectorModificationType};
21+
use graphene_std::vector::{Gradient, MeshGradient, PointId, Vector, VectorModification, VectorModificationType};
2022
use graphene_std::{Artboard, Color, Graphic, NodeInputDecleration};
2123

2224
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
@@ -571,6 +573,36 @@ impl<'a> ModifyInputsContext<'a> {
571573
);
572574
}
573575

576+
/// Write the mesh gradient to the Fill node's direct value.
577+
pub fn fill_mesh_gradient_set(&mut self, mesh_gradient: MeshGradient) {
578+
let Some(fill_node_id) = self
579+
.get_output_layer()
580+
.and_then(|output_layer| get_fill_node_id_with_direct_fill_input(output_layer, self.network_interface))
581+
else {
582+
return;
583+
};
584+
self.set_input_with_refresh(
585+
InputConnector::node(fill_node_id, graphene_std::vector::fill::BackupMeshGradientInput::INDEX),
586+
NodeInput::value(TaggedValue::MeshGradient(mesh_gradient.clone()), false),
587+
true,
588+
);
589+
self.set_input_with_refresh(
590+
InputConnector::node(fill_node_id, graphene_std::vector::fill::FillInput::<List<Graphic>>::INDEX),
591+
NodeInput::value(TaggedValue::MeshGradient(mesh_gradient), false),
592+
false,
593+
);
594+
}
595+
596+
/// Write the mesh gradient to the Mesh Gradient Value node feeding the layer.
597+
pub fn mesh_gradient_set(&mut self, mesh_gradient: MeshGradient) {
598+
let Some(output_layer) = self.get_output_layer() else { return };
599+
let Some(mesh_gradient_value_id) = get_upstream_mesh_gradient_value_node_id(output_layer, self.network_interface) else {
600+
return;
601+
};
602+
let input_connector = InputConnector::node(mesh_gradient_value_id, graphene_std::math_nodes::mesh_gradient_value::MeshGradientInput::INDEX);
603+
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::MeshGradient(mesh_gradient), false), false);
604+
}
605+
574606
/// Write the gradient stops to the 'Gradient Value' node feeding the layer.
575607
pub fn gradient_stops_set(&mut self, stops: Gradient) {
576608
let Some(output_layer) = self.get_output_layer() else { return };

editor/src/messages/portfolio/document/overlays/utility_functions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub fn selected_segments_for_layer(vector: &Vector, state: &SelectedLayerState)
6969
selected_segments
7070
}
7171

72-
fn overlay_bezier_handles(bezier: Bezier, segment_id: SegmentId, transform: DAffine2, is_selected: impl Fn(ManipulatorPointId) -> bool, overlay_context: &mut OverlayContext) {
72+
pub fn overlay_bezier_handles(bezier: Bezier, segment_id: SegmentId, transform: DAffine2, is_selected: impl Fn(ManipulatorPointId) -> bool, overlay_context: &mut OverlayContext) {
7373
let bezier = bezier.apply_transformation(|point| transform.transform_point2(point));
7474
let not_under_anchor = |position: DVec2, anchor: DVec2| position.distance_squared(anchor) >= HIDE_HANDLE_DISTANCE * HIDE_HANDLE_DISTANCE;
7575

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,17 @@ pub fn gradient_orientation_rightward(transform: glam::DAffine2) -> bool {
360360
}
361361
}
362362

363+
/// Try to find a "Mesh Gradient Value" node that is connected to a "Fill" node, or to a layer directly.
364+
pub fn get_upstream_mesh_gradient_value_node_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<NodeId> {
365+
let target_input = gradient_chain_target_input(layer, network_interface);
366+
let walk_from = network_interface.upstream_output_connector(&target_input, &[])?.node_id()?;
367+
368+
network_interface
369+
.upstream_flow_back_from_nodes(vec![walk_from], &[], FlowType::HorizontalFlow)
370+
.take_while(|node_id| !network_interface.is_layer(node_id, &[]))
371+
.find(|node_id| network_interface.reference(node_id, &[]).as_ref() == Some(&DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::mesh_gradient_value::IDENTIFIER)))
372+
}
373+
363374
/// Get the current fill of a layer from the closest "Fill" node.
364375
pub fn get_fill_color(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<Color> {
365376
let inputs = NodeGraphLayer::new(layer, network_interface).find_node_inputs(&DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER))?;

0 commit comments

Comments
 (0)