diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index cfaa6d45..2df662c8 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -167,7 +167,6 @@ impl Dispatcher { // Send the information for tooltips and categories for each node/input. queue.add(FrontendMessage::SendUIMetadata { - input_type_descriptions: Vec::new(), node_descriptions: document_node_definitions::collect_node_descriptions(), node_types: document_node_definitions::collect_node_types(), }); diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index d5988bbf..8f98bfe1 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -44,8 +44,6 @@ pub enum FrontendMessage { // Send prefix: Send global, static data to the frontend that is never updated SendUIMetadata { - #[serde(rename = "inputTypeDescriptions")] - input_type_descriptions: Vec<(String, String)>, #[serde(rename = "nodeDescriptions")] node_descriptions: Vec<(String, String)>, #[serde(rename = "nodeTypes")] diff --git a/editor/src/messages/layout/utility_types/layout_widget.rs b/editor/src/messages/layout/utility_types/layout_widget.rs index b1d9550b..6ebf1020 100644 --- a/editor/src/messages/layout/utility_types/layout_widget.rs +++ b/editor/src/messages/layout/utility_types/layout_widget.rs @@ -325,7 +325,14 @@ pub enum LayoutGroup { }, // TODO: Move this from being a child of `enum LayoutGroup` to being a child of `enum Layout` #[serde(rename = "section")] - Section { name: String, visible: bool, pinned: bool, id: u64, layout: SubLayout }, + Section { + name: String, + description: String, + visible: bool, + pinned: bool, + id: u64, + layout: SubLayout, + }, } impl Default for LayoutGroup { @@ -402,6 +409,7 @@ impl LayoutGroup { ( Self::Section { name: current_name, + description: current_description, visible: current_visible, pinned: current_pinned, id: current_id, @@ -409,6 +417,7 @@ impl LayoutGroup { }, Self::Section { name: new_name, + description: new_description, visible: new_visible, pinned: new_pinned, id: new_id, @@ -417,9 +426,16 @@ impl LayoutGroup { ) => { // Resend the entire panel if the lengths, names, visibility, or node IDs are different // TODO: Diff insersion and deletion of items - if current_layout.len() != new_layout.len() || *current_name != new_name || *current_visible != new_visible || *current_pinned != new_pinned || *current_id != new_id { + if current_layout.len() != new_layout.len() + || *current_name != new_name + || *current_description != new_description + || *current_visible != new_visible + || *current_pinned != new_pinned + || *current_id != new_id + { // Update self to reflect new changes current_name.clone_from(&new_name); + current_description.clone_from(&new_description); *current_visible = new_visible; *current_pinned = new_pinned; *current_id = new_id; @@ -428,6 +444,7 @@ impl LayoutGroup { // Push an update layout group to the diff let new_value = DiffUpdate::LayoutGroup(Self::Section { name: new_name, + description: new_description, visible: new_visible, pinned: new_pinned, id: new_id, diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 8b1997c9..b03787f6 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -353,7 +353,7 @@ impl MessageHandler> for DocumentMessag } let Some(bounds) = self.metadata().bounding_box_document(layer) else { continue }; - let name = self.network_interface.frontend_display_name(&layer.to_node(), &[]); + let name = self.network_interface.display_name(&layer.to_node(), &[]); let transform = self.metadata().document_to_viewport * DAffine2::from_translation(bounds[0].min(bounds[1])) diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs index 645b66a1..460702c4 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs @@ -240,7 +240,7 @@ impl MessageHandler> for Gr responses.add(NodeGraphMessage::SetDisplayName { node_id, - alias: network_interface.frontend_display_name(&artboard.to_node(), &[]), + alias: network_interface.display_name(&artboard.to_node(), &[]), skip_adding_history_step: true, }); diff --git a/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs b/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs index dd49e4ec..72653119 100644 --- a/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs +++ b/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs @@ -120,7 +120,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into()], + input_properties: vec![("In", "TODO").into()], output_names: vec!["Out".to_string()], ..Default::default() }, @@ -141,7 +141,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into()], + input_properties: vec![("In", "TODO").into()], output_names: vec!["Out".to_string()], ..Default::default() }, @@ -203,7 +203,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Graphical Data".into(), "Over".into()], + input_properties: vec![("Graphical Data", "TODO").into(), ("Over", "TODO").into()], output_names: vec!["Out".to_string()], node_type_metadata: NodeTypePersistentMetadata::layer(IVec2::new(0, 0)), network_metadata: Some(NodeNetworkMetadata { @@ -316,10 +316,11 @@ fn static_nodes() -> Vec { }, persistent_node_metadata: DocumentNodePersistentMetadata { input_properties: vec![ - "Artboards".into(), - PropertiesRow::with_override("Contents", WidgetOverride::Hidden), + ("Artboards", "TODO").into(), + PropertiesRow::with_override("Contents", "TODO", WidgetOverride::Hidden), PropertiesRow::with_override( "Location", + "TODO", WidgetOverride::Vec2(Vec2InputSettings { x: "X".to_string(), y: "Y".to_string(), @@ -329,6 +330,7 @@ fn static_nodes() -> Vec { ), PropertiesRow::with_override( "Dimensions", + "TODO", WidgetOverride::Vec2(Vec2InputSettings { x: "W".to_string(), y: "H".to_string(), @@ -336,8 +338,8 @@ fn static_nodes() -> Vec { ..Default::default() }), ), - PropertiesRow::with_override("Background", WidgetOverride::Custom("artboard_background".to_string())), - "Clip".into(), + PropertiesRow::with_override("Background", "TODO", WidgetOverride::Custom("artboard_background".to_string())), + ("Clip", "TODO").into(), ], output_names: vec!["Out".to_string()], node_type_metadata: NodeTypePersistentMetadata::layer(IVec2::new(0, 0)), @@ -420,7 +422,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Empty".into(), "URL".into()], + input_properties: vec![("Empty", "TODO").into(), ("URL", "TODO").into()], output_names: vec!["Image".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -570,7 +572,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into()], + input_properties: vec![("In", "TODO").into()], output_names: vec!["Canvas".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -670,7 +672,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Artwork".into(), "Footprint".into()], + input_properties: vec![("Artwork", "TODO").into(), ("Footprint", "TODO").into()], output_names: vec!["Canvas".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -730,7 +732,10 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Image".into(), PropertiesRow::with_override("Stencil", WidgetOverride::Custom("mask_stencil".to_string()))], + input_properties: vec![ + ("Image", "TODO").into(), + PropertiesRow::with_override("Stencil", "TODO", WidgetOverride::Custom("mask_stencil".to_string())), + ], output_names: vec!["Image".to_string()], ..Default::default() }, @@ -754,7 +759,11 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Image".into(), PropertiesRow::with_override("Insertion", WidgetOverride::Hidden), "Into".into()], + input_properties: vec![ + ("Image", "TODO").into(), + PropertiesRow::with_override("Insertion", "TODO", WidgetOverride::Hidden), + ("Into", "TODO").into(), + ], output_names: vec!["Image".to_string()], ..Default::default() }, @@ -779,7 +788,13 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["None".into(), "Red".into(), "Green".into(), "Blue".into(), "Alpha".into()], + input_properties: vec![ + ("None", "TODO").into(), + ("Red", "TODO").into(), + ("Green", "TODO").into(), + ("Blue", "TODO").into(), + ("Alpha", "TODO").into(), + ], output_names: vec!["Image".to_string()], ..Default::default() }, @@ -848,7 +863,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Image".into()], + input_properties: vec![("Image", "TODO").into()], output_names: vec!["Red".to_string(), "Green".to_string(), "Blue".to_string(), "Alpha".to_string()], has_primary_output: false, network_metadata: Some(NodeNetworkMetadata { @@ -933,7 +948,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Vector2".into()], + input_properties: vec![("Vector2", "TODO").into()], output_names: vec!["X".to_string(), "Y".to_string()], has_primary_output: false, network_metadata: Some(NodeNetworkMetadata { @@ -1003,7 +1018,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Background".into(), "Bounds".into(), "Trace".into(), "Cache".into()], + input_properties: vec![("Background", "TODO").into(), ("Bounds", "TODO").into(), ("Trace", "TODO").into(), ("Cache", "TODO").into()], output_names: vec!["Image".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1040,7 +1055,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Image".into()], + input_properties: vec![("Image", "TODO").into()], output_names: vec!["Image".to_string()], ..Default::default() }, @@ -1059,7 +1074,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Image".into()], + input_properties: vec![("Image", "TODO").into()], output_names: vec!["Image".to_string()], ..Default::default() }, @@ -1093,7 +1108,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Empty".into(), "Image".into()], + input_properties: vec![("Empty", "TODO").into(), ("Image", "TODO").into()], output_names: vec!["Image".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1156,7 +1171,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into()], + input_properties: vec![("In", "TODO").into()], output_names: vec!["Uniform".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1235,7 +1250,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into()], + input_properties: vec![("In", "TODO").into()], output_names: vec!["Storage".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1314,7 +1329,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into(), "In".into()], + input_properties: vec![("In", "TODO").into(), ("In", "TODO").into()], output_names: vec!["Output Buffer".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1403,7 +1418,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into(), "In".into(), "In".into()], + input_properties: vec![("In", "TODO").into(), ("In", "TODO").into(), ("In", "TODO").into()], output_names: vec!["Command Buffer".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1463,7 +1478,12 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Shader Handle".into(), "String".into(), "Bindgroup".into(), "Arc Shader Input".into()], + input_properties: vec![ + ("Shader Handle", "TODO").into(), + ("String", "TODO").into(), + ("Bindgroup", "TODO").into(), + ("Arc Shader Input", "TODO").into(), + ], output_names: vec!["Pipeline Layout".to_string()], ..Default::default() }, @@ -1508,7 +1528,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into()], + input_properties: vec![("In", "TODO").into()], output_names: vec!["Pipeline Result".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1588,7 +1608,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into()], + input_properties: vec![("In", "TODO").into()], output_names: vec!["Buffer".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1733,7 +1753,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Texture".into(), "Surface".into()], + input_properties: vec![("Texture", "TODO").into(), ("Surface", "TODO").into()], output_names: vec!["Rendered Texture".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1806,7 +1826,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["In".into()], + input_properties: vec![("In", "TODO").into()], output_names: vec!["Texture".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -1864,7 +1884,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Image".into(), "Node".into()], + input_properties: vec![("Image", "TODO").into(), ("Node", "TODO").into()], output_names: vec!["Image".to_string()], ..Default::default() }, @@ -1882,7 +1902,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Node".into()], + input_properties: vec![("Node", "TODO").into()], output_names: vec!["Document Node".to_string()], ..Default::default() }, @@ -1909,10 +1929,10 @@ fn static_nodes() -> Vec { }, persistent_node_metadata: DocumentNodePersistentMetadata { input_properties: vec![ - "Image".into(), - PropertiesRow::with_override("Brightness", WidgetOverride::Custom("brightness".to_string())), - PropertiesRow::with_override("Brightness", WidgetOverride::Custom("contrast".to_string())), - "Use Classic".into(), + ("Image", "TODO").into(), + PropertiesRow::with_override("Brightness", "TODO", WidgetOverride::Custom("brightness".to_string())), + PropertiesRow::with_override("Brightness", "TODO", WidgetOverride::Custom("contrast".to_string())), + ("Use Classic", "TODO").into(), ], output_names: vec!["Image".to_string()], ..Default::default() @@ -1938,7 +1958,7 @@ fn static_nodes() -> Vec { // ..Default::default() // }, // persistent_node_metadata: DocumentNodePersistentMetadata { - // input_properties: vec!["Image".into(), "Curve".into()], + // input_properties: vec![("Image", "TODO").into(), ("Curve", "TODO").into()], // output_names: vec!["Image".to_string()], // ..Default::default() // }, @@ -1963,9 +1983,10 @@ fn static_nodes() -> Vec { }, persistent_node_metadata: DocumentNodePersistentMetadata { input_properties: vec![ - "None".into(), + ("None", "TODO").into(), PropertiesRow::with_override( "Start", + "TODO", WidgetOverride::Vec2(Vec2InputSettings { x: "X".to_string(), y: "Y".to_string(), @@ -1975,6 +1996,7 @@ fn static_nodes() -> Vec { ), PropertiesRow::with_override( "End", + "TODO", WidgetOverride::Vec2(Vec2InputSettings { x: "X".to_string(), y: "Y".to_string(), @@ -2025,7 +2047,7 @@ fn static_nodes() -> Vec { ..Default::default() }, persistent_node_metadata: DocumentNodePersistentMetadata { - input_properties: vec!["Vector Data".into(), "Modification".into()], + input_properties: vec![("Vector Data", "TODO").into(), ("Modification", "TODO").into()], output_names: vec!["Vector Data".to_string()], network_metadata: Some(NodeNetworkMetadata { persistent_metadata: NodeNetworkPersistentMetadata { @@ -2085,11 +2107,12 @@ fn static_nodes() -> Vec { }, persistent_node_metadata: DocumentNodePersistentMetadata { input_properties: vec![ - "Editor API".into(), - PropertiesRow::with_override("Text", WidgetOverride::Custom("text_area".to_string())), - PropertiesRow::with_override("Font", WidgetOverride::Custom("text_font".to_string())), + ("Editor API", "TODO").into(), + PropertiesRow::with_override("Text", "TODO", WidgetOverride::Custom("text_area".to_string())), + PropertiesRow::with_override("Font", "TODO", WidgetOverride::Custom("text_font".to_string())), PropertiesRow::with_override( "Size", + "TODO", WidgetOverride::Number(NumberInputSettings { unit: Some(" px".to_string()), min: Some(1.), @@ -2098,6 +2121,7 @@ fn static_nodes() -> Vec { ), PropertiesRow::with_override( "Line Height", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), step: Some(0.1), @@ -2106,6 +2130,7 @@ fn static_nodes() -> Vec { ), PropertiesRow::with_override( "Character Spacing", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), step: Some(0.1), @@ -2114,6 +2139,7 @@ fn static_nodes() -> Vec { ), PropertiesRow::with_override( "Max Width", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(1.), blank_assist: false, @@ -2122,6 +2148,7 @@ fn static_nodes() -> Vec { ), PropertiesRow::with_override( "Max Height", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(1.), blank_assist: false, @@ -2211,9 +2238,10 @@ fn static_nodes() -> Vec { ..Default::default() }), input_properties: vec![ - "Vector Data".into(), + ("Vector Data", "TODO").into(), PropertiesRow::with_override( "Translation", + "TODO", WidgetOverride::Vec2(Vec2InputSettings { x: "X".to_string(), y: "Y".to_string(), @@ -2221,9 +2249,10 @@ fn static_nodes() -> Vec { ..Default::default() }), ), - PropertiesRow::with_override("Rotation", WidgetOverride::Custom("transform_rotation".to_string())), + PropertiesRow::with_override("Rotation", "TODO", WidgetOverride::Custom("transform_rotation".to_string())), PropertiesRow::with_override( "Scale", + "TODO", WidgetOverride::Vec2(Vec2InputSettings { x: "W".to_string(), y: "H".to_string(), @@ -2231,8 +2260,8 @@ fn static_nodes() -> Vec { ..Default::default() }), ), - PropertiesRow::with_override("Skew", WidgetOverride::Custom("transform_skew".to_string())), - PropertiesRow::with_override("Pivot", WidgetOverride::Hidden), + PropertiesRow::with_override("Skew", "TODO", WidgetOverride::Custom("transform_skew".to_string())), + PropertiesRow::with_override("Pivot", "TODO", WidgetOverride::Hidden), ], output_names: vec!["Data".to_string()], ..Default::default() @@ -2332,7 +2361,7 @@ fn static_nodes() -> Vec { }, ..Default::default() }), - input_properties: vec!["Group of Paths".into(), "Operation".into()], + input_properties: vec![("Group of Paths", "TODO").into(), ("Operation", "TODO").into()], output_names: vec!["Vector".to_string()], ..Default::default() }, @@ -2363,10 +2392,11 @@ fn static_nodes() -> Vec { }, persistent_node_metadata: DocumentNodePersistentMetadata { input_properties: vec![ - "Points".into(), - Into::::into("Instance").with_tooltip("Artwork to be copied and placed at each point"), + ("Points", "TODO").into(), + Into::::into(("Instance", "TODO")).with_tooltip("Artwork to be copied and placed at each point"), PropertiesRow::with_override( "Random Scale Min", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), mode: NumberInputMode::Range, @@ -2379,6 +2409,7 @@ fn static_nodes() -> Vec { .with_tooltip("Minimum range of randomized sizes given to each instance"), PropertiesRow::with_override( "Random Scale Max", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), mode: NumberInputMode::Range, @@ -2391,6 +2422,7 @@ fn static_nodes() -> Vec { .with_tooltip("Minimum range of randomized sizes given to each instance"), PropertiesRow::with_override( "Random Scale Bias", + "TODO", WidgetOverride::Number(NumberInputSettings { mode: NumberInputMode::Range, range_min: Some(-50.), @@ -2401,6 +2433,7 @@ fn static_nodes() -> Vec { .with_tooltip("Bias for the probability distribution of randomized sizes (0 is uniform, negatives favor more of small sizes, positives favor more of large sizes)"), PropertiesRow::with_override( "Random Scale Seed", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), is_integer: true, @@ -2410,6 +2443,7 @@ fn static_nodes() -> Vec { .with_tooltip("Seed to determine unique variations on all the randomized instance sizes"), PropertiesRow::with_override( "Random Rotation", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), max: Some(360.), @@ -2421,6 +2455,7 @@ fn static_nodes() -> Vec { .with_tooltip("Range of randomized angles given to each instance, in degrees ranging from furthest clockwise to counterclockwise"), PropertiesRow::with_override( "Random Rotation Seed", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), is_integer: true, @@ -2552,9 +2587,10 @@ fn static_nodes() -> Vec { ..Default::default() }), input_properties: vec![ - "Vector Data".into(), + ("Vector Data", "TODO").into(), PropertiesRow::with_override( "Spacing", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(1.), unit: Some(" px".to_string()), @@ -2564,6 +2600,7 @@ fn static_nodes() -> Vec { .with_tooltip("Distance between each instance (exact if 'Adaptive Spacing' is disabled, approximate if enabled)"), PropertiesRow::with_override( "Start Offset", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), unit: Some(" px".to_string()), @@ -2573,6 +2610,7 @@ fn static_nodes() -> Vec { .with_tooltip("Exclude some distance from the start of the path before the first instance"), PropertiesRow::with_override( "Stop Offset", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), unit: Some(" px".to_string()), @@ -2580,7 +2618,7 @@ fn static_nodes() -> Vec { }), ) .with_tooltip("Exclude some distance from the end of the path after the last instance"), - Into::::into("Adaptive Spacing").with_tooltip("Round 'Spacing' to a nearby value that divides into the path length evenly"), + Into::::into(("Adaptive Spacing", "TODO")).with_tooltip("Round 'Spacing' to a nearby value that divides into the path length evenly"), ], output_names: vec!["Vector".to_string()], ..Default::default() @@ -2686,9 +2724,10 @@ fn static_nodes() -> Vec { ..Default::default() }), input_properties: vec![ - "Vector Data".into(), + ("Vector Data", "TODO").into(), PropertiesRow::with_override( "Separation Disk Diameter", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.01), mode: NumberInputMode::Range, @@ -2699,6 +2738,7 @@ fn static_nodes() -> Vec { ), PropertiesRow::with_override( "Seed", + "TODO", WidgetOverride::Number(NumberInputSettings { min: Some(0.), is_integer: true, @@ -2800,10 +2840,10 @@ fn static_nodes() -> Vec { input_properties: fields .iter() .map(|f| match f.widget_override { - RegistryWidgetOverride::None => f.name.into(), - RegistryWidgetOverride::Hidden => PropertiesRow::with_override(f.name, WidgetOverride::Hidden), - RegistryWidgetOverride::String(str) => PropertiesRow::with_override(f.name, WidgetOverride::String(str.to_string())), - RegistryWidgetOverride::Custom(str) => PropertiesRow::with_override(f.name, WidgetOverride::Custom(str.to_string())), + RegistryWidgetOverride::None => (f.name, f.description).into(), + RegistryWidgetOverride::Hidden => PropertiesRow::with_override(f.name, f.description, WidgetOverride::Hidden), + RegistryWidgetOverride::String(str) => PropertiesRow::with_override(f.name, f.description, WidgetOverride::String(str.to_string())), + RegistryWidgetOverride::Custom(str) => PropertiesRow::with_override(f.name, f.description, WidgetOverride::Custom(str.to_string())), }) .collect(), output_names: vec![output_type.to_string()], @@ -2994,7 +3034,7 @@ fn static_input_properties() -> InputProperties { map.insert( "number".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let mut number_input = NumberInput::default(); if let Some(unit) = context .network_interface @@ -3060,14 +3100,14 @@ fn static_input_properties() -> InputProperties { true }); Ok(vec![LayoutGroup::Row { - widgets: node_properties::number_widget(document_node, node_id, index, input_name, number_input, blank_assist), + widgets: node_properties::number_widget(document_node, node_id, index, input_name, input_description, number_input, blank_assist), }]) }), ); map.insert( "vec2".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let x = context .network_interface .input_metadata(&node_id, index, "x", context.selection_network_path) @@ -3102,6 +3142,7 @@ fn static_input_properties() -> InputProperties { node_id, index, input_name, + input_description, x, y, unit, @@ -3113,39 +3154,48 @@ fn static_input_properties() -> InputProperties { map.insert( "noise_properties_scale".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (_, coherent_noise_active, _, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; - let scale = node_properties::number_widget(document_node, node_id, index, input_name, NumberInput::default().min(0.).disabled(!coherent_noise_active), true); + let scale = node_properties::number_widget( + document_node, + node_id, + index, + input_name, + input_description, + NumberInput::default().min(0.).disabled(!coherent_noise_active), + true, + ); Ok(vec![scale.into()]) }), ); map.insert( "noise_properties_noise_type".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; - let noise_type_row = node_properties::noise_type(document_node, node_id, index, input_name, true); + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; + let noise_type_row = node_properties::noise_type(document_node, node_id, index, input_name, input_description, true); Ok(vec![noise_type_row, LayoutGroup::Row { widgets: Vec::new() }]) }), ); map.insert( "noise_properties_domain_warp_type".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (_, coherent_noise_active, _, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; - let domain_warp_type = node_properties::domain_warp_type(document_node, node_id, index, input_name, true, !coherent_noise_active); + let domain_warp_type = node_properties::domain_warp_type(document_node, node_id, index, input_name, input_description, true, !coherent_noise_active); Ok(vec![domain_warp_type]) }), ); map.insert( "noise_properties_domain_warp_amplitude".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (_, coherent_noise_active, _, _, domain_warp_active, _) = node_properties::query_noise_pattern_state(node_id, context)?; let domain_warp_amplitude = node_properties::number_widget( document_node, node_id, index, input_name, + input_description, NumberInput::default().min(0.).disabled(!coherent_noise_active || !domain_warp_active), true, ); @@ -3155,22 +3205,23 @@ fn static_input_properties() -> InputProperties { map.insert( "noise_properties_fractal_type".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (_, coherent_noise_active, _, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; - let fractal_type_row = node_properties::fractal_type(document_node, node_id, index, input_name, true, !coherent_noise_active); + let fractal_type_row = node_properties::fractal_type(document_node, node_id, index, input_name, input_description, true, !coherent_noise_active); Ok(vec![fractal_type_row]) }), ); map.insert( "noise_properties_fractal_octaves".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; let fractal_octaves = node_properties::number_widget( document_node, node_id, index, input_name, + input_description, NumberInput::default() .mode_range() .min(1.) @@ -3186,13 +3237,14 @@ fn static_input_properties() -> InputProperties { map.insert( "noise_properties_fractal_lacunarity".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; let fractal_lacunarity = node_properties::number_widget( document_node, node_id, index, input_name, + input_description, NumberInput::default() .mode_range() .min(0.) @@ -3206,13 +3258,14 @@ fn static_input_properties() -> InputProperties { map.insert( "noise_properties_fractal_gain".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; let fractal_gain = node_properties::number_widget( document_node, node_id, index, input_name, + input_description, NumberInput::default() .mode_range() .min(0.) @@ -3226,13 +3279,14 @@ fn static_input_properties() -> InputProperties { map.insert( "noise_properties_fractal_weighted_strength".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; let fractal_weighted_strength = node_properties::number_widget( document_node, node_id, index, input_name, + input_description, NumberInput::default() .mode_range() .min(0.) @@ -3246,13 +3300,14 @@ fn static_input_properties() -> InputProperties { map.insert( "noise_properties_ping_pong_strength".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (fractal_active, coherent_noise_active, _, ping_pong_active, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; let fractal_ping_pong_strength = node_properties::number_widget( document_node, node_id, index, input_name, + input_description, NumberInput::default() .mode_range() .min(0.) @@ -3266,31 +3321,33 @@ fn static_input_properties() -> InputProperties { map.insert( "noise_properties_cellular_distance_function".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; - let cellular_distance_function_row = node_properties::cellular_distance_function(document_node, node_id, index, input_name, true, !coherent_noise_active || !cellular_noise_active); + let cellular_distance_function_row = + node_properties::cellular_distance_function(document_node, node_id, index, input_name, input_description, true, !coherent_noise_active || !cellular_noise_active); Ok(vec![cellular_distance_function_row]) }), ); map.insert( "noise_properties_cellular_return_type".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; - let cellular_return_type = node_properties::cellular_return_type(document_node, node_id, index, input_name, true, !coherent_noise_active || !cellular_noise_active); + let cellular_return_type = node_properties::cellular_return_type(document_node, node_id, index, input_name, input_description, true, !coherent_noise_active || !cellular_noise_active); Ok(vec![cellular_return_type]) }), ); map.insert( "noise_properties_cellular_jitter".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; let cellular_jitter = node_properties::number_widget( document_node, node_id, index, input_name, + input_description, NumberInput::default() .mode_range() .range_min(Some(0.)) @@ -3304,7 +3361,7 @@ fn static_input_properties() -> InputProperties { map.insert( "brightness".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let is_use_classic = document_node .inputs .iter() @@ -3319,6 +3376,7 @@ fn static_input_properties() -> InputProperties { node_id, index, input_name, + input_description, NumberInput::default().mode_range().range_min(Some(b_min)).range_max(Some(b_max)).unit("%").display_decimal_places(2), true, ); @@ -3328,7 +3386,7 @@ fn static_input_properties() -> InputProperties { map.insert( "contrast".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let is_use_classic = document_node .inputs .iter() @@ -3343,6 +3401,7 @@ fn static_input_properties() -> InputProperties { node_id, index, input_name, + input_description, NumberInput::default().mode_range().range_min(Some(c_min)).range_max(Some(c_max)).unit("%").display_decimal_places(2), true, ); @@ -3352,52 +3411,68 @@ fn static_input_properties() -> InputProperties { map.insert( "assign_colors_gradient".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; - let gradient_row = node_properties::color_widget(document_node, node_id, index, input_name, ColorInput::default().allow_none(false), true); + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; + let gradient_row = node_properties::color_widget(document_node, node_id, index, input_name, input_description, ColorInput::default().allow_none(false), true); Ok(vec![gradient_row]) }), ); map.insert( "assign_colors_seed".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let randomize_enabled = node_properties::query_assign_colors_randomize(node_id, context)?; - let seed_row = node_properties::number_widget(document_node, node_id, index, input_name, NumberInput::default().min(0.).int().disabled(!randomize_enabled), true); + let seed_row = node_properties::number_widget( + document_node, + node_id, + index, + input_name, + input_description, + NumberInput::default().min(0.).int().disabled(!randomize_enabled), + true, + ); Ok(vec![seed_row.into()]) }), ); map.insert( "assign_colors_repeat_every".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; let randomize_enabled = node_properties::query_assign_colors_randomize(node_id, context)?; - let repeat_every_row = node_properties::number_widget(document_node, node_id, index, input_name, NumberInput::default().min(0.).int().disabled(randomize_enabled), true); + let repeat_every_row = node_properties::number_widget( + document_node, + node_id, + index, + input_name, + input_description, + NumberInput::default().min(0.).int().disabled(randomize_enabled), + true, + ); Ok(vec![repeat_every_row.into()]) }), ); map.insert( "mask_stencil".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; - let mask = node_properties::color_widget(document_node, node_id, index, input_name, ColorInput::default(), true); + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; + let mask = node_properties::color_widget(document_node, node_id, index, input_name, input_description, ColorInput::default(), true); Ok(vec![mask]) }), ); map.insert( "spline_input".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; Ok(vec![LayoutGroup::Row { - widgets: node_properties::vec_dvec2_input(document_node, node_id, index, input_name, TextInput::default().centered(true), true), + widgets: node_properties::vec_dvec2_input(document_node, node_id, index, input_name, input_description, TextInput::default().centered(true), true), }]) }), ); map.insert( "transform_rotation".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; - let mut widgets = node_properties::start_widgets(document_node, node_id, index, input_name, super::utility_types::FrontendGraphDataType::Number, true); + let mut widgets = node_properties::start_widgets(document_node, node_id, index, input_name, input_description, super::utility_types::FrontendGraphDataType::Number, true); let Some(input) = document_node.inputs.get(index) else { return Err("Input not found in transform rotation input override".to_string()); @@ -3427,9 +3502,9 @@ fn static_input_properties() -> InputProperties { map.insert( "transform_skew".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; - let mut widgets = node_properties::start_widgets(document_node, node_id, index, input_name, super::utility_types::FrontendGraphDataType::Number, true); + let mut widgets = node_properties::start_widgets(document_node, node_id, index, input_name, input_description, super::utility_types::FrontendGraphDataType::Number, true); let Some(input) = document_node.inputs.get(index) else { return Err("Input not found in transform skew input override".to_string()); @@ -3472,17 +3547,17 @@ fn static_input_properties() -> InputProperties { map.insert( "text_area".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; Ok(vec![LayoutGroup::Row { - widgets: node_properties::text_area_widget(document_node, node_id, index, input_name, true), + widgets: node_properties::text_area_widget(document_node, node_id, index, input_name, input_description, true), }]) }), ); map.insert( "text_font".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; - let (font, style) = node_properties::font_inputs(document_node, node_id, index, input_name, true); + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; + let (font, style) = node_properties::font_inputs(document_node, node_id, index, input_name, input_description, true); let mut result = vec![LayoutGroup::Row { widgets: font }]; if let Some(style) = style { result.push(LayoutGroup::Row { widgets: style }); @@ -3493,12 +3568,13 @@ fn static_input_properties() -> InputProperties { map.insert( "artboard_background".to_string(), Box::new(|node_id, index, context| { - let (document_node, input_name) = node_properties::query_node_and_input_name(node_id, index, context)?; + let (document_node, input_name, input_description) = node_properties::query_node_and_input_info(node_id, index, context)?; Ok(vec![node_properties::color_widget( document_node, node_id, index, input_name, + input_description, ColorInput::default().allow_none(false), true, )]) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 787e8d40..26114588 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -2051,7 +2051,7 @@ impl NodeGraphMessageHandler { Separator::new(SeparatorType::Related).widget_holder(), IconLabel::new("Layer").tooltip("Name of the selected layer").widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), - TextInput::new(context.network_interface.frontend_display_name(&layer, context.selection_network_path)) + TextInput::new(context.network_interface.display_name(&layer, context.selection_network_path)) .tooltip("Name of the selected layer") .on_update(move |text_input| { NodeGraphMessage::SetDisplayName { @@ -2095,9 +2095,10 @@ impl NodeGraphMessageHandler { !context.network_interface.is_layer(node_id, context.selection_network_path) } }) + .map(|(_, node_id)| node_id) .collect::>() - .iter() - .map(|(_, node_id)| node_properties::generate_node_properties(*node_id, context)) + .into_iter() + .map(|node_id| node_properties::generate_node_properties(node_id, context)) .collect::>(); layer_properties.extend(node_properties); @@ -2215,6 +2216,7 @@ impl NodeGraphMessageHandler { resolved_type: Some(format!("{:?} from {:?}", &input.ty, input.type_source)), valid_types: input.valid_types.iter().map(|ty| ty.to_string()).collect(), name: input.name.unwrap_or_else(|| input.ty.nested_type().to_string()), + description: input.description.unwrap_or_default(), connected_to: input.output_connector, }) }); @@ -2234,6 +2236,7 @@ impl NodeGraphMessageHandler { Some(FrontendGraphOutput { data_type: frontend_data_type, name: "Output 1".to_string(), + description: String::new(), resolved_type: primary_output_type.map(|(input, type_source)| format!("{input:?} from {type_source:?}")), connected_to, }) @@ -2267,6 +2270,7 @@ impl NodeGraphMessageHandler { exposed_outputs.push(FrontendGraphOutput { data_type: frontend_data_type, name: output_name, + description: String::new(), resolved_type: exposed_output.clone().map(|(input, type_source)| format!("{input:?} from {type_source:?}")), connected_to, }); @@ -2306,7 +2310,7 @@ impl NodeGraphMessageHandler { .is_some_and(|node_metadata| node_metadata.persistent_metadata.is_layer()), can_be_layer: can_be_layer_lookup.contains(&node_id), reference: network_interface.reference(&node_id, breadcrumb_network_path).cloned().unwrap_or_default(), - display_name: network_interface.frontend_display_name(&node_id, breadcrumb_network_path), + display_name: network_interface.display_name(&node_id, breadcrumb_network_path), primary_input, exposed_inputs, primary_output, @@ -2332,7 +2336,7 @@ impl NodeGraphMessageHandler { if let Some(network) = node.implementation.get_network() { current_network = network; }; - subgraph_names.push(network_interface.frontend_display_name(node_id, ¤t_network_path)); + subgraph_names.push(network_interface.display_name(node_id, ¤t_network_path)); current_network_path.push(*node_id) } Some(subgraph_names) @@ -2395,7 +2399,7 @@ impl NodeGraphMessageHandler { let data = LayerPanelEntry { id: node_id, - alias: network_interface.frontend_display_name(&node_id, &[]), + alias: network_interface.display_name(&node_id, &[]), tooltip: if cfg!(debug_assertions) { format!("Layer ID: {node_id}") } else { "".into() }, in_selected_network: selection_network_path.is_empty(), children_allowed, @@ -2522,6 +2526,7 @@ impl NodeGraphMessageHandler { #[derive(Default)] struct InputLookup { name: Option, + description: Option, ty: Type, type_source: TypeSource, valid_types: Vec, @@ -2552,11 +2557,16 @@ fn frontend_inputs_lookup(breadcrumb_network_path: &[NodeId], network_interface: .input_name(&node_id, index, breadcrumb_network_path) .filter(|s| !s.is_empty()) .map(|name| name.to_string()); + let description = network_interface + .input_description(&node_id, index, breadcrumb_network_path) + .filter(|s| !s.is_empty()) + .map(|description| description.to_string()); // Get the output connector that feeds into this input (done here as well for simplicity) let connector = OutputConnector::from_input(input); inputs.push(Some(InputLookup { name, + description, output_connector: connector, ..Default::default() })); 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 84b55ff5..b418723d 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -73,12 +73,12 @@ pub fn add_blank_assist(widgets: &mut Vec) { ]); } -pub fn start_widgets(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, data_type: FrontendGraphDataType, blank_assist: bool) -> Vec { +pub fn start_widgets(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, data_type: FrontendGraphDataType, blank_assist: bool) -> Vec { let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return vec![]; }; - let mut widgets = vec![expose_widget(node_id, index, data_type, input.is_exposed()), TextLabel::new(name).widget_holder()]; + let mut widgets = vec![expose_widget(node_id, index, data_type, input.is_exposed()), TextLabel::new(name).tooltip(description).widget_holder()]; if blank_assist { add_blank_assist(&mut widgets); } @@ -97,6 +97,10 @@ pub(crate) fn property_from_type( log::warn!("A widget failed to be built for node {node_id}, index {index} because the input name could not be determined"); return Err(vec![]); }; + let Some(description) = context.network_interface.input_description(&node_id, index, context.selection_network_path) else { + log::warn!("A widget failed to be built for node {node_id}, index {index} because the input description could not be determined"); + return Err(vec![]); + }; let Some(network) = context.network_interface.nested_network(context.selection_network_path) else { log::warn!("A widget failed to be built for node {node_id}, index {index} because the network could not be determined"); return Err(vec![]); @@ -122,59 +126,72 @@ pub(crate) fn property_from_type( Type::Concrete(concrete_type) => { match concrete_type.alias.as_ref().map(|x| x.as_ref()) { // Aliased types (ambiguous values) - Some("Percentage") => number_widget(document_node, node_id, index, name, number_input.percentage().min(min(0.)).max(max(100.)), true).into(), - Some("SignedPercentage") => number_widget(document_node, node_id, index, name, number_input.percentage().min(min(-100.)).max(max(100.)), true).into(), - Some("Angle") => number_widget(document_node, node_id, index, name, number_input.mode_range().min(min(-180.)).max(max(180.)).unit("°"), true).into(), - Some("PixelLength") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)).unit(" px"), true).into(), - Some("Length") => number_widget(document_node, node_id, index, name, number_input.min(min(0.)), true).into(), - Some("Fraction") => number_widget(document_node, node_id, index, name, number_input.mode_range().min(min(0.)).max(max(1.)), true).into(), - Some("IntegerCount") => number_widget(document_node, node_id, index, name, number_input.int().min(min(1.)), true).into(), - Some("SeedValue") => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)), true).into(), - Some("Resolution") => vec2_widget(document_node, node_id, index, name, "W", "H", " px", Some(64.), add_blank_assist), + Some("Percentage") => number_widget(document_node, node_id, index, name, description, number_input.percentage().min(min(0.)).max(max(100.)), true).into(), + Some("SignedPercentage") => number_widget(document_node, node_id, index, name, description, number_input.percentage().min(min(-100.)).max(max(100.)), true).into(), + Some("Angle") => number_widget( + document_node, + node_id, + index, + name, + description, + number_input.mode_range().min(min(-180.)).max(max(180.)).unit("°"), + true, + ) + .into(), + Some("PixelLength") => number_widget(document_node, node_id, index, name, description, number_input.min(min(0.)).unit(" px"), true).into(), + Some("Length") => number_widget(document_node, node_id, index, name, description, number_input.min(min(0.)), true).into(), + Some("Fraction") => number_widget(document_node, node_id, index, name, description, number_input.mode_range().min(min(0.)).max(max(1.)), true).into(), + Some("IntegerCount") => number_widget(document_node, node_id, index, name, description, number_input.int().min(min(1.)), true).into(), + Some("SeedValue") => number_widget(document_node, node_id, index, name, description, number_input.int().min(min(0.)), true).into(), + Some("Resolution") => vec2_widget(document_node, node_id, index, name, description, "W", "H", " px", Some(64.), add_blank_assist), // For all other types, use TypeId-based matching _ => { use std::any::TypeId; match concrete_type.id { - Some(x) if x == TypeId::of::() => bool_widget(document_node, node_id, index, name, CheckboxInput::default(), true).into(), - Some(x) if x == TypeId::of::() => number_widget(document_node, node_id, index, name, number_input.min(min(f64::NEG_INFINITY)).max(max(f64::INFINITY)), true).into(), - Some(x) if x == TypeId::of::() => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)).max(max(f64::from(u32::MAX))), true).into(), - Some(x) if x == TypeId::of::() => number_widget(document_node, node_id, index, name, number_input.int().min(min(0.)), true).into(), - Some(x) if x == TypeId::of::() => text_widget(document_node, node_id, index, name, true).into(), - Some(x) if x == TypeId::of::() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(false), true), - Some(x) if x == TypeId::of::>() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(true), true), - Some(x) if x == TypeId::of::() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", None, add_blank_assist), - Some(x) if x == TypeId::of::() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", Some(0.), add_blank_assist), - Some(x) if x == TypeId::of::() => vec2_widget(document_node, node_id, index, name, "X", "Y", "", None, add_blank_assist), - Some(x) if x == TypeId::of::>() => vec_f64_input(document_node, node_id, index, name, TextInput::default(), true).into(), - Some(x) if x == TypeId::of::>() => vec_dvec2_input(document_node, node_id, index, name, TextInput::default(), true).into(), + Some(x) if x == TypeId::of::() => bool_widget(document_node, node_id, index, name, description, CheckboxInput::default(), true).into(), + Some(x) if x == TypeId::of::() => { + number_widget(document_node, node_id, index, name, description, number_input.min(min(f64::NEG_INFINITY)).max(max(f64::INFINITY)), true).into() + } + Some(x) if x == TypeId::of::() => { + number_widget(document_node, node_id, index, name, description, number_input.int().min(min(0.)).max(max(f64::from(u32::MAX))), true).into() + } + Some(x) if x == TypeId::of::() => number_widget(document_node, node_id, index, name, description, number_input.int().min(min(0.)), true).into(), + Some(x) if x == TypeId::of::() => text_widget(document_node, node_id, index, name, description, true).into(), + Some(x) if x == TypeId::of::() => color_widget(document_node, node_id, index, name, description, ColorInput::default().allow_none(false), true), + Some(x) if x == TypeId::of::>() => color_widget(document_node, node_id, index, name, description, ColorInput::default().allow_none(true), true), + Some(x) if x == TypeId::of::() => vec2_widget(document_node, node_id, index, name, description, "X", "Y", "", None, add_blank_assist), + Some(x) if x == TypeId::of::() => vec2_widget(document_node, node_id, index, name, description, "X", "Y", "", Some(0.), add_blank_assist), + Some(x) if x == TypeId::of::() => vec2_widget(document_node, node_id, index, name, description, "X", "Y", "", None, add_blank_assist), + Some(x) if x == TypeId::of::>() => vec_f64_input(document_node, node_id, index, name, description, TextInput::default(), true).into(), + Some(x) if x == TypeId::of::>() => vec_dvec2_input(document_node, node_id, index, name, description, TextInput::default(), true).into(), Some(x) if x == TypeId::of::() => { - let (font_widgets, style_widgets) = font_inputs(document_node, node_id, index, name, false); + let (font_widgets, style_widgets) = font_inputs(document_node, node_id, index, name, description, false); font_widgets.into_iter().chain(style_widgets.unwrap_or_default()).collect::>().into() } - Some(x) if x == TypeId::of::() => curves_widget(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(false), true), - Some(x) if x == TypeId::of::() => vector_widget(document_node, node_id, index, name, true).into(), + Some(x) if x == TypeId::of::() => curves_widget(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => color_widget(document_node, node_id, index, name, description, ColorInput::default().allow_none(false), true), + Some(x) if x == TypeId::of::() => vector_widget(document_node, node_id, index, name, description, true).into(), Some(x) if x == TypeId::of::() || x == TypeId::of::>() || x == TypeId::of::() => { - raster_widget(document_node, node_id, index, name, true).into() + raster_widget(document_node, node_id, index, name, description, true).into() } - Some(x) if x == TypeId::of::() => group_widget(document_node, node_id, index, name, true).into(), + Some(x) if x == TypeId::of::() => group_widget(document_node, node_id, index, name, description, true).into(), Some(x) if x == TypeId::of::() => { let widgets = footprint_widget(document_node, node_id, index); let (last, rest) = widgets.split_last().expect("Footprint widget should return multiple rows"); extra_widgets = rest.to_vec(); last.clone() } - Some(x) if x == TypeId::of::() => blend_mode(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => real_time_mode(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => color_channel(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => rgba_channel(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => xy_components(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => noise_type(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => fractal_type(document_node, node_id, index, name, true, false), - Some(x) if x == TypeId::of::() => cellular_distance_function(document_node, node_id, index, name, true, false), - Some(x) if x == TypeId::of::() => cellular_return_type(document_node, node_id, index, name, true, false), - Some(x) if x == TypeId::of::() => domain_warp_type(document_node, node_id, index, name, true, false), + Some(x) if x == TypeId::of::() => blend_mode(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => real_time_mode(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => color_channel(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => rgba_channel(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => xy_components(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => noise_type(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => fractal_type(document_node, node_id, index, name, description, true, false), + Some(x) if x == TypeId::of::() => cellular_distance_function(document_node, node_id, index, name, description, true, false), + Some(x) if x == TypeId::of::() => cellular_return_type(document_node, node_id, index, name, description, true, false), + Some(x) if x == TypeId::of::() => domain_warp_type(document_node, node_id, index, name, description, true, false), Some(x) if x == TypeId::of::() => vec![ DropdownInput::new(vec![vec![ MenuListEntry::new("Relative") @@ -187,9 +204,9 @@ pub(crate) fn property_from_type( .widget_holder(), ] .into(), - Some(x) if x == TypeId::of::() => grid_type_widget(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => line_cap_widget(document_node, node_id, index, name, true), - Some(x) if x == TypeId::of::() => line_join_widget(document_node, node_id, index, name, true), + Some(x) if x == TypeId::of::() => grid_type_widget(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => line_cap_widget(document_node, node_id, index, name, description, true), + Some(x) if x == TypeId::of::() => line_join_widget(document_node, node_id, index, name, description, true), Some(x) if x == TypeId::of::() => vec![ DropdownInput::new(vec![vec![ MenuListEntry::new("Solid") @@ -214,9 +231,9 @@ pub(crate) fn property_from_type( .widget_holder(), ] .into(), - Some(x) if x == TypeId::of::() => boolean_operation_radio_buttons(document_node, node_id, index, name, true), + Some(x) if x == TypeId::of::() => boolean_operation_radio_buttons(document_node, node_id, index, name, description, true), Some(x) if x == TypeId::of::() => centroid_widget(document_node, node_id, index), - Some(x) if x == TypeId::of::() => luminance_calculation(document_node, node_id, index, name, true), + Some(x) if x == TypeId::of::() => luminance_calculation(document_node, node_id, index, name, description, true), // Some(x) if x == TypeId::of::() => vec![ // DropdownInput::new( // ImaginateSamplingMethod::list() @@ -250,7 +267,7 @@ pub(crate) fn property_from_type( // ] // .into(), _ => { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, true); + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, true); widgets.extend_from_slice(&[ Separator::new(SeparatorType::Unrelated).widget_holder(), TextLabel::new("-") @@ -277,8 +294,8 @@ pub(crate) fn property_from_type( Ok(extra_widgets) } -pub fn text_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn text_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); @@ -296,8 +313,8 @@ pub fn text_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, widgets } -pub fn text_area_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn text_area_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); @@ -315,8 +332,8 @@ pub fn text_area_widget(document_node: &DocumentNode, node_id: NodeId, index: us widgets } -pub fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, checkbox_input: CheckboxInput, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, checkbox_input: CheckboxInput, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); @@ -336,7 +353,7 @@ pub fn bool_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, } pub fn footprint_widget(document_node: &DocumentNode, node_id: NodeId, index: usize) -> Vec { - let mut location_widgets = start_widgets(document_node, node_id, index, "Footprint", FrontendGraphDataType::General, true); + let mut location_widgets = start_widgets(document_node, node_id, index, "Footprint", "TODO", FrontendGraphDataType::General, true); location_widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); let mut scale_widgets = vec![TextLabel::new("").widget_holder()]; @@ -481,13 +498,14 @@ pub fn vec2_widget( node_id: NodeId, index: usize, name: &str, + description: &str, x: &str, y: &str, unit: &str, min: Option, mut assist: impl FnMut(&mut Vec), ) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Number, false); + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::Number, false); assist(&mut widgets); @@ -598,8 +616,8 @@ pub fn vec2_widget( LayoutGroup::Row { widgets } } -pub fn vec_f64_input(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, text_input: TextInput, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Number, blank_assist); +pub fn vec_f64_input(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, text_input: TextInput, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::Number, blank_assist); let from_string = |string: &str| { string @@ -627,8 +645,8 @@ pub fn vec_f64_input(document_node: &DocumentNode, node_id: NodeId, index: usize widgets } -pub fn vec_dvec2_input(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, text_props: TextInput, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Number, blank_assist); +pub fn vec_dvec2_input(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, text_props: TextInput, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::Number, blank_assist); let from_string = |string: &str| { string @@ -656,8 +674,8 @@ pub fn vec_dvec2_input(document_node: &DocumentNode, node_id: NodeId, index: usi widgets } -pub fn font_inputs(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> (Vec, Option>) { - let mut first_widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn font_inputs(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> (Vec, Option>) { + let mut first_widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let mut second_widgets = None; let from_font_input = |font: &FontInput| TaggedValue::Font(Font::new(font.font_family.clone(), font.font_style.clone())); @@ -690,8 +708,8 @@ pub fn font_inputs(document_node: &DocumentNode, node_id: NodeId, index: usize, (first_widgets, second_widgets) } -pub fn vector_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::VectorData, blank_assist); +pub fn vector_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::VectorData, blank_assist); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.push(TextLabel::new("Vector data is supplied through the node graph").widget_holder()); @@ -699,8 +717,8 @@ pub fn vector_widget(document_node: &DocumentNode, node_id: NodeId, index: usize widgets } -pub fn raster_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Raster, blank_assist); +pub fn raster_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::Raster, blank_assist); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.push(TextLabel::new("Raster data is supplied through the node graph").widget_holder()); @@ -708,8 +726,8 @@ pub fn raster_widget(document_node: &DocumentNode, node_id: NodeId, index: usize widgets } -pub fn group_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Group, blank_assist); +pub fn group_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::Group, blank_assist); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.push(TextLabel::new("Group data is supplied through the node graph").widget_holder()); @@ -717,8 +735,8 @@ pub fn group_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, widgets } -pub fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, number_props: NumberInput, blank_assist: bool) -> Vec { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Number, blank_assist); +pub fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, number_props: NumberInput, blank_assist: bool) -> Vec { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::Number, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); @@ -786,8 +804,8 @@ pub fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize } // TODO: Generalize this instead of using a separate function per dropdown menu enum -pub fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -813,8 +831,8 @@ pub fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize LayoutGroup::Row { widgets }.with_tooltip("Color Channel") } -pub fn real_time_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn real_time_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -847,8 +865,8 @@ pub fn real_time_mode(document_node: &DocumentNode, node_id: NodeId, index: usiz LayoutGroup::Row { widgets }.with_tooltip("Real Time Mode") } -pub fn rgba_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn rgba_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -874,8 +892,8 @@ pub fn rgba_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, LayoutGroup::Row { widgets }.with_tooltip("Color Channel") } -pub fn xy_components(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn xy_components(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -902,8 +920,8 @@ pub fn xy_components(document_node: &DocumentNode, node_id: NodeId, index: usize } // TODO: Generalize this instead of using a separate function per dropdown menu enum -pub fn noise_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn noise_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -928,8 +946,8 @@ pub fn noise_type(document_node: &DocumentNode, node_id: NodeId, index: usize, n } // TODO: Generalize this instead of using a separate function per dropdown menu enum -pub fn fractal_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn fractal_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -954,8 +972,8 @@ pub fn fractal_type(document_node: &DocumentNode, node_id: NodeId, index: usize, } // TODO: Generalize this instead of using a separate function per dropdown menu enum -pub fn cellular_distance_function(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn cellular_distance_function(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -983,8 +1001,8 @@ pub fn cellular_distance_function(document_node: &DocumentNode, node_id: NodeId, } // TODO: Generalize this instead of using a separate function per dropdown menu enum -pub fn cellular_return_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn cellular_return_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -1009,8 +1027,8 @@ pub fn cellular_return_type(document_node: &DocumentNode, node_id: NodeId, index } // TODO: Generalize this instead of using a separate function per dropdown menu enum -pub fn domain_warp_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn domain_warp_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool, disabled: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -1035,8 +1053,8 @@ pub fn domain_warp_type(document_node: &DocumentNode, node_id: NodeId, index: us } // TODO: Generalize this instead of using a separate function per dropdown menu enum -pub fn blend_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn blend_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -1068,8 +1086,8 @@ pub fn blend_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, n } // TODO: Generalize this for all dropdowns (also see blend_mode and channel_extration) -pub fn luminance_calculation(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn luminance_calculation(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -1095,8 +1113,8 @@ pub fn luminance_calculation(document_node: &DocumentNode, node_id: NodeId, inde LayoutGroup::Row { widgets }.with_tooltip("Formula used to calculate the luminance of a pixel") } -pub fn boolean_operation_radio_buttons(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn boolean_operation_radio_buttons(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); @@ -1125,8 +1143,8 @@ pub fn boolean_operation_radio_buttons(document_node: &DocumentNode, node_id: No LayoutGroup::Row { widgets } } -pub fn grid_type_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn grid_type_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -1150,8 +1168,8 @@ pub fn grid_type_widget(document_node: &DocumentNode, node_id: NodeId, index: us LayoutGroup::Row { widgets } } -pub fn line_cap_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn line_cap_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -1175,8 +1193,8 @@ pub fn line_cap_widget(document_node: &DocumentNode, node_id: NodeId, index: usi LayoutGroup::Row { widgets } } -pub fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -1200,8 +1218,8 @@ pub fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: us LayoutGroup::Row { widgets } } -pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, color_button: ColorInput, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, color_button: ColorInput, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); // Return early with just the label if the input is exposed to the graph, meaning we don't want to show the color picker widget in the Properties panel let NodeInput::Value { tagged_value, exposed: false } = &document_node.inputs[index] else { @@ -1247,8 +1265,8 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, LayoutGroup::Row { widgets } } -pub fn curves_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist); +pub fn curves_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, description: &str, blank_assist: bool) -> LayoutGroup { + let mut widgets = start_widgets(document_node, node_id, index, name, description, FrontendGraphDataType::General, blank_assist); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); @@ -1267,7 +1285,7 @@ pub fn curves_widget(document_node: &DocumentNode, node_id: NodeId, index: usize } pub fn centroid_widget(document_node: &DocumentNode, node_id: NodeId, index: usize) -> LayoutGroup { - let mut widgets = start_widgets(document_node, node_id, index, "Centroid Type", FrontendGraphDataType::General, true); + let mut widgets = start_widgets(document_node, node_id, index, "Centroid Type", "TODO", FrontendGraphDataType::General, true); let Some(input) = document_node.inputs.get(index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); return LayoutGroup::Row { widgets: vec![] }; @@ -1307,13 +1325,17 @@ pub fn get_document_node<'a>(node_id: NodeId, context: &'a NodePropertiesContext network.nodes.get(&node_id).ok_or(format!("node {node_id} not found in get_document_node")) } -pub fn query_node_and_input_name<'a>(node_id: NodeId, input_index: usize, context: &'a NodePropertiesContext<'a>) -> Result<(&'a DocumentNode, &'a str), String> { +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 document_node = get_document_node(node_id, context)?; let input_name = context .network_interface .input_name(&node_id, input_index, context.selection_network_path) - .ok_or("input name not found in noise_properties_scale")?; - Ok((document_node, input_name)) + .ok_or("input name not found in query_node_and_input_info")?; + let input_description = context + .network_interface + .input_description(&node_id, input_index, context.selection_network_path) + .ok_or("input description not found in query_node_and_input_info")?; + Ok((document_node, input_name, input_description)) } pub fn query_noise_pattern_state(node_id: NodeId, context: &NodePropertiesContext) -> Result<(bool, bool, bool, bool, bool, bool), String> { @@ -1369,7 +1391,7 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper // Monochrome let monochrome_index = 1; - let monochrome = bool_widget(document_node, node_id, monochrome_index, "Monochrome", CheckboxInput::default(), true); + let monochrome = bool_widget(document_node, node_id, monochrome_index, "Monochrome", "TODO", CheckboxInput::default(), true); let is_monochrome = match document_node.inputs[monochrome_index].as_value() { Some(TaggedValue::Bool(monochrome_choice)) => *monochrome_choice, _ => false, @@ -1422,6 +1444,7 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper node_id, r.0, r.1, + "TODO", NumberInput::default().mode_range().min(-200.).max(200.).value(Some(r.2)).unit("%"), true, ); @@ -1430,6 +1453,7 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper node_id, g.0, g.1, + "TODO", NumberInput::default().mode_range().min(-200.).max(200.).value(Some(g.2)).unit("%"), true, ); @@ -1438,6 +1462,7 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper node_id, b.0, b.1, + "TODO", NumberInput::default().mode_range().min(-200.).max(200.).value(Some(b.2)).unit("%"), true, ); @@ -1446,6 +1471,7 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper node_id, c.0, c.1, + "TODO", NumberInput::default().mode_range().min(-200.).max(200.).value(Some(c.2)).unit("%"), true, ); @@ -1522,14 +1548,14 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp SelectiveColorChoice::Neutrals => ((30, "(Neutrals) Cyan"), (31, "(Neutrals) Magenta"), (32, "(Neutrals) Yellow"), (33, "(Neutrals) Black")), SelectiveColorChoice::Blacks => ((34, "(Blacks) Cyan"), (35, "(Blacks) Magenta"), (36, "(Blacks) Yellow"), (37, "(Blacks) Black")), }; - let cyan = number_widget(document_node, node_id, c.0, c.1, NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true); - let magenta = number_widget(document_node, node_id, m.0, m.1, NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true); - let yellow = number_widget(document_node, node_id, y.0, y.1, NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true); - let black = number_widget(document_node, node_id, k.0, k.1, NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true); + let cyan = number_widget(document_node, node_id, c.0, c.1, "TODO", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true); + let magenta = number_widget(document_node, node_id, m.0, m.1, "TODO", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true); + let yellow = number_widget(document_node, node_id, y.0, y.1, "TODO", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true); + let black = number_widget(document_node, node_id, k.0, k.1, "TODO", NumberInput::default().mode_range().min(-100.).max(100.).unit("%"), true); // Mode let mode_index = 1; - let mut mode = start_widgets(document_node, node_id, mode_index, "Mode", FrontendGraphDataType::General, true); + let mut mode = start_widgets(document_node, node_id, mode_index, "Mode", "TODO", FrontendGraphDataType::General, true); mode.push(Separator::new(SeparatorType::Unrelated).widget_holder()); let Some(input) = document_node.inputs.get(mode_index) else { @@ -1565,7 +1591,7 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp #[cfg(feature = "gpu")] pub(crate) fn _gpu_map_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { - let map = text_widget(document_node, node_id, 1, "Map", true); + let map = text_widget(document_node, node_id, 1, "Map", "TODO", true); vec![LayoutGroup::Row { widgets: map }] } @@ -1584,7 +1610,7 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte return Vec::new(); } }; - let grid_type = grid_type_widget(document_node, node_id, grid_type_index, "Grid Type", true); + let grid_type = grid_type_widget(document_node, node_id, grid_type_index, "Grid Type", "TODO", true); let mut widgets = vec![grid_type]; @@ -1595,21 +1621,21 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte if let Some(&TaggedValue::GridType(grid_type)) = grid_type_input.as_non_exposed_value() { match grid_type { GridType::Rectangular => { - let spacing = vec2_widget(document_node, node_id, spacing_index, "Spacing", "W", "H", " px", Some(0.), add_blank_assist); + let spacing = vec2_widget(document_node, node_id, spacing_index, "Spacing", "TODO", "W", "H", " px", Some(0.), add_blank_assist); widgets.push(spacing); } GridType::Isometric => { let spacing = LayoutGroup::Row { - widgets: number_widget(document_node, node_id, spacing_index, "Spacing", NumberInput::default().label("H").min(0.).unit(" px"), true), + widgets: number_widget(document_node, node_id, spacing_index, "Spacing", "TODO", NumberInput::default().label("H").min(0.).unit(" px"), true), }; - let angles = vec2_widget(document_node, node_id, angles_index, "Angles", "", "", "°", None, add_blank_assist); + let angles = vec2_widget(document_node, node_id, angles_index, "Angles", "TODO", "", "", "°", None, add_blank_assist); widgets.extend([spacing, angles]); } } } - let rows = number_widget(document_node, node_id, rows_index, "Rows", NumberInput::default().min(1.), true); - let columns = number_widget(document_node, node_id, columns_index, "Columns", NumberInput::default().min(1.), true); + let rows = number_widget(document_node, node_id, rows_index, "Rows", "TODO", NumberInput::default().min(1.), true); + let columns = number_widget(document_node, node_id, columns_index, "Columns", "TODO", NumberInput::default().min(1.), true); widgets.extend([LayoutGroup::Row { widgets: rows }, LayoutGroup::Row { widgets: columns }]); @@ -1624,10 +1650,10 @@ pub(crate) fn exposure_properties(node_id: NodeId, context: &mut NodePropertiesC return Vec::new(); } }; - let exposure = number_widget(document_node, node_id, 1, "Exposure", NumberInput::default().min(-20.).max(20.), true); - let offset = number_widget(document_node, node_id, 2, "Offset", NumberInput::default().min(-0.5).max(0.5), true); + let exposure = number_widget(document_node, node_id, 1, "Exposure", "TODO", NumberInput::default().min(-20.).max(20.), true); + let offset = number_widget(document_node, node_id, 2, "Offset", "TODO", NumberInput::default().min(-0.5).max(0.5), true); let gamma_input = NumberInput::default().min(0.01).max(9.99).increment_step(0.1); - let gamma_correction = number_widget(document_node, node_id, 3, "Gamma Correction", gamma_input, true); + let gamma_correction = number_widget(document_node, node_id, 3, "Gamma Correction", "TODO", gamma_input, true); vec![ LayoutGroup::Row { widgets: exposure }, @@ -1651,13 +1677,13 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties let clamped_index = 5; // Size X - let size_x = number_widget(document_node, node_id, size_x_index, "Size X", NumberInput::default(), true); + let size_x = number_widget(document_node, node_id, size_x_index, "Size X", "TODO", NumberInput::default(), true); // Size Y - let size_y = number_widget(document_node, node_id, size_y_index, "Size Y", NumberInput::default(), true); + let size_y = number_widget(document_node, node_id, size_y_index, "Size Y", "TODO", NumberInput::default(), true); // Corner Radius - let mut corner_radius_row_1 = start_widgets(document_node, node_id, corner_radius_index, "Corner Radius", FrontendGraphDataType::Number, true); + let mut corner_radius_row_1 = start_widgets(document_node, node_id, corner_radius_index, "Corner Radius", "TODO", FrontendGraphDataType::Number, true); corner_radius_row_1.push(Separator::new(SeparatorType::Unrelated).widget_holder()); let mut corner_radius_row_2 = vec![Separator::new(SeparatorType::Unrelated).widget_holder()]; @@ -1757,7 +1783,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties } // Clamped - let clamped = bool_widget(document_node, node_id, clamped_index, "Clamped", CheckboxInput::default(), true); + let clamped = bool_widget(document_node, node_id, clamped_index, "Clamped", "TODO", CheckboxInput::default(), true); vec![ LayoutGroup::Row { widgets: size_x }, @@ -2317,11 +2343,14 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper break 'early_return default.clone(); } } + let Some(implementations) = &interpreted_executor::node_registry::NODE_REGISTRY.get(proto_node_identifier) else { log::error!("Could not get implementation for protonode {proto_node_identifier:?}"); return Vec::new(); }; + let proto_node_identifier = proto_node_identifier.clone(); + let mut input_types = implementations .keys() .filter_map(|item| item.inputs.get(input_index)) @@ -2329,10 +2358,12 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper .collect::>(); input_types.sort_by_key(|ty| ty.type_name()); let input_type = input_types.first().cloned(); + let Some(input_type) = input_type else { log::error!("Could not get input type for protonode {proto_node_identifier:?} at index {input_index:?}"); return Vec::new(); }; + input_type.clone() } _ => context.network_interface.input_type(&InputConnector::node(node_id, input_index), context.selection_network_path).0, @@ -2340,6 +2371,7 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper property_from_type(node_id, input_index, &input_type, number_options, context).unwrap_or_else(|value| value) }); + layout.extend(row); } } @@ -2352,7 +2384,7 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper .reference(&node_id, context.selection_network_path) .cloned() .unwrap_or_default() // If there is an error getting the reference, default to empty string - .or_else(||{ + .or_else(|| { // If there is no reference, try to get the proto node name context.network_interface.implementation(&node_id, context.selection_network_path).and_then(|implementation|{ if let DocumentNodeImplementation::ProtoNode(protonode) = implementation { @@ -2363,10 +2395,12 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper }) }) .unwrap_or("Custom Node".to_string()); + let description = context.network_interface.description(&node_id, context.selection_network_path); let visible = context.network_interface.is_visible(&node_id, context.selection_network_path); let pinned = context.network_interface.is_pinned(&node_id, context.selection_network_path); LayoutGroup::Section { name, + description, visible, pinned, id: node_id.0, @@ -2387,7 +2421,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte let backup_color_index = 2; let backup_gradient_index = 3; - let mut widgets_first_row = start_widgets(document_node, node_id, fill_index, "Fill", FrontendGraphDataType::General, true); + let mut widgets_first_row = start_widgets(document_node, node_id, fill_index, "Fill", "TODO", FrontendGraphDataType::General, true); 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(), @@ -2573,24 +2607,24 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) - let line_join_index = 6; let miter_limit_index = 7; - let color = color_widget(document_node, node_id, color_index, "Color", ColorInput::default(), true); - let weight = number_widget(document_node, node_id, weight_index, "Weight", NumberInput::default().unit(" px").min(0.), true); + let color = color_widget(document_node, node_id, color_index, "Color", "TODO", ColorInput::default(), true); + let weight = number_widget(document_node, node_id, weight_index, "Weight", "TODO", NumberInput::default().unit(" px").min(0.), true); let dash_lengths_val = match &document_node.inputs[dash_lengths_index].as_value() { Some(TaggedValue::VecF64(x)) => x, _ => &vec![], }; - let dash_lengths = vec_f64_input(document_node, node_id, dash_lengths_index, "Dash Lengths", TextInput::default().centered(true), true); + let dash_lengths = vec_f64_input(document_node, node_id, dash_lengths_index, "Dash Lengths", "TODO", TextInput::default().centered(true), true); let number_input = NumberInput::default().unit(" px").disabled(dash_lengths_val.is_empty()); - let dash_offset = number_widget(document_node, node_id, dash_offset_index, "Dash Offset", number_input, true); - let line_cap = line_cap_widget(document_node, node_id, line_cap_index, "Line Cap", true); - let line_join = line_join_widget(document_node, node_id, line_join_index, "Line Join", true); + let dash_offset = number_widget(document_node, node_id, dash_offset_index, "Dash Offset", "TODO", number_input, true); + let line_cap = line_cap_widget(document_node, node_id, line_cap_index, "Line Cap", "TODO", true); + let line_join = line_join_widget(document_node, node_id, line_join_index, "Line Join", "TODO", true); let line_join_val = match &document_node.inputs[line_join_index].as_value() { Some(TaggedValue::LineJoin(x)) => x, _ => &LineJoin::Miter, }; let number_input = NumberInput::default().min(0.).disabled(line_join_val != &LineJoin::Miter); - let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", number_input, true); + let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", "TODO", number_input, true); vec![ color, @@ -2616,16 +2650,16 @@ pub fn offset_path_properties(node_id: NodeId, context: &mut NodePropertiesConte let miter_limit_index = 3; let number_input = NumberInput::default().unit(" px"); - let distance = number_widget(document_node, node_id, distance_index, "Offset", number_input, true); + let distance = number_widget(document_node, node_id, distance_index, "Offset", "TODO", number_input, true); - let line_join = line_join_widget(document_node, node_id, line_join_index, "Line Join", true); + let line_join = line_join_widget(document_node, node_id, line_join_index, "Line Join", "TODO", true); let line_join_val = match &document_node.inputs[line_join_index].as_value() { Some(TaggedValue::LineJoin(x)) => x, _ => &LineJoin::Miter, }; let number_input = NumberInput::default().min(0.).disabled(line_join_val != &LineJoin::Miter); - let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", number_input, true); + let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", "TODO", number_input, true); vec![LayoutGroup::Row { widgets: distance }, line_join, LayoutGroup::Row { widgets: miter_limit }] } @@ -2643,7 +2677,7 @@ pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> let operation_b_index = 2; let expression = (|| { - let mut widgets = start_widgets(document_node, node_id, expression_index, "Expression", FrontendGraphDataType::General, true); + let mut widgets = start_widgets(document_node, node_id, expression_index, "Expression", "TODO", FrontendGraphDataType::General, true); let Some(input) = document_node.inputs.get(expression_index) else { log::warn!("A widget failed to be built because its node's input index is invalid."); @@ -2677,7 +2711,7 @@ pub fn math_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> } widgets })(); - let operand_b = number_widget(document_node, node_id, operation_b_index, "Operand B", NumberInput::default(), true); + let operand_b = number_widget(document_node, node_id, operation_b_index, "Operand B", "TODO", NumberInput::default(), true); let operand_a_hint = vec![TextLabel::new("(Operand A is the primary input)").widget_holder()]; vec![ diff --git a/editor/src/messages/portfolio/document/node_graph/utility_types.rs b/editor/src/messages/portfolio/document/node_graph/utility_types.rs index b23e048d..b2d5dc5d 100644 --- a/editor/src/messages/portfolio/document/node_graph/utility_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/utility_types.rs @@ -48,6 +48,7 @@ pub struct FrontendGraphInput { #[serde(rename = "dataType")] pub data_type: FrontendGraphDataType, pub name: String, + pub description: String, #[serde(rename = "resolvedType")] pub resolved_type: Option, #[serde(rename = "validTypes")] @@ -61,6 +62,7 @@ pub struct FrontendGraphOutput { #[serde(rename = "dataType")] pub data_type: FrontendGraphDataType, pub name: String, + pub description: String, #[serde(rename = "resolvedType")] pub resolved_type: Option, #[serde(rename = "connectedTo")] diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface.rs b/editor/src/messages/portfolio/document/utility_types/network_interface.rs index 8d240973..c7952fd8 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface.rs @@ -818,6 +818,7 @@ impl NodeNetworkInterface { FrontendGraphOutput { data_type, name: import_name, + description: String::new(), resolved_type: Some(format!("{input_type:?} from {type_source:?}")), connected_to, }, @@ -902,6 +903,7 @@ impl NodeNetworkInterface { FrontendGraphInput { data_type: frontend_data_type, name: export_name, + description: String::new(), resolved_type: input_type.map(|(export_type, source)| format!("{export_type:?} from {source:?}")), valid_types: self.valid_input_types(&InputConnector::Export(*export_index), network_path).iter().map(|ty| ty.to_string()).collect(), connected_to, @@ -1132,6 +1134,14 @@ impl NodeNetworkInterface { value.as_str() } + pub fn input_description(&self, node_id: &NodeId, index: usize, network_path: &[NodeId]) -> Option<&str> { + let Some(value) = self.input_metadata(node_id, index, "input_description", network_path) else { + log::error!("Could not get input_description for node {node_id} index {index}"); + return None; + }; + value.as_str() + } + pub fn input_properties_row(&self, node_id: &NodeId, index: usize, network_path: &[NodeId]) -> Option<&PropertiesRow> { self.node_metadata(node_id, network_path) .and_then(|node_metadata| node_metadata.persistent_metadata.input_properties.get(index)) @@ -1145,16 +1155,7 @@ impl NodeNetworkInterface { input_row.input_data.get(field) } - // Use frontend display name instead - fn display_name(&self, node_id: &NodeId, network_path: &[NodeId]) -> String { - let Some(node_metadata) = self.node_metadata(node_id, network_path) else { - log::error!("Could not get node_metadata in display_name"); - return "".to_string(); - }; - node_metadata.persistent_metadata.display_name.clone() - } - - pub fn frontend_display_name(&self, node_id: &NodeId, network_path: &[NodeId]) -> String { + pub fn display_name(&self, node_id: &NodeId, network_path: &[NodeId]) -> String { let is_layer = self .node_metadata(node_id, network_path) .expect("Could not get persistent node metadata in untitled_layer_label") @@ -1165,17 +1166,30 @@ impl NodeNetworkInterface { return "".to_string(); }; - if self.display_name(node_id, network_path).is_empty() { + let display_name = if let Some(node_metadata) = self.node_metadata(node_id, network_path) { + node_metadata.persistent_metadata.display_name.clone() + } else { + log::error!("Could not get node_metadata in display_name"); + String::new() + }; + + if display_name.is_empty() { if is_layer && *reference == Some("Merge".to_string()) { "Untitled Layer".to_string() } else { reference.clone().unwrap_or("Untitled Node".to_string()) } } else { - self.display_name(node_id, network_path) + display_name } } + pub fn description(&self, node_id: &NodeId, network_path: &[NodeId]) -> String { + self.get_node_definition(network_path, *node_id) + .and_then(|node_definition| Some(node_definition.description.to_string())) + .unwrap_or_default() + } + pub fn is_locked(&self, node_id: &NodeId, network_path: &[NodeId]) -> bool { let Some(node_metadata) = self.node_metadata(node_id, network_path) else { log::error!("Could not get persistent node metadata in is_locked for node {node_id}"); @@ -1472,7 +1486,7 @@ impl NodeNetworkInterface { _ => {} }; - let name = self.frontend_display_name(node_id, network_path); + let name = self.display_name(node_id, network_path); div.set_text_content(Some(&name)); @@ -3415,9 +3429,9 @@ impl NodeNetworkInterface { return; }; if insert_index == -1 { - node_metadata.persistent_metadata.input_properties.push(input_name.into()); + node_metadata.persistent_metadata.input_properties.push((input_name, "TODO").into()); } else { - node_metadata.persistent_metadata.input_properties.insert(insert_index as usize, input_name.into()); + node_metadata.persistent_metadata.input_properties.insert(insert_index as usize, (input_name, "TODO").into()); } // Clear the reference to the nodes definition @@ -6159,7 +6173,7 @@ pub enum WidgetOverride { #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct PropertiesRow { /// A general datastore than can store key value pairs of any types for any input - // TODO: This could be simplified to just Value, and key value pairs could be stored as the Object variant + // TODO: This could be simplified to just Value, and key value pairs could be stored as the Value::Object variant pub input_data: HashMap, // An input can override a widget, which would otherwise be automatically generated from the type // The string is the identifier to the widget override function stored in INPUT_OVERRIDES @@ -6168,20 +6182,21 @@ pub struct PropertiesRow { impl Default for PropertiesRow { fn default() -> Self { - "".into() + ("", "TODO").into() } } -impl From<&str> for PropertiesRow { - fn from(input_name: &str) -> Self { - PropertiesRow::with_override(input_name, WidgetOverride::None) +impl From<(&str, &str)> for PropertiesRow { + fn from(input_name_and_description: (&str, &str)) -> Self { + PropertiesRow::with_override(input_name_and_description.0, input_name_and_description.1, WidgetOverride::None) } } impl PropertiesRow { - pub fn with_override(input_name: &str, widget_override: WidgetOverride) -> Self { + pub fn with_override(input_name: &str, input_description: &str, widget_override: WidgetOverride) -> Self { let mut input_data = HashMap::new(); input_data.insert("input_name".to_string(), Value::String(input_name.to_string())); + input_data.insert("input_description".to_string(), Value::String(input_description.to_string())); match widget_override { WidgetOverride::None => PropertiesRow { input_data, widget_override: None }, WidgetOverride::Hidden => PropertiesRow { @@ -6351,7 +6366,7 @@ impl From for DocumentNodePersistentMe .as_ref() .and_then(|reference| resolve_document_node_type(reference)) .map(|definition| definition.node_template.persistent_node_metadata.input_properties.clone()) - .unwrap_or(old.input_names.into_iter().map(|name| name.as_str().into()).collect()); + .unwrap_or(old.input_names.into_iter().map(|name| (name.as_str(), "TODO").into()).collect()); DocumentNodePersistentMetadata { reference: old.reference, diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index b5ecf3dd..945de4c7 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -830,7 +830,7 @@ impl MessageHandler> for PortfolioMes // Upgrade artboard name being passed as hidden value input to "To Artboard" if reference == "Artboard" && upgrade_from_before_returning_nested_click_targets { - let label = document.network_interface.frontend_display_name(node_id, network_path); + let label = document.network_interface.display_name(node_id, network_path); document .network_interface .set_input(&InputConnector::node(NodeId(0), 1), NodeInput::value(TaggedValue::String(label), false), &[*node_id]); diff --git a/frontend/src/components/views/Graph.svelte b/frontend/src/components/views/Graph.svelte index 702287b3..cec9c2c1 100644 --- a/frontend/src/components/views/Graph.svelte +++ b/frontend/src/components/views/Graph.svelte @@ -1069,7 +1069,7 @@
{#each exposedInputsOutputs as [input, output]}
- + {input !== undefined ? input.name : output.name}
diff --git a/frontend/src/components/widgets/WidgetSection.svelte b/frontend/src/components/widgets/WidgetSection.svelte index ccb07f03..2e641f40 100644 --- a/frontend/src/components/widgets/WidgetSection.svelte +++ b/frontend/src/components/widgets/WidgetSection.svelte @@ -26,7 +26,7 @@