Drop the legacy fill and stroke rows for single-typed paint

This commit is contained in:
Dennis Kobert
2026-08-22 17:29:51 +00:00
parent 7569bdb9cb
commit 3da7f6cea3
8 changed files with 191 additions and 240 deletions

View File

@@ -457,7 +457,7 @@ impl<'a> ModifyInputsContext<'a> {
let Some(fill_node_id) = self.existing_proto_node_id(graphene_std::vector_nodes::fill::IDENTIFIER, true) else {
return;
};
let input_connector = InputConnector::node(fill_node_id, graphene_std::vector::fill::FillInput::<Graphic>::INDEX);
let input_connector = InputConnector::node(fill_node_id, graphene_std::vector::fill::FillInput::INDEX);
let backup_input_connector = InputConnector::node(fill_node_id, graphene_std::vector::fill::BackupColorInput::INDEX);
self.set_input_with_refresh(backup_input_connector, NodeInput::value(TaggedValue::Color(color), false), true);
@@ -474,7 +474,7 @@ impl<'a> ModifyInputsContext<'a> {
// Skip the rerender on all but the last input so the whole update triggers a single graph run
self.set_input_with_refresh(
InputConnector::node(fill_node_id, graphene_std::vector::fill::FillInput::<Graphic>::INDEX),
InputConnector::node(fill_node_id, graphene_std::vector::fill::FillInput::INDEX),
NodeInput::value(TaggedValue::Gradient(gradient), false),
true,
);
@@ -715,7 +715,7 @@ impl<'a> ModifyInputsContext<'a> {
return;
};
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::PaintInput::<Graphic>::INDEX);
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::PaintInput::INDEX);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::Color(color), false), true);
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::WeightInput::INDEX);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::F64(stroke.weight), false), true);

View File

@@ -1769,7 +1769,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
let is_text_node = reference.as_ref().is_some_and(|r| *r == DefinitionIdentifier::ProtoNode(graphene_std::text::text::IDENTIFIER));
let is_stroke_node = reference.as_ref().is_some_and(|r| *r == DefinitionIdentifier::ProtoNode(graphene_std::vector::stroke::IDENTIFIER));
let is_fill_node = reference.as_ref().is_some_and(|r| *r == DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER));
let is_fill_input = is_fill_node && input_index == graphene_std::vector::fill::FillInput::<Graphic>::INDEX;
let is_fill_input = is_fill_node && input_index == graphene_std::vector::fill::FillInput::INDEX;
let is_shape_generator_node = reference.as_ref().is_some_and(|r| {
[regular_polygon::IDENTIFIER, star::IDENTIFIER, arc::IDENTIFIER, spiral::IDENTIFIER, grid::IDENTIFIER, arrow::IDENTIFIER]
.into_iter()

View File

@@ -16,7 +16,6 @@ use graph_craft::application_io::resource::ResourceId;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
use graph_craft::{Type, concrete};
use graphene_std::Graphic;
use graphene_std::NodeInputDecleration;
use graphene_std::animation::RealTimeMode;
use graphene_std::brush::brush_stroke::BrushStroke;
@@ -2172,7 +2171,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
use graphene_std::vector::generator_nodes::rectangle::*;
// Corner Radius
let mut corner_radius_row_1 = start_widgets(ParameterWidgetsInfo::new(node_id, CornerRadiusInput::<f64>::INDEX, true, context));
let mut corner_radius_row_1 = start_widgets(ParameterWidgetsInfo::new(node_id, CornerRadiusInput::INDEX, true, context));
corner_radius_row_1.push(Separator::new(SeparatorStyle::Unrelated).widget_instance());
let mut corner_radius_row_2 = vec![Separator::new(SeparatorStyle::Unrelated).widget_instance()];
@@ -2192,7 +2191,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
};
if let Some(&TaggedValue::Bool(is_individual)) = input.as_non_exposed_value() {
// Values
let Some(input) = document_node.inputs.get(CornerRadiusInput::<f64>::INDEX) else {
let Some(input) = document_node.inputs.get(CornerRadiusInput::INDEX) else {
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
@@ -2220,7 +2219,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
.into(),
NodeGraphMessage::SetInputValue {
node_id,
input_index: CornerRadiusInput::<f64>::INDEX,
input_index: CornerRadiusInput::INDEX,
value: TaggedValue::F64(uniform_val),
}
.into(),
@@ -2240,7 +2239,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
.into(),
NodeGraphMessage::SetInputValue {
node_id,
input_index: CornerRadiusInput::<f64>::INDEX,
input_index: CornerRadiusInput::INDEX,
value: TaggedValue::F64Array(individual_val_for_switch.clone()),
}
.into(),
@@ -2263,13 +2262,13 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
};
TextInput::default()
.value(individual_val.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", "))
.on_update(optionally_update_value(move |x: &TextInput| from_string(&x.value), node_id, CornerRadiusInput::<f64>::INDEX))
.on_update(optionally_update_value(move |x: &TextInput| from_string(&x.value), node_id, CornerRadiusInput::INDEX))
.widget_instance()
} else {
NumberInput::default()
.value(Some(uniform_val))
.unit(" px")
.on_update(update_value(move |x: &NumberInput| TaggedValue::F64(x.value.unwrap()), node_id, CornerRadiusInput::<f64>::INDEX))
.on_update(update_value(move |x: &NumberInput| TaggedValue::F64(x.value.unwrap()), node_id, CornerRadiusInput::INDEX))
.on_commit(commit_value)
.widget_instance()
};
@@ -2457,13 +2456,13 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
Other,
}
let connector = InputConnector::node(node_id, FillInput::<Graphic>::INDEX);
let connector = InputConnector::node(node_id, FillInput::INDEX);
let input_type = context.network_interface.input_type(&connector, context.selection_network_path);
// Pass blank_assist=false because the assist slot is filled below ("Reverse Stops" button when in gradient mode)
let mut widgets_first_row = start_widgets(ParameterWidgetsInfo::new(node_id, FillInput::<Graphic>::INDEX, false, context));
let mut widgets_first_row = start_widgets(ParameterWidgetsInfo::new(node_id, FillInput::INDEX, false, context));
if get_document_node(node_id, context).is_ok_and(|node| node.inputs.get(FillInput::<Graphic>::INDEX).is_some_and(|input| input.is_exposed())) {
if get_document_node(node_id, context).is_ok_and(|node| node.inputs.get(FillInput::INDEX).is_some_and(|input| input.is_exposed())) {
return vec![LayoutGroup::row(widgets_first_row)];
}
@@ -2474,7 +2473,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
let fill = match input_type.compiled_nested_type() {
Some(ty) if ty == &concrete!(List<Color>) => {
if let Ok(document_node) = get_document_node(node_id, context) {
let color = match document_node.inputs[FillInput::<Graphic>::INDEX].as_value() {
let color = match document_node.inputs[FillInput::INDEX].as_value() {
Some(&TaggedValue::Color(c)) => c,
_ => None,
};
@@ -2525,7 +2524,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
let reverse_button = IconButton::new("Reverse", 24)
.tooltip_label("Reverse Stops")
.tooltip_description("Reverse the gradient color stops.")
.on_update(update_value(move |_| TaggedValue::Gradient(stops.reversed()), node_id, FillInput::<Graphic>::INDEX))
.on_update(update_value(move |_| TaggedValue::Gradient(stops.reversed()), node_id, FillInput::INDEX))
.widget_instance();
widgets_first_row.push(Separator::new(SeparatorStyle::Unrelated).widget_instance());
widgets_first_row.push(reverse_button);
@@ -2549,7 +2548,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
messages: Box::new([
NodeGraphMessage::SetInputValue {
node_id,
input_index: FillInput::<Graphic>::INDEX,
input_index: FillInput::INDEX,
value: TaggedValue::Color(color),
}
.into(),
@@ -2566,7 +2565,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
messages: Box::new([
NodeGraphMessage::SetInputValue {
node_id,
input_index: FillInput::<Graphic>::INDEX,
input_index: FillInput::INDEX,
value: TaggedValue::Gradient(gradient.clone()),
}
.into(),
@@ -2607,11 +2606,11 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
let entries = vec![
RadioEntryData::new("solid")
.label("Solid")
.on_update(update_value(move |_| TaggedValue::Color(backup_color), node_id, FillInput::<Graphic>::INDEX))
.on_update(update_value(move |_| TaggedValue::Color(backup_color), node_id, FillInput::INDEX))
.on_commit(commit_value),
RadioEntryData::new("gradient")
.label("Gradient")
.on_update(update_value(move |_| TaggedValue::Gradient(backup_gradient.clone()), node_id, FillInput::<Graphic>::INDEX))
.on_update(update_value(move |_| TaggedValue::Gradient(backup_gradient.clone()), node_id, FillInput::INDEX))
.on_commit(commit_value),
];
@@ -2724,7 +2723,7 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
let miter_limit_disabled = join_value != &StrokeJoin::Miter;
let color = color_widget(
ParameterWidgetsInfo::new(node_id, PaintInput::<Graphic>::INDEX, true, context),
ParameterWidgetsInfo::new(node_id, PaintInput::INDEX, true, context),
crate::messages::layout::utility_types::widgets::button_widgets::ColorInput::default(),
);
let weight = number_widget(ParameterWidgetsInfo::new(node_id, WeightInput::INDEX, true, context), NumberInput::default().unit(" px").min(0.));

View File

@@ -16,7 +16,7 @@ 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::{GradientSpreadMethod, GradientStops, GradientType, PointId, SegmentId, VectorModificationType};
use graphene_std::{Color, Graphic};
use graphene_std::Color;
use std::collections::VecDeque;
/// 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.
@@ -275,14 +275,14 @@ pub fn get_viewport_center(layer: LayerNodeIdentifier, network_interface: &NodeN
pub fn get_fill_node_id_with_direct_fill_input(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<NodeId> {
let fill_node_id = NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name(&DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER))?;
let fill_node = network_interface.document_network().nodes.get(&fill_node_id)?;
matches!(fill_node.inputs.get(graphene_std::vector::fill::FillInput::<Graphic>::INDEX)?, NodeInput::Value { .. }).then_some(fill_node_id)
matches!(fill_node.inputs.get(graphene_std::vector::fill::FillInput::INDEX)?, NodeInput::Value { .. }).then_some(fill_node_id)
}
/// Determine the input connector where the gradient chain enters the layer.
/// Returns Fill's fill input if the layer has a "Fill" node, otherwise returns the layer's content input.
pub fn gradient_chain_target_input(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> InputConnector {
if let Some(fill_node_id) = NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name(&DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER)) {
InputConnector::node(fill_node_id, graphene_std::vector::fill::FillInput::<Graphic>::INDEX)
InputConnector::node(fill_node_id, graphene_std::vector::fill::FillInput::INDEX)
} else {
InputConnector::node(layer.to_node(), 1)
}
@@ -303,7 +303,7 @@ pub fn get_upstream_gradient_value_node_id(layer: LayerNodeIdentifier, network_i
pub fn get_fill_input_node_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<NodeId> {
let fill_node_id = NodeGraphLayer::new(layer, network_interface).upstream_node_id_from_name(&DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER))?;
let fill_node = network_interface.document_network().nodes.get(&fill_node_id)?;
let NodeInput::Node { node_id, .. } = fill_node.inputs.get(graphene_std::vector::fill::FillInput::<Graphic>::INDEX)? else {
let NodeInput::Node { node_id, .. } = fill_node.inputs.get(graphene_std::vector::fill::FillInput::INDEX)? else {
return None;
};
Some(*node_id)
@@ -317,7 +317,7 @@ pub fn get_gradient_stops(layer: LayerNodeIdentifier, network_interface: &NodeNe
.document_network()
.nodes
.get(&fill_node_id)
.and_then(|node| node.inputs.get(graphene_std::vector::fill::FillInput::<Graphic>::INDEX))
.and_then(|node| node.inputs.get(graphene_std::vector::fill::FillInput::INDEX))
.and_then(|input| input.as_value())
.and_then(|value| if let TaggedValue::Gradient(gradient) = value { Some(gradient.clone()) } else { None });
}
@@ -363,7 +363,7 @@ pub fn gradient_orientation_rightward(transform: glam::DAffine2) -> bool {
/// Get the current fill of a layer from the closest "Fill" node.
pub fn get_fill_color(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<Color> {
let inputs = NodeGraphLayer::new(layer, network_interface).find_node_inputs(&DefinitionIdentifier::ProtoNode(graphene_std::vector::fill::IDENTIFIER))?;
let &TaggedValue::Color(color) = inputs.get(graphene_std::vector::fill::FillInput::<Graphic>::INDEX)?.as_value()? else {
let &TaggedValue::Color(color) = inputs.get(graphene_std::vector::fill::FillInput::INDEX)?.as_value()? else {
return None;
};
color
@@ -638,7 +638,7 @@ pub struct FillNodeGradient {
pub fn read_fill_node_gradient(fill_node: &DocumentNode, bounding_box: impl FnOnce() -> [DVec2; 2]) -> Option<FillNodeGradient> {
use graphene_std::vector::fill;
let TaggedValue::Gradient(stops) = fill_node.inputs.get(fill::FillInput::<Graphic>::INDEX)?.as_value()? else {
let TaggedValue::Gradient(stops) = fill_node.inputs.get(fill::FillInput::INDEX)?.as_value()? else {
return None;
};
let gradient_type = match fill_node.inputs.get(fill::GradientTypeInput::INDEX).and_then(|input| input.as_value()) {
@@ -665,7 +665,7 @@ pub fn read_fill_node_gradient(fill_node: &DocumentNode, bounding_box: impl FnOn
}
/// Returns the stroke color from a layer's upstream Stroke node.
pub fn get_stroke_color(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<Option<Color>> {
let color_index = graphene_std::vector::stroke::PaintInput::<Graphic>::INDEX;
let color_index = graphene_std::vector::stroke::PaintInput::INDEX;
let tagged = NodeGraphLayer::new(layer, network_interface).find_input(&DefinitionIdentifier::ProtoNode(graphene_std::vector::stroke::IDENTIFIER), color_index)?;
if let TaggedValue::Color(color) = tagged { Some(*color) } else { None }
}
@@ -699,7 +699,7 @@ pub fn selected_fill_state(document: &DocumentMessageHandler) -> Option<Selected
let fill_choice = (|| {
let fill_node = document.network_interface.document_network().nodes.get(&fill_node_id)?;
match fill_node.inputs.get(graphene_std::vector::fill::FillInput::<Graphic>::INDEX)?.as_value()? {
match fill_node.inputs.get(graphene_std::vector::fill::FillInput::INDEX)?.as_value()? {
&TaggedValue::Color(color) => Some(color.map_or(FillChoice::None, FillChoice::Solid)),
TaggedValue::Gradient(stops) => Some(FillChoice::Gradient(stops.clone())),
_ => None,
@@ -825,7 +825,7 @@ pub fn set_stroke_color_for_selected_layers(color: Option<Color>, weight: f64, d
let layers: Vec<_> = document.network_interface.selected_nodes().selected_layers_except_artboards(&document.network_interface).collect();
for layer in layers {
if let Some(node_id) = get_stroke_id(layer, &document.network_interface) {
let input_index = graphene_std::vector::stroke::PaintInput::<Graphic>::INDEX;
let input_index = graphene_std::vector::stroke::PaintInput::INDEX;
let value = TaggedValue::Color(color);
responses.add(NodeGraphMessage::SetInputValue { node_id, input_index, value });
} else {

View File

@@ -2058,7 +2058,7 @@ 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 = match fill_node.inputs.get(fill::FillInput::<Graphic>::INDEX)?.as_value()? {
let stops = match fill_node.inputs.get(fill::FillInput::INDEX)?.as_value()? {
TaggedValue::Gradient(stops) => stops.clone(),
_ => return None,
};
@@ -2176,7 +2176,7 @@ mod test_gradient {
editor
.handle_message(NodeGraphMessage::CreateWire {
output_connector: OutputConnector::node(gradient_node_id, 0),
input_connector: InputConnector::node(fill_node_id, fill::FillInput::<Graphic>::INDEX),
input_connector: InputConnector::node(fill_node_id, fill::FillInput::INDEX),
})
.await;