use proc_macro::TokenStream;
use quote::quote;
use syn::{Data, DeriveInput, Fields, parse_macro_input};
#[proc_macro_derive(Node, attributes(transform))]
pub fn derive_node(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let struct_name = &input.ident;
let fields = match &input.data {
Data::Struct(data_struct) => match &data_struct.fields {
Fields::Named(fields_named) => &fields_named.named,
_ => panic!("Node can only be derived for structs with named fields"),
},
_ => panic!("Node can only be derived for structs"),
};
let mut transform_field = None;
for field in fields {
for attr in &field.attrs {
if attr.path().is_ident("transform") {
transform_field = Some(field.ident.clone().unwrap());
}
}
}
if transform_field.is_none() {
let mut errors = Vec::new();
if transform_field.is_none() {
errors.push(syn::Error::new_spanned(
struct_name,
"Missing field marked with #[transform]\n\
Example:\n\
#[transform]\n\
transform: NodeTransform,",
));
}
let combined = errors
.into_iter()
.map(|e| e.to_compile_error())
.collect::<proc_macro2::TokenStream>();
return TokenStream::from(combined);
}
let transform = transform_field.unwrap();
let expanded = quote! {
impl ::maple::engine::nodes::Node for #struct_name
{
fn get_transform(&mut self) -> &mut ::maple::engine::components::NodeTransform {
&mut self.#transform
}
}
};
TokenStream::from(expanded)
}