@@ -121,6 +121,9 @@ pub(crate) fn property_from_type(
121121 index : usize ,
122122 ty : & Type ,
123123 number_options : ( Option < f64 > , Option < f64 > , Option < ( f64 , f64 ) > ) ,
124+ unit : Option < & str > ,
125+ display_decimal_places : Option < u32 > ,
126+ step : Option < f64 > ,
124127 context : & mut NodePropertiesContext ,
125128) -> Result < Vec < LayoutGroup > , Vec < LayoutGroup > > {
126129 let Some ( network) = context. network_interface . nested_network ( context. selection_network_path ) else {
@@ -142,6 +145,15 @@ pub(crate) fn property_from_type(
142145 number_max = Some ( range_end) ;
143146 number_input = number_input. mode_range ( ) . min ( range_start) . max ( range_end) ;
144147 }
148+ if let Some ( unit) = unit {
149+ number_input = number_input. unit ( unit) ;
150+ }
151+ if let Some ( display_decimal_places) = display_decimal_places {
152+ number_input = number_input. display_decimal_places ( display_decimal_places) ;
153+ }
154+ if let Some ( step) = step {
155+ number_input = number_input. step ( step) ;
156+ }
145157
146158 let min = |x : f64 | number_min. unwrap_or ( x) ;
147159 let max = |x : f64 | number_max. unwrap_or ( x) ;
@@ -155,15 +167,15 @@ pub(crate) fn property_from_type(
155167 // Aliased types (ambiguous values)
156168 Some ( "Percentage" ) => number_widget ( default_info, number_input. percentage ( ) . min ( min ( 0. ) ) . max ( max ( 100. ) ) ) . into ( ) ,
157169 Some ( "SignedPercentage" ) => number_widget ( default_info, number_input. percentage ( ) . min ( min ( -100. ) ) . max ( max ( 100. ) ) ) . into ( ) ,
158- Some ( "Angle" ) => number_widget ( default_info, number_input. mode_range ( ) . min ( min ( -180. ) ) . max ( max ( 180. ) ) . unit ( "°" ) ) . into ( ) ,
159- Some ( "Multiplier" ) => number_widget ( default_info, number_input. unit ( "x" ) ) . into ( ) ,
160- Some ( "PixelLength" ) => number_widget ( default_info, number_input. min ( min ( 0. ) ) . unit ( " px" ) ) . into ( ) ,
170+ Some ( "Angle" ) => number_widget ( default_info, number_input. mode_range ( ) . min ( min ( -180. ) ) . max ( max ( 180. ) ) . unit ( unit . unwrap_or ( "°" ) ) ) . into ( ) ,
171+ Some ( "Multiplier" ) => number_widget ( default_info, number_input. unit ( unit . unwrap_or ( "x" ) ) ) . into ( ) ,
172+ Some ( "PixelLength" ) => number_widget ( default_info, number_input. min ( min ( 0. ) ) . unit ( unit . unwrap_or ( " px" ) ) ) . into ( ) ,
161173 Some ( "Length" ) => number_widget ( default_info, number_input. min ( min ( 0. ) ) ) . into ( ) ,
162174 Some ( "Fraction" ) => number_widget ( default_info, number_input. mode_range ( ) . min ( min ( 0. ) ) . max ( max ( 1. ) ) ) . into ( ) ,
163175 Some ( "IntegerCount" ) => number_widget ( default_info, number_input. int ( ) . min ( min ( 1. ) ) ) . into ( ) ,
164176 Some ( "SeedValue" ) => number_widget ( default_info, number_input. int ( ) . min ( min ( 0. ) ) ) . into ( ) ,
165- Some ( "Resolution" ) => vector2_widget ( default_info, "W" , "H" , " px" , Some ( 64. ) ) ,
166- Some ( "PixelSize" ) => vector2_widget ( default_info, "X" , "Y" , " px" , None ) ,
177+ Some ( "Resolution" ) => coordinate_widget ( default_info, "W" , "H" , unit . unwrap_or ( " px" ) , Some ( 64. ) ) ,
178+ Some ( "PixelSize" ) => coordinate_widget ( default_info, "X" , "Y" , unit . unwrap_or ( " px" ) , None ) ,
167179
168180 // For all other types, use TypeId-based matching
169181 _ => {
@@ -177,14 +189,14 @@ pub(crate) fn property_from_type(
177189 Some ( x) if x == TypeId :: of :: < u64 > ( ) => number_widget ( default_info, number_input. int ( ) . min ( min ( 0. ) ) ) . into ( ) ,
178190 Some ( x) if x == TypeId :: of :: < bool > ( ) => bool_widget ( default_info, CheckboxInput :: default ( ) ) . into ( ) ,
179191 Some ( x) if x == TypeId :: of :: < String > ( ) => text_widget ( default_info) . into ( ) ,
180- Some ( x) if x == TypeId :: of :: < DVec2 > ( ) => vector2_widget ( default_info, "X" , "Y" , "" , None ) ,
181- Some ( x) if x == TypeId :: of :: < UVec2 > ( ) => vector2_widget ( default_info, "X" , "Y" , "" , Some ( 0. ) ) ,
182- Some ( x) if x == TypeId :: of :: < IVec2 > ( ) => vector2_widget ( default_info, "X" , "Y" , "" , None ) ,
192+ Some ( x) if x == TypeId :: of :: < DVec2 > ( ) => coordinate_widget ( default_info, "X" , "Y" , "" , None ) ,
193+ Some ( x) if x == TypeId :: of :: < UVec2 > ( ) => coordinate_widget ( default_info, "X" , "Y" , "" , Some ( 0. ) ) ,
194+ Some ( x) if x == TypeId :: of :: < IVec2 > ( ) => coordinate_widget ( default_info, "X" , "Y" , "" , None ) ,
183195 // ==========================
184196 // PRIMITIVE COLLECTION TYPES
185197 // ==========================
186198 Some ( x) if x == TypeId :: of :: < Vec < f64 > > ( ) => array_of_number_widget ( default_info, TextInput :: default ( ) ) . into ( ) ,
187- Some ( x) if x == TypeId :: of :: < Vec < DVec2 > > ( ) => array_of_vector2_widget ( default_info, TextInput :: default ( ) ) . into ( ) ,
199+ Some ( x) if x == TypeId :: of :: < Vec < DVec2 > > ( ) => array_of_coordinates_widget ( default_info, TextInput :: default ( ) ) . into ( ) ,
188200 // ====================
189201 // GRAPHICAL DATA TYPES
190202 // ====================
@@ -249,8 +261,8 @@ pub(crate) fn property_from_type(
249261 }
250262 }
251263 Type :: Generic ( _) => vec ! [ TextLabel :: new( "Generic type (not supported)" ) . widget_holder( ) ] . into ( ) ,
252- Type :: Fn ( _, out) => return property_from_type ( node_id, index, out, number_options, context) ,
253- Type :: Future ( out) => return property_from_type ( node_id, index, out, number_options, context) ,
264+ Type :: Fn ( _, out) => return property_from_type ( node_id, index, out, number_options, unit , display_decimal_places , step , context) ,
265+ Type :: Future ( out) => return property_from_type ( node_id, index, out, number_options, unit , display_decimal_places , step , context) ,
254266 } ;
255267
256268 extra_widgets. push ( widgets) ;
@@ -334,6 +346,15 @@ pub fn reference_point_widget(parameter_widgets_info: ParameterWidgetsInfo, disa
334346 if let Some ( & TaggedValue :: ReferencePoint ( reference_point) ) = input. as_non_exposed_value ( ) {
335347 widgets. extend_from_slice ( & [
336348 Separator :: new ( SeparatorType :: Unrelated ) . widget_holder ( ) ,
349+ CheckboxInput :: new ( reference_point != ReferencePoint :: None )
350+ . on_update ( update_value (
351+ move |x : & CheckboxInput | TaggedValue :: ReferencePoint ( if x. checked { ReferencePoint :: Center } else { ReferencePoint :: None } ) ,
352+ node_id,
353+ index,
354+ ) )
355+ . disabled ( disabled)
356+ . widget_holder ( ) ,
357+ Separator :: new ( SeparatorType :: Related ) . widget_holder ( ) ,
337358 ReferencePointInput :: new ( reference_point)
338359 . on_update ( update_value ( move |x : & ReferencePointInput | TaggedValue :: ReferencePoint ( x. value ) , node_id, index) )
339360 . disabled ( disabled)
@@ -489,7 +510,7 @@ pub fn footprint_widget(parameter_widgets_info: ParameterWidgetsInfo, extra_widg
489510 last. clone ( )
490511}
491512
492- pub fn vector2_widget ( parameter_widgets_info : ParameterWidgetsInfo , x : & str , y : & str , unit : & str , min : Option < f64 > ) -> LayoutGroup {
513+ pub fn coordinate_widget ( parameter_widgets_info : ParameterWidgetsInfo , x : & str , y : & str , unit : & str , min : Option < f64 > ) -> LayoutGroup {
493514 let ParameterWidgetsInfo { document_node, node_id, index, .. } = parameter_widgets_info;
494515
495516 let mut widgets = start_widgets ( parameter_widgets_info, FrontendGraphDataType :: Number ) ;
@@ -632,7 +653,7 @@ pub fn array_of_number_widget(parameter_widgets_info: ParameterWidgetsInfo, text
632653 widgets
633654}
634655
635- pub fn array_of_vector2_widget ( parameter_widgets_info : ParameterWidgetsInfo , text_props : TextInput ) -> Vec < WidgetHolder > {
656+ pub fn array_of_coordinates_widget ( parameter_widgets_info : ParameterWidgetsInfo , text_props : TextInput ) -> Vec < WidgetHolder > {
636657 let ParameterWidgetsInfo { document_node, node_id, index, .. } = parameter_widgets_info;
637658
638659 let mut widgets = start_widgets ( parameter_widgets_info, FrontendGraphDataType :: Number ) ;
@@ -1172,7 +1193,7 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte
11721193 if let Some ( & TaggedValue :: GridType ( grid_type) ) = grid_type_input. as_non_exposed_value ( ) {
11731194 match grid_type {
11741195 GridType :: Rectangular => {
1175- let spacing = vector2_widget ( ParameterWidgetsInfo :: from_index ( document_node, node_id, spacing_index, true , context) , "W" , "H" , " px" , Some ( 0. ) ) ;
1196+ let spacing = coordinate_widget ( ParameterWidgetsInfo :: from_index ( document_node, node_id, spacing_index, true , context) , "W" , "H" , " px" , Some ( 0. ) ) ;
11761197 widgets. push ( spacing) ;
11771198 }
11781199 GridType :: Isometric => {
@@ -1182,7 +1203,7 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte
11821203 NumberInput :: default ( ) . label ( "H" ) . min ( 0. ) . unit ( " px" ) ,
11831204 ) ,
11841205 } ;
1185- let angles = vector2_widget ( ParameterWidgetsInfo :: from_index ( document_node, node_id, angles_index, true , context) , "" , "" , "°" , None ) ;
1206+ let angles = coordinate_widget ( ParameterWidgetsInfo :: from_index ( document_node, node_id, angles_index, true , context) , "" , "" , "°" , None ) ;
11861207 widgets. extend ( [ spacing, angles] ) ;
11871208 }
11881209 }
@@ -1386,6 +1407,9 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper
13861407 } ;
13871408
13881409 let mut number_options = ( None , None , None ) ;
1410+ let mut display_decimal_places = None ;
1411+ let mut step = None ;
1412+ let mut unit_suffix = None ;
13891413 let input_type = match implementation {
13901414 DocumentNodeImplementation :: ProtoNode ( proto_node_identifier) => ' early_return: {
13911415 if let Some ( field) = graphene_core:: registry:: NODE_METADATA
@@ -1395,6 +1419,9 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper
13951419 . and_then ( |metadata| metadata. fields . get ( input_index) )
13961420 {
13971421 number_options = ( field. number_min , field. number_max , field. number_mode_range ) ;
1422+ display_decimal_places = field. number_display_decimal_places ;
1423+ unit_suffix = field. unit ;
1424+ step = field. number_step ;
13981425 if let Some ( ref default) = field. default_type {
13991426 break ' early_return default. clone ( ) ;
14001427 }
@@ -1408,7 +1435,7 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper
14081435 let mut input_types = implementations
14091436 . keys ( )
14101437 . filter_map ( |item| item. inputs . get ( input_index) )
1411- . filter ( |ty| property_from_type ( node_id, input_index, ty, number_options, context) . is_ok ( ) )
1438+ . filter ( |ty| property_from_type ( node_id, input_index, ty, number_options, unit_suffix , display_decimal_places , step , context) . is_ok ( ) )
14121439 . collect :: < Vec < _ > > ( ) ;
14131440 input_types. sort_by_key ( |ty| ty. type_name ( ) ) ;
14141441 let input_type = input_types. first ( ) . cloned ( ) ;
@@ -1422,7 +1449,7 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper
14221449 _ => context. network_interface . input_type ( & InputConnector :: node ( node_id, input_index) , context. selection_network_path ) . 0 ,
14231450 } ;
14241451
1425- property_from_type ( node_id, input_index, & input_type, number_options, context) . unwrap_or_else ( |value| value)
1452+ property_from_type ( node_id, input_index, & input_type, number_options, unit_suffix , display_decimal_places , step , context) . unwrap_or_else ( |value| value)
14261453 } ) ;
14271454
14281455 layout. extend ( row) ;
0 commit comments