@@ -21,9 +21,10 @@ use graphene_core::vector::misc::CentroidType;
21
21
use graphene_core:: vector:: style:: { GradientType , LineCap , LineJoin } ;
22
22
use graphene_std:: animation:: RealTimeMode ;
23
23
use graphene_std:: application_io:: TextureFrameTable ;
24
+ use graphene_std:: ops:: XY ;
24
25
use graphene_std:: transform:: Footprint ;
25
26
use graphene_std:: vector:: VectorDataTable ;
26
- use graphene_std:: vector:: misc:: BooleanOperation ;
27
+ use graphene_std:: vector:: misc:: { BooleanOperation , GridType } ;
27
28
use graphene_std:: vector:: style:: { Fill , FillChoice , FillType , GradientStops } ;
28
29
use graphene_std:: { GraphicGroupTable , RasterFrame } ;
29
30
@@ -168,6 +169,7 @@ pub(crate) fn property_from_type(
168
169
Some ( x) if x == TypeId :: of :: < RealTimeMode > ( ) => real_time_mode ( document_node, node_id, index, name, true ) ,
169
170
Some ( x) if x == TypeId :: of :: < RedGreenBlue > ( ) => color_channel ( document_node, node_id, index, name, true ) ,
170
171
Some ( x) if x == TypeId :: of :: < RedGreenBlueAlpha > ( ) => rgba_channel ( document_node, node_id, index, name, true ) ,
172
+ Some ( x) if x == TypeId :: of :: < XY > ( ) => xy_components ( document_node, node_id, index, name, true ) ,
171
173
Some ( x) if x == TypeId :: of :: < NoiseType > ( ) => noise_type ( document_node, node_id, index, name, true ) ,
172
174
Some ( x) if x == TypeId :: of :: < FractalType > ( ) => fractal_type ( document_node, node_id, index, name, true , false ) ,
173
175
Some ( x) if x == TypeId :: of :: < CellularDistanceFunction > ( ) => cellular_distance_function ( document_node, node_id, index, name, true , false ) ,
@@ -185,6 +187,7 @@ pub(crate) fn property_from_type(
185
187
. widget_holder( ) ,
186
188
]
187
189
. into ( ) ,
190
+ Some ( x) if x == TypeId :: of :: < GridType > ( ) => grid_type_widget ( document_node, node_id, index, name, true ) ,
188
191
Some ( x) if x == TypeId :: of :: < LineCap > ( ) => line_cap_widget ( document_node, node_id, index, name, true ) ,
189
192
Some ( x) if x == TypeId :: of :: < LineJoin > ( ) => line_join_widget ( document_node, node_id, index, name, true ) ,
190
193
Some ( x) if x == TypeId :: of :: < FillType > ( ) => vec ! [
@@ -567,6 +570,28 @@ pub fn vec2_widget(
567
570
. widget_holder ( ) ,
568
571
] ) ;
569
572
}
573
+ Some ( & TaggedValue :: F64 ( value) ) => {
574
+ widgets. extend_from_slice ( & [
575
+ Separator :: new ( SeparatorType :: Unrelated ) . widget_holder ( ) ,
576
+ NumberInput :: new ( Some ( value) )
577
+ . label ( x)
578
+ . unit ( unit)
579
+ . min ( min. unwrap_or ( -( ( 1_u64 << f64:: MANTISSA_DIGITS ) as f64 ) ) )
580
+ . max ( ( 1_u64 << f64:: MANTISSA_DIGITS ) as f64 )
581
+ . on_update ( update_value ( move |input : & NumberInput | TaggedValue :: DVec2 ( DVec2 :: new ( input. value . unwrap ( ) , value) ) , node_id, index) )
582
+ . on_commit ( commit_value)
583
+ . widget_holder ( ) ,
584
+ Separator :: new ( SeparatorType :: Related ) . widget_holder ( ) ,
585
+ NumberInput :: new ( Some ( value) )
586
+ . label ( y)
587
+ . unit ( unit)
588
+ . min ( min. unwrap_or ( -( ( 1_u64 << f64:: MANTISSA_DIGITS ) as f64 ) ) )
589
+ . max ( ( 1_u64 << f64:: MANTISSA_DIGITS ) as f64 )
590
+ . on_update ( update_value ( move |input : & NumberInput | TaggedValue :: DVec2 ( DVec2 :: new ( value, input. value . unwrap ( ) ) ) , node_id, index) )
591
+ . on_commit ( commit_value)
592
+ . widget_holder ( ) ,
593
+ ] ) ;
594
+ }
570
595
_ => { }
571
596
}
572
597
@@ -745,6 +770,15 @@ pub fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize
745
770
. widget_holder ( ) ,
746
771
] ) ;
747
772
}
773
+ Some ( & TaggedValue :: DVec2 ( dvec2) ) => widgets. extend_from_slice ( & [
774
+ Separator :: new ( SeparatorType :: Unrelated ) . widget_holder ( ) ,
775
+ number_props
776
+ // We use an arbitrary `y` instead of an arbitrary `x` here because the "Grid" node's "Spacing" value's height should be used from rectangular mode when transferred to "Y Spacing" in isometric mode
777
+ . value ( Some ( dvec2. y ) )
778
+ . on_update ( update_value ( move |x : & NumberInput | TaggedValue :: F64 ( x. value . unwrap ( ) ) , node_id, index) )
779
+ . on_commit ( commit_value)
780
+ . widget_holder ( ) ,
781
+ ] ) ,
748
782
_ => { }
749
783
}
750
784
@@ -840,6 +874,33 @@ pub fn rgba_channel(document_node: &DocumentNode, node_id: NodeId, index: usize,
840
874
LayoutGroup :: Row { widgets } . with_tooltip ( "Color Channel" )
841
875
}
842
876
877
+ pub fn xy_components ( document_node : & DocumentNode , node_id : NodeId , index : usize , name : & str , blank_assist : bool ) -> LayoutGroup {
878
+ let mut widgets = start_widgets ( document_node, node_id, index, name, FrontendGraphDataType :: General , blank_assist) ;
879
+ let Some ( input) = document_node. inputs . get ( index) else {
880
+ log:: warn!( "A widget failed to be built because its node's input index is invalid." ) ;
881
+ return LayoutGroup :: Row { widgets : vec ! [ ] } ;
882
+ } ;
883
+ if let Some ( & TaggedValue :: XY ( mode) ) = input. as_non_exposed_value ( ) {
884
+ let calculation_modes = [ XY :: X , XY :: Y ] ;
885
+ let mut entries = Vec :: with_capacity ( calculation_modes. len ( ) ) ;
886
+ for method in calculation_modes {
887
+ entries. push (
888
+ MenuListEntry :: new ( format ! ( "{method:?}" ) )
889
+ . label ( method. to_string ( ) )
890
+ . on_update ( update_value ( move |_| TaggedValue :: XY ( method) , node_id, index) )
891
+ . on_commit ( commit_value) ,
892
+ ) ;
893
+ }
894
+ let entries = vec ! [ entries] ;
895
+
896
+ widgets. extend_from_slice ( & [
897
+ Separator :: new ( SeparatorType :: Unrelated ) . widget_holder ( ) ,
898
+ DropdownInput :: new ( entries) . selected_index ( Some ( mode as u32 ) ) . widget_holder ( ) ,
899
+ ] ) ;
900
+ }
901
+ LayoutGroup :: Row { widgets } . with_tooltip ( "X or Y Component of Vector2" )
902
+ }
903
+
843
904
// TODO: Generalize this instead of using a separate function per dropdown menu enum
844
905
pub fn noise_type ( document_node : & DocumentNode , node_id : NodeId , index : usize , name : & str , blank_assist : bool ) -> LayoutGroup {
845
906
let mut widgets = start_widgets ( document_node, node_id, index, name, FrontendGraphDataType :: General , blank_assist) ;
@@ -1064,6 +1125,31 @@ pub fn boolean_operation_radio_buttons(document_node: &DocumentNode, node_id: No
1064
1125
LayoutGroup :: Row { widgets }
1065
1126
}
1066
1127
1128
+ pub fn grid_type_widget ( document_node : & DocumentNode , node_id : NodeId , index : usize , name : & str , blank_assist : bool ) -> LayoutGroup {
1129
+ let mut widgets = start_widgets ( document_node, node_id, index, name, FrontendGraphDataType :: General , blank_assist) ;
1130
+ let Some ( input) = document_node. inputs . get ( index) else {
1131
+ log:: warn!( "A widget failed to be built because its node's input index is invalid." ) ;
1132
+ return LayoutGroup :: Row { widgets : vec ! [ ] } ;
1133
+ } ;
1134
+ if let Some ( & TaggedValue :: GridType ( grid_type) ) = input. as_non_exposed_value ( ) {
1135
+ let entries = [ ( "Rectangular" , GridType :: Rectangular ) , ( "Isometric" , GridType :: Isometric ) ]
1136
+ . into_iter ( )
1137
+ . map ( |( name, val) | {
1138
+ RadioEntryData :: new ( format ! ( "{val:?}" ) )
1139
+ . label ( name)
1140
+ . on_update ( update_value ( move |_| TaggedValue :: GridType ( val) , node_id, index) )
1141
+ . on_commit ( commit_value)
1142
+ } )
1143
+ . collect ( ) ;
1144
+
1145
+ widgets. extend_from_slice ( & [
1146
+ Separator :: new ( SeparatorType :: Unrelated ) . widget_holder ( ) ,
1147
+ RadioInput :: new ( entries) . selected_index ( Some ( grid_type as u32 ) ) . widget_holder ( ) ,
1148
+ ] ) ;
1149
+ }
1150
+ LayoutGroup :: Row { widgets }
1151
+ }
1152
+
1067
1153
pub fn line_cap_widget ( document_node : & DocumentNode , node_id : NodeId , index : usize , name : & str , blank_assist : bool ) -> LayoutGroup {
1068
1154
let mut widgets = start_widgets ( document_node, node_id, index, name, FrontendGraphDataType :: General , blank_assist) ;
1069
1155
let Some ( input) = document_node. inputs . get ( index) else {
@@ -1484,6 +1570,52 @@ pub(crate) fn _gpu_map_properties(document_node: &DocumentNode, node_id: NodeId,
1484
1570
vec ! [ LayoutGroup :: Row { widgets: map } ]
1485
1571
}
1486
1572
1573
+ pub ( crate ) fn grid_properties ( node_id : NodeId , context : & mut NodePropertiesContext ) -> Vec < LayoutGroup > {
1574
+ let grid_type_index = 1 ;
1575
+ let spacing_index = 2 ;
1576
+ let angles_index = 3 ;
1577
+ let rows_index = 4 ;
1578
+ let columns_index = 5 ;
1579
+
1580
+ let document_node = match get_document_node ( node_id, context) {
1581
+ Ok ( document_node) => document_node,
1582
+ Err ( err) => {
1583
+ log:: error!( "Could not get document node in exposure_properties: {err}" ) ;
1584
+ return Vec :: new ( ) ;
1585
+ }
1586
+ } ;
1587
+ let grid_type = grid_type_widget ( document_node, node_id, grid_type_index, "Grid Type" , true ) ;
1588
+
1589
+ let mut widgets = vec ! [ grid_type] ;
1590
+
1591
+ let Some ( grid_type_input) = document_node. inputs . get ( grid_type_index) else {
1592
+ log:: warn!( "A widget failed to be built because its node's input index is invalid." ) ;
1593
+ return vec ! [ ] ;
1594
+ } ;
1595
+ if let Some ( & TaggedValue :: GridType ( grid_type) ) = grid_type_input. as_non_exposed_value ( ) {
1596
+ match grid_type {
1597
+ GridType :: Rectangular => {
1598
+ let spacing = vec2_widget ( document_node, node_id, spacing_index, "Spacing" , "W" , "H" , " px" , Some ( 0. ) , add_blank_assist) ;
1599
+ widgets. push ( spacing) ;
1600
+ }
1601
+ GridType :: Isometric => {
1602
+ let spacing = LayoutGroup :: Row {
1603
+ widgets : number_widget ( document_node, node_id, spacing_index, "Spacing" , NumberInput :: default ( ) . label ( "H" ) . min ( 0. ) . unit ( " px" ) , true ) ,
1604
+ } ;
1605
+ let angles = vec2_widget ( document_node, node_id, angles_index, "Angles" , "" , "" , "°" , None , add_blank_assist) ;
1606
+ widgets. extend ( [ spacing, angles] ) ;
1607
+ }
1608
+ }
1609
+ }
1610
+
1611
+ let rows = number_widget ( document_node, node_id, rows_index, "Rows" , NumberInput :: default ( ) . min ( 1. ) , true ) ;
1612
+ let columns = number_widget ( document_node, node_id, columns_index, "Columns" , NumberInput :: default ( ) . min ( 1. ) , true ) ;
1613
+
1614
+ widgets. extend ( [ LayoutGroup :: Row { widgets : rows } , LayoutGroup :: Row { widgets : columns } ] ) ;
1615
+
1616
+ widgets
1617
+ }
1618
+
1487
1619
pub ( crate ) fn exposure_properties ( node_id : NodeId , context : & mut NodePropertiesContext ) -> Vec < LayoutGroup > {
1488
1620
let document_node = match get_document_node ( node_id, context) {
1489
1621
Ok ( document_node) => document_node,
0 commit comments