Skip to content

Commit

Permalink
feat: add with attribute for LdtkIntCell derive macro (#157)
Browse files Browse the repository at this point in the history
* feat: add with attribute for LdtkIntCell derive macro

* chore: fix clippy warning
  • Loading branch information
geieredgar committed Jan 29, 2023
1 parent 156ae8c commit d3fbd3c
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 3 deletions.
35 changes: 35 additions & 0 deletions macros/src/ldtk_int_cell.rs
Expand Up @@ -2,6 +2,7 @@ use quote::quote;

static LDTK_INT_CELL_ATTRIBUTE_NAME: &str = "ldtk_int_cell";
static FROM_INT_GRID_CELL_ATTRIBUTE_NAME: &str = "from_int_grid_cell";
static WITH_ATTRIBUTE_NAME: &str = "with";

pub fn expand_ldtk_int_cell_derive(ast: &syn::DeriveInput) -> proc_macro::TokenStream {
let struct_name = &ast.ident;
Expand Down Expand Up @@ -41,6 +42,15 @@ pub fn expand_ldtk_int_cell_derive(ast: &syn::DeriveInput) -> proc_macro::TokenS
continue;
}

let with = field
.attrs
.iter()
.find(|a| *a.path.get_ident().as_ref().unwrap() == WITH_ATTRIBUTE_NAME);
if let Some(attribute) = with {
field_constructions.push(expand_with_attribute(attribute, field_name, field_type));
continue;
}

field_constructions.push(quote! {
#field_name: <#field_type as std::default::Default>::default(),
});
Expand Down Expand Up @@ -101,3 +111,28 @@ fn expand_from_int_grid_cell_attribute(
}
}
}

fn expand_with_attribute(
attribute: &syn::Attribute,
field_name: &syn::Ident,
_: &syn::Type,
) -> proc_macro2::TokenStream {
match attribute
.parse_meta()
.expect("Cannot parse #[with...] attribute")
{
syn::Meta::List(syn::MetaList { nested, .. }) if nested.len() == 1 => {
match nested.first().unwrap() {
syn::NestedMeta::Meta(syn::Meta::Path(path)) => {
quote! {
#field_name: #path(int_grid_cell),
}
}
_ => panic!("Expected function as the only argument of #[with(...)]"),
}
}
_ => {
panic!("#[with...] attribute should take the form #[with(function_name)]")
}
}
}
2 changes: 1 addition & 1 deletion macros/src/lib.rs
Expand Up @@ -21,7 +21,7 @@ pub fn ldtk_entity_derive(input: TokenStream) -> TokenStream {
ldtk_entity::expand_ldtk_entity_derive(&ast)
}

#[proc_macro_derive(LdtkIntCell, attributes(ldtk_int_cell, from_int_grid_cell))]
#[proc_macro_derive(LdtkIntCell, attributes(ldtk_int_cell, from_int_grid_cell, with))]
pub fn ldtk_int_cell_derive(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();

Expand Down
29 changes: 29 additions & 0 deletions src/app/ldtk_int_cell.rs
Expand Up @@ -125,6 +125,35 @@ use std::{collections::HashMap, marker::PhantomData};
/// damage: Damage,
/// }
/// ```
///
/// ### `#[with(...)]`
///
/// Indicates that this component or bundle should be initialized with the given
/// function.
///
/// Note: The given function should have signature `fn (int_grid_cell: IntGridCell) -> T`
/// where `T` is the field type. The function should also be accessible in the scope.
///
/// ```
/// # use bevy::prelude::*;
/// # use bevy_ecs_ldtk::prelude::*;
/// # #[derive(Component, Default)]
/// # struct Fluid { viscosity: i32 }
/// # #[derive(Component, Default)]
/// # struct Damage;
/// fn initial_fluid(_: IntGridCell) -> Fluid {
/// Fluid {
/// viscosity: 20
/// }
/// }
///
/// #[derive(Bundle, LdtkIntCell)]
/// pub struct Lava {
/// #[with(initial_fluid)]
/// fluid: Fluid,
/// damage: Damage,
/// }
/// ```
pub trait LdtkIntCell {
/// The constructor used by the plugin when spawning additional components on IntGrid tiles.
/// If you need access to more of the [World](bevy::prelude::World), you can create a system that queries for
Expand Down
3 changes: 1 addition & 2 deletions src/ldtk/field_instance.rs
Expand Up @@ -174,8 +174,7 @@ impl<'de> Deserialize<'de> for FieldInstance {
)
} else {
return Err(de::Error::custom(format!(
"Encountered unknown field type: {}",
t
"Encountered unknown field type: {t}"
)));
}
}
Expand Down

0 comments on commit d3fbd3c

Please sign in to comment.