Replace all hard-coded magic number node input indices with *Input::INDEX constants

This commit is contained in:
Keavon Chambers 2025-06-22 23:18:34 -07:00
parent 930278128d
commit ae88f4a3de
3 changed files with 157 additions and 134 deletions

View file

@ -567,7 +567,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(DocumentMessage::AddTransaction);
let new_ids: HashMap<_, _> = data.iter().map(|(id, _)| (*id, NodeId::new())).collect();
let nodes: Vec<_> = new_ids.iter().map(|(_, id)| *id).collect();
let nodes: Vec<_> = new_ids.values().copied().collect();
responses.add(NodeGraphMessage::AddNodes {
nodes: data,
new_ids: new_ids.clone(),

View file

@ -22,7 +22,6 @@ use graphene_std::raster_types::{CPU, GPU, RasterDataTable};
use graphene_std::text::Font;
use graphene_std::transform::{Footprint, ReferencePoint};
use graphene_std::vector::VectorDataTable;
use graphene_std::vector::generator_nodes::grid;
use graphene_std::vector::misc::CentroidType;
use graphene_std::vector::misc::{ArcType, MergeByDistanceAlgorithm};
use graphene_std::vector::misc::{BooleanOperation, GridType};
@ -939,8 +938,7 @@ pub fn get_document_node<'a>(node_id: NodeId, context: &'a NodePropertiesContext
}
pub fn query_node_and_input_info<'a>(node_id: NodeId, input_index: usize, context: &'a NodePropertiesContext<'a>) -> Result<(&'a DocumentNode, &'a str, &'a str), String> {
let node_id2 = node_id.clone();
let document_node = get_document_node(node_id2, context)?;
let document_node = get_document_node(node_id, context)?;
let input_name = context.network_interface.input_name(node_id, input_index, context.selection_network_path).unwrap_or_else(|| {
log::warn!("input name not found in query_node_and_input_info");
""
@ -982,16 +980,19 @@ pub fn query_noise_pattern_state(node_id: NodeId, context: &NodePropertiesContex
}
pub fn query_assign_colors_randomize(node_id: NodeId, context: &NodePropertiesContext) -> Result<bool, String> {
use graphene_std::vector::assign_colors::*;
let document_node = get_document_node(node_id, context)?;
// This is safe since the node is a proto node and the implementation cannot be changed.
let randomize_index = 5;
Ok(match document_node.inputs.get(randomize_index).and_then(|input| input.as_value()) {
Ok(match document_node.inputs.get(RandomizeInput::INDEX).and_then(|input| input.as_value()) {
Some(TaggedValue::Bool(randomize_enabled)) => *randomize_enabled,
_ => false,
})
}
pub(crate) fn brightness_contrast_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::raster::brightness_contrast::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1001,17 +1002,18 @@ pub(crate) fn brightness_contrast_properties(node_id: NodeId, context: &mut Node
};
// Use Classic
let use_classic_index = 3;
let use_classic = bool_widget(ParameterWidgetsInfo::from_index(document_node, node_id, use_classic_index, true, context), CheckboxInput::default());
let use_classic_value = match document_node.inputs[use_classic_index].as_value() {
let use_classic = bool_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, UseClassicInput::INDEX, true, context),
CheckboxInput::default(),
);
let use_classic_value = match document_node.inputs[UseClassicInput::INDEX].as_value() {
Some(TaggedValue::Bool(use_classic_choice)) => *use_classic_choice,
_ => false,
};
// Brightness
let brightness_index = 1;
let brightness = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, brightness_index, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, BrightnessInput::INDEX, true, context),
NumberInput::default()
.unit("%")
.mode_range()
@ -1021,9 +1023,8 @@ pub(crate) fn brightness_contrast_properties(node_id: NodeId, context: &mut Node
);
// Contrast
let contrast_index = 2;
let contrast = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, contrast_index, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, ContrastInput::INDEX, true, context),
NumberInput::default()
.unit("%")
.mode_range()
@ -1042,6 +1043,8 @@ pub(crate) fn brightness_contrast_properties(node_id: NodeId, context: &mut Node
}
pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::raster::channel_mixer::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1051,20 +1054,21 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper
};
// Monochrome
let monochrome_index = 1;
let is_monochrome = bool_widget(ParameterWidgetsInfo::from_index(document_node, node_id, monochrome_index, true, context), CheckboxInput::default());
let is_monochrome_value = match document_node.inputs[monochrome_index].as_value() {
let is_monochrome = bool_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, MonochromeInput::INDEX, true, context),
CheckboxInput::default(),
);
let is_monochrome_value = match document_node.inputs[MonochromeInput::INDEX].as_value() {
Some(TaggedValue::Bool(monochrome_choice)) => *monochrome_choice,
_ => false,
};
// Output channel choice
let output_channel_index = 18;
let output_channel = enum_choice::<RedGreenBlue>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, output_channel_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, OutputChannelInput::INDEX, true, context))
.exposable(false)
.property_row();
let output_channel_value = match &document_node.inputs[output_channel_index].as_value() {
let output_channel_value = match &document_node.inputs[OutputChannelInput::INDEX].as_value() {
Some(TaggedValue::RedGreenBlue(choice)) => choice,
_ => {
warn!("Channel Mixer node properties panel could not be displayed.");
@ -1074,10 +1078,10 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper
// Output Channel modes
let (red_output_index, green_output_index, blue_output_index, constant_output_index) = match (is_monochrome_value, output_channel_value) {
(true, _) => (2, 3, 4, 5),
(false, RedGreenBlue::Red) => (6, 7, 8, 9),
(false, RedGreenBlue::Green) => (10, 11, 12, 13),
(false, RedGreenBlue::Blue) => (14, 15, 16, 17),
(true, _) => (MonochromeRInput::INDEX, MonochromeGInput::INDEX, MonochromeBInput::INDEX, MonochromeCInput::INDEX),
(false, RedGreenBlue::Red) => (RedRInput::INDEX, RedGInput::INDEX, RedBInput::INDEX, RedCInput::INDEX),
(false, RedGreenBlue::Green) => (GreenRInput::INDEX, GreenGInput::INDEX, GreenBInput::INDEX, GreenCInput::INDEX),
(false, RedGreenBlue::Blue) => (BlueRInput::INDEX, BlueGInput::INDEX, BlueBInput::INDEX, BlueCInput::INDEX),
};
let number_input = NumberInput::default().mode_range().min(-200.).max(200.).unit("%");
let red = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, red_output_index, true, context), number_input.clone());
@ -1102,6 +1106,8 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper
}
pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::raster::selective_color::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1109,15 +1115,14 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp
return Vec::new();
}
};
// Colors choice
let colors_index = 38;
// Colors choice
let colors = enum_choice::<SelectiveColorChoice>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, colors_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, ColorsInput::INDEX, true, context))
.exposable(false)
.property_row();
let colors_choice_index = match &document_node.inputs[colors_index].as_value() {
let colors_choice = match &document_node.inputs[ColorsInput::INDEX].as_value() {
Some(TaggedValue::SelectiveColorChoice(choice)) => choice,
_ => {
warn!("Selective Color node properties panel could not be displayed.");
@ -1126,16 +1131,16 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp
};
// CMYK
let (c_index, m_index, y_index, k_index) = match colors_choice_index {
SelectiveColorChoice::Reds => (2, 3, 4, 5),
SelectiveColorChoice::Yellows => (6, 7, 8, 9),
SelectiveColorChoice::Greens => (10, 11, 12, 13),
SelectiveColorChoice::Cyans => (14, 15, 16, 17),
SelectiveColorChoice::Blues => (18, 19, 20, 21),
SelectiveColorChoice::Magentas => (22, 23, 24, 25),
SelectiveColorChoice::Whites => (26, 27, 28, 29),
SelectiveColorChoice::Neutrals => (30, 31, 32, 33),
SelectiveColorChoice::Blacks => (34, 35, 36, 37),
let (c_index, m_index, y_index, k_index) = match colors_choice {
SelectiveColorChoice::Reds => (RCInput::INDEX, RMInput::INDEX, RYInput::INDEX, RKInput::INDEX),
SelectiveColorChoice::Yellows => (YCInput::INDEX, YMInput::INDEX, YYInput::INDEX, YKInput::INDEX),
SelectiveColorChoice::Greens => (GCInput::INDEX, GMInput::INDEX, GYInput::INDEX, GKInput::INDEX),
SelectiveColorChoice::Cyans => (CCInput::INDEX, CMInput::INDEX, CYInput::INDEX, CKInput::INDEX),
SelectiveColorChoice::Blues => (BCInput::INDEX, BMInput::INDEX, BYInput::INDEX, BKInput::INDEX),
SelectiveColorChoice::Magentas => (MCInput::INDEX, MMInput::INDEX, MYInput::INDEX, MKInput::INDEX),
SelectiveColorChoice::Whites => (WCInput::INDEX, WMInput::INDEX, WYInput::INDEX, WKInput::INDEX),
SelectiveColorChoice::Neutrals => (NCInput::INDEX, NMInput::INDEX, NYInput::INDEX, NKInput::INDEX),
SelectiveColorChoice::Blacks => (KCInput::INDEX, KMInput::INDEX, KYInput::INDEX, KKInput::INDEX),
};
let number_input = NumberInput::default().mode_range().min(-100.).max(100.).unit("%");
let cyan = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, c_index, true, context), number_input.clone());
@ -1144,9 +1149,8 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp
let black = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, k_index, true, context), number_input);
// Mode
let mode_index = 1;
let mode = enum_choice::<RelativeAbsolute>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, mode_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, ModeInput::INDEX, true, context))
.property_row();
vec![
@ -1163,11 +1167,7 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp
}
pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let grid_type_index = grid::GridTypeInput::INDEX;
let spacing_index = grid::SpacingInput::<f64>::INDEX;
let angles_index = grid::AnglesInput::INDEX;
let rows_index = grid::RowsInput::INDEX;
let columns_index = grid::ColumnsInput::INDEX;
use graphene_std::vector::generator_nodes::grid::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
@ -1177,36 +1177,48 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte
}
};
let grid_type = enum_choice::<GridType>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, grid_type_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, GridTypeInput::INDEX, true, context))
.property_row();
let mut widgets = vec![grid_type];
let Some(grid_type_input) = document_node.inputs.get(grid_type_index) else {
let Some(grid_type_input) = document_node.inputs.get(GridTypeInput::INDEX) else {
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::GridType(grid_type)) = grid_type_input.as_non_exposed_value() {
match grid_type {
GridType::Rectangular => {
let spacing = coordinate_widget(ParameterWidgetsInfo::from_index(document_node, node_id, spacing_index, true, context), "W", "H", " px", Some(0.));
let spacing = coordinate_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, SpacingInput::<f64>::INDEX, true, context),
"W",
"H",
" px",
Some(0.),
);
widgets.push(spacing);
}
GridType::Isometric => {
let spacing = LayoutGroup::Row {
widgets: number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, spacing_index, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, SpacingInput::<f64>::INDEX, true, context),
NumberInput::default().label("H").min(0.).unit(" px"),
),
};
let angles = coordinate_widget(ParameterWidgetsInfo::from_index(document_node, node_id, angles_index, true, context), "", "", "°", None);
let angles = coordinate_widget(ParameterWidgetsInfo::from_index(document_node, node_id, AnglesInput::INDEX, true, context), "", "", "°", None);
widgets.extend([spacing, angles]);
}
}
}
let rows = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, rows_index, true, context), NumberInput::default().min(1.));
let columns = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, columns_index, true, context), NumberInput::default().min(1.));
let rows = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, RowsInput::INDEX, true, context),
NumberInput::default().min(1.),
);
let columns = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, ColumnsInput::INDEX, true, context),
NumberInput::default().min(1.),
);
widgets.extend([LayoutGroup::Row { widgets: rows }, LayoutGroup::Row { widgets: columns }]);
@ -1214,6 +1226,8 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte
}
pub(crate) fn exposure_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::raster::exposure::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1221,10 +1235,16 @@ pub(crate) fn exposure_properties(node_id: NodeId, context: &mut NodePropertiesC
return Vec::new();
}
};
let exposure = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, 1, true, context), NumberInput::default().min(-20.).max(20.));
let offset = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, 2, true, context), NumberInput::default().min(-0.5).max(0.5));
let exposure = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, ExposureInput::INDEX, true, context),
NumberInput::default().min(-20.).max(20.),
);
let offset = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, OffsetInput::INDEX, true, context),
NumberInput::default().min(-0.5).max(0.5),
);
let gamma_correction = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, 3, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, GammaCorrectionInput::INDEX, true, context),
NumberInput::default().min(0.01).max(9.99).increment_step(0.1),
);
@ -1236,6 +1256,8 @@ pub(crate) fn exposure_properties(node_id: NodeId, context: &mut NodePropertiesC
}
pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::vector::generator_nodes::rectangle::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1243,21 +1265,15 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
return Vec::new();
}
};
let size_x_index = 1;
let size_y_index = 2;
let corner_rounding_type_index = 3;
let corner_radius_index = 4;
let clamped_index = 5;
// Size X
let size_x = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, size_x_index, true, context), NumberInput::default());
let size_x = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, WidthInput::INDEX, true, context), NumberInput::default());
// Size Y
let size_y = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, size_y_index, true, context), NumberInput::default());
let size_y = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, HeightInput::INDEX, true, context), NumberInput::default());
// Corner Radius
let mut corner_radius_row_1 = start_widgets(
ParameterWidgetsInfo::from_index(document_node, node_id, corner_radius_index, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, CornerRadiusInput::<f64>::INDEX, true, context),
FrontendGraphDataType::Number,
);
corner_radius_row_1.push(Separator::new(SeparatorType::Unrelated).widget_holder());
@ -1266,13 +1282,13 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
corner_radius_row_2.push(TextLabel::new("").widget_holder());
add_blank_assist(&mut corner_radius_row_2);
let Some(input) = document_node.inputs.get(corner_rounding_type_index) else {
let Some(input) = document_node.inputs.get(IndividualCornerRadiiInput::INDEX) else {
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
if let Some(&TaggedValue::Bool(is_individual)) = input.as_non_exposed_value() {
// Values
let Some(input) = document_node.inputs.get(corner_radius_index) else {
let Some(input) = document_node.inputs.get(CornerRadiusInput::<f64>::INDEX) else {
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
@ -1294,13 +1310,13 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
Message::Batched(Box::new([
NodeGraphMessage::SetInputValue {
node_id,
input_index: corner_rounding_type_index,
input_index: IndividualCornerRadiiInput::INDEX,
value: TaggedValue::Bool(false),
}
.into(),
NodeGraphMessage::SetInputValue {
node_id,
input_index: corner_radius_index,
input_index: CornerRadiusInput::<f64>::INDEX,
value: TaggedValue::F64(uniform_val),
}
.into(),
@ -1313,13 +1329,13 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
Message::Batched(Box::new([
NodeGraphMessage::SetInputValue {
node_id,
input_index: corner_rounding_type_index,
input_index: IndividualCornerRadiiInput::INDEX,
value: TaggedValue::Bool(true),
}
.into(),
NodeGraphMessage::SetInputValue {
node_id,
input_index: corner_radius_index,
input_index: CornerRadiusInput::<f64>::INDEX,
value: TaggedValue::F64Array4(individual_val),
}
.into(),
@ -1346,12 +1362,12 @@ 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, corner_radius_index))
.on_update(optionally_update_value(move |x: &TextInput| from_string(&x.value), node_id, CornerRadiusInput::<f64>::INDEX))
.widget_holder()
} else {
NumberInput::default()
.value(Some(uniform_val))
.on_update(update_value(move |x: &NumberInput| TaggedValue::F64(x.value.unwrap()), node_id, corner_radius_index))
.on_update(update_value(move |x: &NumberInput| TaggedValue::F64(x.value.unwrap()), node_id, CornerRadiusInput::<f64>::INDEX))
.on_commit(commit_value)
.widget_holder()
};
@ -1359,7 +1375,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
}
// Clamped
let clamped = bool_widget(ParameterWidgetsInfo::from_index(document_node, node_id, clamped_index, true, context), CheckboxInput::default());
let clamped = bool_widget(ParameterWidgetsInfo::from_index(document_node, node_id, ClampedInput::INDEX, true, context), CheckboxInput::default());
vec![
LayoutGroup::Row { widgets: size_x },
@ -1486,6 +1502,8 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper
/// Fill Node Widgets LayoutGroup
pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::vector::fill::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1493,16 +1511,16 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
return Vec::new();
}
};
let fill_index = 1;
let backup_color_index = 2;
let backup_gradient_index = 3;
let mut widgets_first_row = start_widgets(ParameterWidgetsInfo::from_index(document_node, node_id, fill_index, true, context), FrontendGraphDataType::General);
let mut widgets_first_row = start_widgets(
ParameterWidgetsInfo::from_index(document_node, node_id, FillInput::<Color>::INDEX, true, context),
FrontendGraphDataType::General,
);
let (fill, backup_color, backup_gradient) = if let (Some(TaggedValue::Fill(fill)), &Some(&TaggedValue::OptionalColor(backup_color)), Some(TaggedValue::Gradient(backup_gradient))) = (
&document_node.inputs[fill_index].as_value(),
&document_node.inputs[backup_color_index].as_value(),
&document_node.inputs[backup_gradient_index].as_value(),
&document_node.inputs[FillInput::<Color>::INDEX].as_value(),
&document_node.inputs[BackupColorInput::INDEX].as_value(),
&document_node.inputs[BackupGradientInput::INDEX].as_value(),
) {
(fill, backup_color, backup_gradient)
} else {
@ -1521,26 +1539,26 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
match &fill2 {
Fill::None => NodeGraphMessage::SetInputValue {
node_id,
input_index: backup_color_index,
input_index: BackupColorInput::INDEX,
value: TaggedValue::OptionalColor(None),
}
.into(),
Fill::Solid(color) => NodeGraphMessage::SetInputValue {
node_id,
input_index: backup_color_index,
input_index: BackupColorInput::INDEX,
value: TaggedValue::OptionalColor(Some(*color)),
}
.into(),
Fill::Gradient(gradient) => NodeGraphMessage::SetInputValue {
node_id,
input_index: backup_gradient_index,
input_index: BackupGradientInput::INDEX,
value: TaggedValue::Gradient(gradient.clone()),
}
.into(),
},
NodeGraphMessage::SetInputValue {
node_id,
input_index: fill_index,
input_index: FillInput::<Color>::INDEX,
value: TaggedValue::Fill(x.value.to_fill(fill2.as_gradient())),
}
.into(),
@ -1568,7 +1586,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
}
},
node_id,
fill_index,
FillInput::<Color>::INDEX,
))
.widget_holder();
row.push(Separator::new(SeparatorType::Unrelated).widget_holder());
@ -1579,11 +1597,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::Fill(backup_color_fill.clone()), node_id, fill_index))
.on_update(update_value(move |_| TaggedValue::Fill(backup_color_fill.clone()), node_id, FillInput::<Color>::INDEX))
.on_commit(commit_value),
RadioEntryData::new("gradient")
.label("Gradient")
.on_update(update_value(move |_| TaggedValue::Fill(backup_gradient_fill.clone()), node_id, fill_index))
.on_update(update_value(move |_| TaggedValue::Fill(backup_gradient_fill.clone()), node_id, FillInput::<Color>::INDEX))
.on_commit(commit_value),
];
@ -1618,7 +1636,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
}
},
node_id,
fill_index,
FillInput::<Color>::INDEX,
))
.widget_holder();
row.push(Separator::new(SeparatorType::Unrelated).widget_holder());
@ -1639,7 +1657,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
TaggedValue::Fill(Fill::Gradient(new_gradient))
},
node_id,
fill_index,
FillInput::<Color>::INDEX,
))
.on_commit(commit_value),
RadioEntryData::new("Radial")
@ -1651,7 +1669,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
TaggedValue::Fill(Fill::Gradient(new_gradient))
},
node_id,
fill_index,
FillInput::<Color>::INDEX,
))
.on_commit(commit_value),
];
@ -1668,6 +1686,8 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
}
pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::vector::stroke::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1675,34 +1695,28 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
return Vec::new();
}
};
let color_index = graphene_std::vector::stroke::ColorInput::<Option<Color>>::INDEX;
let weight_index = graphene_std::vector::stroke::WeightInput::INDEX;
let align_index = graphene_std::vector::stroke::AlignInput::INDEX;
let cap_index = graphene_std::vector::stroke::CapInput::INDEX;
let join_index = graphene_std::vector::stroke::JoinInput::INDEX;
let miter_limit_index = graphene_std::vector::stroke::MiterLimitInput::INDEX;
let paint_order_index = graphene_std::vector::stroke::PaintOrderInput::INDEX;
let dash_lengths_index = graphene_std::vector::stroke::DashLengthsInput::INDEX;
let dash_offset_index = graphene_std::vector::stroke::DashOffsetInput::INDEX;
let color = color_widget(ParameterWidgetsInfo::from_index(document_node, node_id, color_index, true, context), ColorInput::default());
let color = color_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, ColorInput::<Option<Color>>::INDEX, true, context),
crate::messages::layout::utility_types::widgets::button_widgets::ColorInput::default(),
);
let weight = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, weight_index, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, WeightInput::INDEX, true, context),
NumberInput::default().unit(" px").min(0.),
);
let align = enum_choice::<StrokeAlign>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, align_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, AlignInput::INDEX, true, context))
.property_row();
let cap = enum_choice::<StrokeCap>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, cap_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, CapInput::INDEX, true, context))
.property_row();
let join = enum_choice::<StrokeJoin>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, join_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, JoinInput::INDEX, true, context))
.property_row();
let miter_limit = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, miter_limit_index, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, MiterLimitInput::INDEX, true, context),
NumberInput::default().min(0.).disabled({
let join_value = match &document_node.inputs[join_index].as_value() {
let join_value = match &document_node.inputs[JoinInput::INDEX].as_value() {
Some(TaggedValue::StrokeJoin(x)) => x,
_ => &StrokeJoin::Miter,
};
@ -1710,18 +1724,18 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
}),
);
let paint_order = enum_choice::<PaintOrder>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, paint_order_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, PaintOrderInput::INDEX, true, context))
.property_row();
let dash_lengths_val = match &document_node.inputs[dash_lengths_index].as_value() {
let dash_lengths_val = match &document_node.inputs[DashLengthsInput::INDEX].as_value() {
Some(TaggedValue::VecF64(x)) => x,
_ => &vec![],
};
let dash_lengths = array_of_number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, dash_lengths_index, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, DashLengthsInput::INDEX, true, context),
TextInput::default().centered(true),
);
let number_input = NumberInput::default().unit(" px").disabled(dash_lengths_val.is_empty());
let dash_offset = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, dash_offset_index, true, context), number_input);
let dash_offset = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, DashOffsetInput::INDEX, true, context), number_input);
vec![
color,
@ -1737,6 +1751,8 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
}
pub fn offset_path_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::vector::offset_path::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1744,30 +1760,28 @@ pub fn offset_path_properties(node_id: NodeId, context: &mut NodePropertiesConte
return Vec::new();
}
};
let distance_index = graphene_std::vector::offset_path::DistanceInput::INDEX;
let join_index = graphene_std::vector::offset_path::JoinInput::INDEX;
let miter_limit_index = graphene_std::vector::offset_path::MiterLimitInput::INDEX;
let number_input = NumberInput::default().unit(" px");
let distance = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, distance_index, true, context), number_input);
let distance = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, DistanceInput::INDEX, true, context), number_input);
let join = enum_choice::<StrokeJoin>()
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, join_index, true, context))
.for_socket(ParameterWidgetsInfo::from_index(document_node, node_id, JoinInput::INDEX, true, context))
.property_row();
let number_input = NumberInput::default().min(0.).disabled({
let join_val = match &document_node.inputs[join_index].as_value() {
let join_val = match &document_node.inputs[JoinInput::INDEX].as_value() {
Some(TaggedValue::StrokeJoin(x)) => x,
_ => &StrokeJoin::Miter,
};
join_val != &StrokeJoin::Miter
});
let miter_limit = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, miter_limit_index, true, context), number_input);
let miter_limit = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, MiterLimitInput::INDEX, true, context), number_input);
vec![LayoutGroup::Row { widgets: distance }, join, LayoutGroup::Row { widgets: miter_limit }]
}
pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
use graphene_std::ops::math::*;
let document_node = match get_document_node(node_id, context) {
Ok(document_node) => document_node,
Err(err) => {
@ -1776,16 +1790,13 @@ pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) ->
}
};
let expression_index = 1;
let operation_b_index = 2;
let expression = (|| {
let mut widgets = start_widgets(
ParameterWidgetsInfo::from_index(document_node, node_id, expression_index, true, context),
ParameterWidgetsInfo::from_index(document_node, node_id, ExpressionInput::INDEX, true, context),
FrontendGraphDataType::General,
);
let Some(input) = document_node.inputs.get(expression_index) else {
let Some(input) = document_node.inputs.get(ExpressionInput::INDEX) else {
log::warn!("A widget failed to be built because its node's input index is invalid.");
return vec![];
};
@ -1809,7 +1820,7 @@ pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) ->
})
},
node_id,
expression_index,
ExpressionInput::INDEX,
))
.on_commit(commit_value)
.widget_holder(),
@ -1817,7 +1828,10 @@ pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) ->
}
widgets
})();
let operand_b = number_widget(ParameterWidgetsInfo::from_index(document_node, node_id, operation_b_index, true, context), NumberInput::default());
let operand_b = number_widget(
ParameterWidgetsInfo::from_index(document_node, node_id, OperandBInput::<f64>::INDEX, true, context),
NumberInput::default(),
);
let operand_a_hint = vec![TextLabel::new("(Operand A is the primary input)").widget_holder()];
vec![
@ -1925,17 +1939,16 @@ pub mod choice {
C: Fn(&()) -> Message + 'static + Send + Sync,
{
let items = E::list()
.into_iter()
.iter()
.map(|group| {
group
.into_iter()
.iter()
.map(|(item, metadata)| {
let item = item.clone();
let updater = updater_factory();
let committer = committer_factory();
MenuListEntry::new(metadata.name.as_ref())
.label(metadata.label.as_ref())
.on_update(move |_| updater(&item))
.on_update(move |_| updater(item))
.on_commit(committer)
})
.collect()
@ -1950,14 +1963,12 @@ pub mod choice {
C: Fn(&()) -> Message + 'static + Send + Sync,
{
let items = E::list()
.into_iter()
.map(|group| group.into_iter())
.flatten()
.iter()
.flat_map(|group| group.iter())
.map(|(item, var_meta)| {
let item = item.clone();
let updater = updater_factory();
let committer = committer_factory();
let entry = RadioEntryData::new(var_meta.name.as_ref()).on_update(move |_| updater(&item)).on_commit(committer);
let entry = RadioEntryData::new(var_meta.name.as_ref()).on_update(move |_| updater(item)).on_commit(committer);
match (var_meta.icon.as_deref(), var_meta.docstring.as_deref()) {
(None, None) => entry.label(var_meta.label.as_ref()),
(None, Some(doc)) => entry.label(var_meta.label.as_ref()).tooltip(doc),
@ -2027,7 +2038,7 @@ pub mod choice {
return LayoutGroup::Row { widgets: vec![] };
};
let input: Option<W::Value> = input.as_non_exposed_value().and_then(|v| <&W::Value as TryFrom<&TaggedValue>>::try_from(v).ok()).map(Clone::clone);
let input: Option<W::Value> = input.as_non_exposed_value().and_then(|v| <&W::Value as TryFrom<&TaggedValue>>::try_from(v).ok()).cloned();
if let Some(current) = input {
let committer = || super::commit_value;

View file

@ -1021,6 +1021,7 @@ async fn channel_mixer<T: Adjust<Color>>(
mut image: T,
monochrome: bool,
#[default(40.)]
#[name("Red")]
monochrome_r: f64,
@ -1144,43 +1145,54 @@ async fn selective_color<T: Adjust<Color>>(
GradientStops,
)]
mut image: T,
mode: RelativeAbsolute,
#[name("(Reds) Cyan")] r_c: f64,
#[name("(Reds) Magenta")] r_m: f64,
#[name("(Reds) Yellow")] r_y: f64,
#[name("(Reds) Black")] r_k: f64,
#[name("(Yellows) Cyan")] y_c: f64,
#[name("(Yellows) Magenta")] y_m: f64,
#[name("(Yellows) Yellow")] y_y: f64,
#[name("(Yellows) Black")] y_k: f64,
#[name("(Greens) Cyan")] g_c: f64,
#[name("(Greens) Magenta")] g_m: f64,
#[name("(Greens) Yellow")] g_y: f64,
#[name("(Greens) Black")] g_k: f64,
#[name("(Cyans) Cyan")] c_c: f64,
#[name("(Cyans) Magenta")] c_m: f64,
#[name("(Cyans) Yellow")] c_y: f64,
#[name("(Cyans) Black")] c_k: f64,
#[name("(Blues) Cyan")] b_c: f64,
#[name("(Blues) Magenta")] b_m: f64,
#[name("(Blues) Yellow")] b_y: f64,
#[name("(Blues) Black")] b_k: f64,
#[name("(Magentas) Cyan")] m_c: f64,
#[name("(Magentas) Magenta")] m_m: f64,
#[name("(Magentas) Yellow")] m_y: f64,
#[name("(Magentas) Black")] m_k: f64,
#[name("(Whites) Cyan")] w_c: f64,
#[name("(Whites) Magenta")] w_m: f64,
#[name("(Whites) Yellow")] w_y: f64,
#[name("(Whites) Black")] w_k: f64,
#[name("(Neutrals) Cyan")] n_c: f64,
#[name("(Neutrals) Magenta")] n_m: f64,
#[name("(Neutrals) Yellow")] n_y: f64,
#[name("(Neutrals) Black")] n_k: f64,
#[name("(Blacks) Cyan")] k_c: f64,
#[name("(Blacks) Magenta")] k_m: f64,
#[name("(Blacks) Yellow")] k_y: f64,
#[name("(Blacks) Black")] k_k: f64,
_colors: SelectiveColorChoice,
) -> T {
image.adjust(|color| {