mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 20:53:53 +00:00
bevy_reflect: Added get_boxed
method to reflect_trait
(#4120)
# Objective Allow `Box<dyn Reflect>` to be converted into a `Box<dyn MyTrait>` using the `#[reflect_trait]` macro. The other methods `get` and `get_mut` only provide a reference to the reflected object. ## Solution Add a `get_boxed` method to the `Reflect***` struct generated by the `#[reflect_trait]` macro. This method takes in a `Box<dyn Reflect>` and returns a `Box<dyn MyTrait>`. Co-authored-by: MrGVSV <49806985+MrGVSV@users.noreply.github.com>
This commit is contained in:
parent
7cb4d3cb43
commit
3a93b677a1
1 changed files with 35 additions and 0 deletions
|
@ -21,6 +21,10 @@ impl Parse for TraitInfo {
|
|||
}
|
||||
}
|
||||
|
||||
/// A trait attribute macro that allows a reflected type to be downcast to a trait object.
|
||||
///
|
||||
/// This generates a struct that takes the form `ReflectMyTrait`. An instance of this struct can then be
|
||||
/// used to perform the conversion.
|
||||
pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStream {
|
||||
let trait_info = parse_macro_input!(input as TraitInfo);
|
||||
let item_trait = &trait_info.item_trait;
|
||||
|
@ -28,23 +32,51 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr
|
|||
let trait_vis = &item_trait.vis;
|
||||
let reflect_trait_ident = crate::utility::get_reflect_ident(&item_trait.ident.to_string());
|
||||
let bevy_reflect_path = BevyManifest::default().get_path("bevy_reflect");
|
||||
|
||||
let struct_doc = format!(
|
||||
" A type generated by the #[reflect_trait] macro for the `{}` trait.\n\n This allows casting from `dyn Reflect` to `dyn {}`.",
|
||||
trait_ident,
|
||||
trait_ident
|
||||
);
|
||||
let get_doc = format!(
|
||||
" Downcast a `&dyn Reflect` type to `&dyn {}`.\n\n If the type cannot be downcast, `None` is returned.",
|
||||
trait_ident,
|
||||
);
|
||||
let get_mut_doc = format!(
|
||||
" Downcast a `&mut dyn Reflect` type to `&mut dyn {}`.\n\n If the type cannot be downcast, `None` is returned.",
|
||||
trait_ident,
|
||||
);
|
||||
let get_box_doc = format!(
|
||||
" Downcast a `Box<dyn Reflect>` type to `Box<dyn {}>`.\n\n If the type cannot be downcast, this will return `Err(Box<dyn Reflect>)`.",
|
||||
trait_ident,
|
||||
);
|
||||
|
||||
TokenStream::from(quote! {
|
||||
#item_trait
|
||||
|
||||
#[doc = #struct_doc]
|
||||
#[derive(Clone)]
|
||||
#trait_vis struct #reflect_trait_ident {
|
||||
get_func: fn(&dyn #bevy_reflect_path::Reflect) -> Option<&dyn #trait_ident>,
|
||||
get_mut_func: fn(&mut dyn #bevy_reflect_path::Reflect) -> Option<&mut dyn #trait_ident>,
|
||||
get_boxed_func: fn(Box<dyn #bevy_reflect_path::Reflect>) -> Result<Box<dyn #trait_ident>, Box<dyn #bevy_reflect_path::Reflect>>,
|
||||
}
|
||||
|
||||
impl #reflect_trait_ident {
|
||||
#[doc = #get_doc]
|
||||
pub fn get<'a>(&self, reflect_value: &'a dyn #bevy_reflect_path::Reflect) -> Option<&'a dyn #trait_ident> {
|
||||
(self.get_func)(reflect_value)
|
||||
}
|
||||
|
||||
#[doc = #get_mut_doc]
|
||||
pub fn get_mut<'a>(&self, reflect_value: &'a mut dyn #bevy_reflect_path::Reflect) -> Option<&'a mut dyn #trait_ident> {
|
||||
(self.get_mut_func)(reflect_value)
|
||||
}
|
||||
|
||||
#[doc = #get_box_doc]
|
||||
pub fn get_boxed(&self, reflect_value: Box<dyn #bevy_reflect_path::Reflect>) -> Result<Box<dyn #trait_ident>, Box<dyn #bevy_reflect_path::Reflect>> {
|
||||
(self.get_boxed_func)(reflect_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: #trait_ident + #bevy_reflect_path::Reflect> #bevy_reflect_path::FromType<T> for #reflect_trait_ident {
|
||||
|
@ -55,6 +87,9 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr
|
|||
},
|
||||
get_mut_func: |reflect_value| {
|
||||
reflect_value.downcast_mut::<T>().map(|value| value as &mut dyn #trait_ident)
|
||||
},
|
||||
get_boxed_func: |reflect_value| {
|
||||
reflect_value.downcast::<T>().map(|value| value as Box<dyn #trait_ident>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue