diff --git a/Cargo.lock b/Cargo.lock index 7c18c5c4e6..f23a90db8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4129,6 +4129,7 @@ dependencies = [ "graph-craft", "graphene-std", "interpreted-executor", + "log", ] [[package]] diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_properties.rs index 1e206d21a0..24328f3539 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -173,6 +173,8 @@ pub(crate) fn property_from_type( Some(x) if x == TypeId::of::() => text_widget(default_info).into(), Some(x) if x == TypeId::of::() => vec2_widget(default_info, "X", "Y", "", None, false), Some(x) if x == TypeId::of::() => transform_widget(default_info, &mut extra_widgets), + Some(x) if x == TypeId::of::() => color_widget(default_info, ColorInput::default()), + Some(x) if x == TypeId::of::>() => color_widget(default_info, ColorInput::default()), // ========================== // PRIMITIVE COLLECTION TYPES // ========================== @@ -926,6 +928,22 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button: // Add the color input match &**tagged_value { + TaggedValue::ColorNotInTable(color) => widgets.push( + color_button + .value(FillChoice::Solid(*color)) + .allow_none(false) + .on_update(update_value(|input: &ColorInput| TaggedValue::ColorNotInTable(input.value.as_solid().unwrap()), node_id, index)) + .on_commit(commit_value) + .widget_holder(), + ), + TaggedValue::OptionalColorNotInTable(color) => widgets.push( + color_button + .value(color.map_or(FillChoice::None, FillChoice::Solid)) + .allow_none(true) + .on_update(update_value(|input: &ColorInput| TaggedValue::OptionalColorNotInTable(input.value.as_solid()), node_id, index)) + .on_commit(commit_value) + .widget_holder(), + ), TaggedValue::Color(color_table) => widgets.push( color_button .value(match color_table.iter().next() { @@ -965,7 +983,7 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button: .on_commit(commit_value) .widget_holder(), ), - _ => {} + x => warn!("Colour {x:?}"), } LayoutGroup::Row { widgets } diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index 6142184ab7..6d404462d5 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -171,6 +171,8 @@ tagged_value! { Bool(bool), String(String), OptionalF64(Option), + ColorNotInTable(Color), + OptionalColorNotInTable(Option), // ======================== // LISTS OF PRIMITIVE TYPES // ======================== @@ -358,6 +360,8 @@ impl TaggedValue { x if x == TypeId::of::() => to_dvec2(string).map(TaggedValue::DVec2)?, x if x == TypeId::of::() => FromStr::from_str(string).map(TaggedValue::Bool).ok()?, x if x == TypeId::of::>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?, + x if x == TypeId::of::() => to_color(string).map(|color| TaggedValue::ColorNotInTable(color))?, + x if x == TypeId::of::>() => TaggedValue::ColorNotInTable(to_color(string)?), x if x == TypeId::of::() => to_color(string).map(|color| TaggedValue::Fill(Fill::solid(color)))?, x if x == TypeId::of::() => to_reference_point(string).map(TaggedValue::ReferencePoint)?, _ => return None, @@ -512,3 +516,8 @@ mod fake_hash { } } } + +#[test] +fn can_construct_color() { + assert_eq!(TaggedValue::from_type(&concrete!(Color)).unwrap(), TaggedValue::ColorNotInTable(Color::default())); +} diff --git a/node-graph/graster-nodes/src/adjustments.rs b/node-graph/graster-nodes/src/adjustments.rs index 76e2fbe502..1274ef5fe4 100644 --- a/node-graph/graster-nodes/src/adjustments.rs +++ b/node-graph/graster-nodes/src/adjustments.rs @@ -307,7 +307,7 @@ fn black_and_white>( GradientStops, )] mut image: T, - #[default(Color::BLACK)] tint: Table, + #[default(Color::BLACK)] tint: Color, #[default(40.)] #[range((-200., 300.))] reds: PercentageF32, @@ -327,9 +327,6 @@ fn black_and_white>( #[range((-200., 300.))] magentas: PercentageF32, ) -> T { - let tint: Option = tint.into(); - let tint = tint.unwrap_or(Color::BLACK); - image.adjust(|color| { let color = color.to_gamma_srgb(); diff --git a/node-graph/graster-nodes/src/blending_nodes.rs b/node-graph/graster-nodes/src/blending_nodes.rs index ff94a595e9..6efc335fbb 100644 --- a/node-graph/graster-nodes/src/blending_nodes.rs +++ b/node-graph/graster-nodes/src/blending_nodes.rs @@ -166,15 +166,12 @@ fn color_overlay>( GradientStops, )] mut image: T, - #[default(Color::BLACK)] color: Table, + #[default(Color::BLACK)] color: Color, blend_mode: BlendMode, #[default(100.)] opacity: PercentageF32, ) -> T { let opacity = (opacity as f32 / 100.).clamp(0., 1.); - let color: Option = color.into(); - let color = color.unwrap_or(Color::BLACK); - image.adjust(|pixel| { let image = pixel.map_rgb(|channel| channel * (1. - opacity)); @@ -206,13 +203,7 @@ mod test { // 100% of the output should come from the multiplied value let opacity = 100.; - let result = super::color_overlay( - (), - Table::new_from_element(Raster::new_cpu(image.clone())), - Table::new_from_element(overlay_color), - BlendMode::Multiply, - opacity, - ); + let result = super::color_overlay((), Table::new_from_element(Raster::new_cpu(image.clone())), overlay_color, BlendMode::Multiply, opacity); let result = result.iter().next().unwrap().element; // The output should just be the original green and alpha channels (as we multiply them by 1 and other channels by 0) diff --git a/node-graph/gstd/src/text.rs b/node-graph/gstd/src/text.rs index ae9c684628..d1a094cc73 100644 --- a/node-graph/gstd/src/text.rs +++ b/node-graph/gstd/src/text.rs @@ -17,12 +17,8 @@ fn text<'i: 'n>( #[unit(" px")] #[default(0.)] character_spacing: f64, - #[unit(" px")] - #[default(None)] - max_width: Option, - #[unit(" px")] - #[default(None)] - max_height: Option, + #[unit(" px")] max_width: Option, + #[unit(" px")] max_height: Option, /// Faux italic. #[unit("°")] #[default(0.)] diff --git a/node-graph/preprocessor/Cargo.toml b/node-graph/preprocessor/Cargo.toml index e39fef365c..08d03c8524 100644 --- a/node-graph/preprocessor/Cargo.toml +++ b/node-graph/preprocessor/Cargo.toml @@ -7,6 +7,7 @@ license = "MIT OR Apache-2.0" [features] [dependencies] +log = { workspace = true } # Workspace dependencies graphene-std = { workspace = true, features = ["gpu"] } diff --git a/node-graph/preprocessor/src/lib.rs b/node-graph/preprocessor/src/lib.rs index 7b5681e206..b440f570d9 100644 --- a/node-graph/preprocessor/src/lib.rs +++ b/node-graph/preprocessor/src/lib.rs @@ -1,3 +1,6 @@ +#[macro_use] +extern crate log; + use graph_craft::document::value::*; use graph_craft::document::*; use graph_craft::proto::RegistryValueSource; @@ -150,7 +153,14 @@ pub fn node_inputs(fields: &[registry::FieldMetadata], first_node_io: &NodeIOTyp match field.value_source { RegistryValueSource::None => {} - RegistryValueSource::Default(data) => return NodeInput::value(TaggedValue::from_primitive_string(data, ty).unwrap_or(TaggedValue::None), exposed), + RegistryValueSource::Default(data) => { + if let Some(custom_default) = TaggedValue::from_primitive_string(data, ty) { + return NodeInput::value(custom_default, exposed); + } else { + // It is incredibly useful to get a warning when the default type cannot be parsed rather than defaulting to `()`. + warn!("Failed to parse default value for type {ty:?} with data {data}"); + } + } RegistryValueSource::Scope(data) => return NodeInput::scope(Cow::Borrowed(data)), };