@@ -12,6 +12,7 @@ use syn::{
1212} ;
1313
1414use crate :: codegen:: generate_node_code;
15+ use crate :: shader_nodes:: ShaderNodeType ;
1516
1617#[ derive( Debug ) ]
1718pub ( crate ) struct Implementation {
@@ -45,6 +46,10 @@ pub(crate) struct NodeFnAttributes {
4546 pub ( crate ) path : Option < Path > ,
4647 pub ( crate ) skip_impl : bool ,
4748 pub ( crate ) properties_string : Option < LitStr > ,
49+ /// whether to `#[cfg]` gate the node implementation, defaults to None
50+ pub ( crate ) cfg : Option < TokenStream2 > ,
51+ /// if this node should get a gpu implementation, defaults to None
52+ pub ( crate ) shader_node : Option < ShaderNodeType > ,
4853 // Add more attributes as needed
4954}
5055
@@ -184,15 +189,19 @@ impl Parse for NodeFnAttributes {
184189 let mut path = None ;
185190 let mut skip_impl = false ;
186191 let mut properties_string = None ;
192+ let mut cfg = None ;
193+ let mut shader_node = None ;
187194
188195 let content = input;
189196 // let content;
190197 // syn::parenthesized!(content in input);
191198
192199 let nested = content. call ( Punctuated :: < Meta , Comma > :: parse_terminated) ?;
193200 for meta in nested {
194- match meta {
195- Meta :: List ( meta) if meta. path . is_ident ( "category" ) => {
201+ let name = meta. path ( ) . get_ident ( ) . ok_or_else ( || Error :: new_spanned ( meta. path ( ) , "Node macro expects a known Ident, not a path" ) ) ?;
202+ match name. to_string ( ) . as_str ( ) {
203+ "category" => {
204+ let meta = meta. require_list ( ) ?;
196205 if category. is_some ( ) {
197206 return Err ( Error :: new_spanned ( meta, "Multiple 'category' attributes are not allowed" ) ) ;
198207 }
@@ -201,14 +210,16 @@ impl Parse for NodeFnAttributes {
201210 . map_err ( |_| Error :: new_spanned ( meta, "Expected a string literal for 'category', e.g., category(\" Value\" )" ) ) ?;
202211 category = Some ( lit) ;
203212 }
204- Meta :: List ( meta) if meta. path . is_ident ( "name" ) => {
213+ "name" => {
214+ let meta = meta. require_list ( ) ?;
205215 if display_name. is_some ( ) {
206216 return Err ( Error :: new_spanned ( meta, "Multiple 'name' attributes are not allowed" ) ) ;
207217 }
208218 let parsed_name: LitStr = meta. parse_args ( ) . map_err ( |_| Error :: new_spanned ( meta, "Expected a string for 'name', e.g., name(\" Memoize\" )" ) ) ?;
209219 display_name = Some ( parsed_name) ;
210220 }
211- Meta :: List ( meta) if meta. path . is_ident ( "path" ) => {
221+ "path" => {
222+ let meta = meta. require_list ( ) ?;
212223 if path. is_some ( ) {
213224 return Err ( Error :: new_spanned ( meta, "Multiple 'path' attributes are not allowed" ) ) ;
214225 }
@@ -217,13 +228,15 @@ impl Parse for NodeFnAttributes {
217228 . map_err ( |_| Error :: new_spanned ( meta, "Expected a valid path for 'path', e.g., path(crate::MemoizeNode)" ) ) ?;
218229 path = Some ( parsed_path) ;
219230 }
220- Meta :: Path ( path) if path. is_ident ( "skip_impl" ) => {
231+ "skip_impl" => {
232+ let path = meta. require_path_only ( ) ?;
221233 if skip_impl {
222234 return Err ( Error :: new_spanned ( path, "Multiple 'skip_impl' attributes are not allowed" ) ) ;
223235 }
224236 skip_impl = true ;
225237 }
226- Meta :: List ( meta) if meta. path . is_ident ( "properties" ) => {
238+ "properties" => {
239+ let meta = meta. require_list ( ) ?;
227240 if properties_string. is_some ( ) {
228241 return Err ( Error :: new_spanned ( path, "Multiple 'properties_string' attributes are not allowed" ) ) ;
229242 }
@@ -233,13 +246,27 @@ impl Parse for NodeFnAttributes {
233246
234247 properties_string = Some ( parsed_properties_string) ;
235248 }
249+ "cfg" => {
250+ if cfg. is_some ( ) {
251+ return Err ( Error :: new_spanned ( path, "Multiple 'feature' attributes are not allowed" ) ) ;
252+ }
253+ let meta = meta. require_list ( ) ?;
254+ cfg = Some ( meta. tokens . clone ( ) ) ;
255+ }
256+ "shader_node" => {
257+ if shader_node. is_some ( ) {
258+ return Err ( Error :: new_spanned ( path, "Multiple 'feature' attributes are not allowed" ) ) ;
259+ }
260+ let meta = meta. require_list ( ) ?;
261+ shader_node = Some ( syn:: parse2 ( meta. tokens . to_token_stream ( ) ) ?) ;
262+ }
236263 _ => {
237264 return Err ( Error :: new_spanned (
238265 meta,
239266 indoc ! (
240267 r#"
241268 Unsupported attribute in `node`.
242- Supported attributes are 'category', 'path' and 'name '.
269+ Supported attributes are 'category', 'path' 'name', 'skip_impl', 'cfg' and 'properties '.
243270
244271 Example usage:
245272 #[node_macro::node(category("Value"), name("Test Node"))]
@@ -256,6 +283,8 @@ impl Parse for NodeFnAttributes {
256283 path,
257284 skip_impl,
258285 properties_string,
286+ cfg,
287+ shader_node,
259288 } )
260289 }
261290}
@@ -758,6 +787,8 @@ mod tests {
758787 path : Some ( parse_quote ! ( graphene_core:: TestNode ) ) ,
759788 skip_impl : true ,
760789 properties_string : None ,
790+ cfg : None ,
791+ shader_node : None ,
761792 } ,
762793 fn_name : Ident :: new ( "add" , Span :: call_site ( ) ) ,
763794 struct_name : Ident :: new ( "Add" , Span :: call_site ( ) ) ,
@@ -819,6 +850,8 @@ mod tests {
819850 path : None ,
820851 skip_impl : false ,
821852 properties_string : None ,
853+ cfg : None ,
854+ shader_node : None ,
822855 } ,
823856 fn_name : Ident :: new ( "transform" , Span :: call_site ( ) ) ,
824857 struct_name : Ident :: new ( "Transform" , Span :: call_site ( ) ) ,
@@ -891,6 +924,8 @@ mod tests {
891924 path : None ,
892925 skip_impl : false ,
893926 properties_string : None ,
927+ cfg : None ,
928+ shader_node : None ,
894929 } ,
895930 fn_name : Ident :: new ( "circle" , Span :: call_site ( ) ) ,
896931 struct_name : Ident :: new ( "Circle" , Span :: call_site ( ) ) ,
@@ -948,6 +983,8 @@ mod tests {
948983 path : None ,
949984 skip_impl : false ,
950985 properties_string : None ,
986+ cfg : None ,
987+ shader_node : None ,
951988 } ,
952989 fn_name : Ident :: new ( "levels" , Span :: call_site ( ) ) ,
953990 struct_name : Ident :: new ( "Levels" , Span :: call_site ( ) ) ,
@@ -1017,6 +1054,8 @@ mod tests {
10171054 path : Some ( parse_quote ! ( graphene_core:: TestNode ) ) ,
10181055 skip_impl : false ,
10191056 properties_string : None ,
1057+ cfg : None ,
1058+ shader_node : None ,
10201059 } ,
10211060 fn_name : Ident :: new ( "add" , Span :: call_site ( ) ) ,
10221061 struct_name : Ident :: new ( "Add" , Span :: call_site ( ) ) ,
@@ -1074,6 +1113,8 @@ mod tests {
10741113 path : None ,
10751114 skip_impl : false ,
10761115 properties_string : None ,
1116+ cfg : None ,
1117+ shader_node : None ,
10771118 } ,
10781119 fn_name : Ident :: new ( "load_image" , Span :: call_site ( ) ) ,
10791120 struct_name : Ident :: new ( "LoadImage" , Span :: call_site ( ) ) ,
@@ -1131,6 +1172,8 @@ mod tests {
11311172 path : None ,
11321173 skip_impl : false ,
11331174 properties_string : None ,
1175+ cfg : None ,
1176+ shader_node : None ,
11341177 } ,
11351178 fn_name : Ident :: new ( "custom_node" , Span :: call_site ( ) ) ,
11361179 struct_name : Ident :: new ( "CustomNode" , Span :: call_site ( ) ) ,
0 commit comments