@@ -21,30 +21,62 @@ impl Parse for TraitInfo {
21
21
}
22
22
}
23
23
24
+ /// A trait attribute macro that allows a reflected type to be downcast to a trait object.
25
+ ///
26
+ /// This generates a struct that takes the form `ReflectMyTrait`. An instance of this struct can then be
27
+ /// used to perform the conversion.
24
28
pub ( crate ) fn reflect_trait ( _args : & TokenStream , input : TokenStream ) -> TokenStream {
25
29
let trait_info = parse_macro_input ! ( input as TraitInfo ) ;
26
30
let item_trait = & trait_info. item_trait ;
27
31
let trait_ident = & item_trait. ident ;
28
32
let trait_vis = & item_trait. vis ;
29
33
let reflect_trait_ident = crate :: utility:: get_reflect_ident ( & item_trait. ident . to_string ( ) ) ;
30
34
let bevy_reflect_path = BevyManifest :: default ( ) . get_path ( "bevy_reflect" ) ;
35
+
36
+ let struct_doc = format ! (
37
+ " A type generated by the #[reflect_trait] macro for the `{}` trait.\n \n This allows casting from `dyn Reflect` to `dyn {}`." ,
38
+ trait_ident,
39
+ trait_ident
40
+ ) ;
41
+ let get_doc = format ! (
42
+ " Downcast a `&dyn Reflect` type to `&dyn {}`.\n \n If the type cannot be downcast, `None` is returned." ,
43
+ trait_ident,
44
+ ) ;
45
+ let get_mut_doc = format ! (
46
+ " Downcast a `&mut dyn Reflect` type to `&mut dyn {}`.\n \n If the type cannot be downcast, `None` is returned." ,
47
+ trait_ident,
48
+ ) ;
49
+ let get_box_doc = format ! (
50
+ " Downcast a `Box<dyn Reflect>` type to `Box<dyn {}>`.\n \n If the type cannot be downcast, this will return `Err(Box<dyn Reflect>)`." ,
51
+ trait_ident,
52
+ ) ;
53
+
31
54
TokenStream :: from ( quote ! {
32
55
#item_trait
33
56
57
+ #[ doc = #struct_doc]
34
58
#[ derive( Clone ) ]
35
59
#trait_vis struct #reflect_trait_ident {
36
60
get_func: fn ( & dyn #bevy_reflect_path:: Reflect ) -> Option <& dyn #trait_ident>,
37
61
get_mut_func: fn ( & mut dyn #bevy_reflect_path:: Reflect ) -> Option <& mut dyn #trait_ident>,
62
+ get_boxed_func: fn ( Box <dyn #bevy_reflect_path:: Reflect >) -> Result <Box <dyn #trait_ident>, Box <dyn #bevy_reflect_path:: Reflect >>,
38
63
}
39
64
40
65
impl #reflect_trait_ident {
66
+ #[ doc = #get_doc]
41
67
pub fn get<' a>( & self , reflect_value: & ' a dyn #bevy_reflect_path:: Reflect ) -> Option <& ' a dyn #trait_ident> {
42
68
( self . get_func) ( reflect_value)
43
69
}
44
70
71
+ #[ doc = #get_mut_doc]
45
72
pub fn get_mut<' a>( & self , reflect_value: & ' a mut dyn #bevy_reflect_path:: Reflect ) -> Option <& ' a mut dyn #trait_ident> {
46
73
( self . get_mut_func) ( reflect_value)
47
74
}
75
+
76
+ #[ doc = #get_box_doc]
77
+ pub fn get_boxed( & self , reflect_value: Box <dyn #bevy_reflect_path:: Reflect >) -> Result <Box <dyn #trait_ident>, Box <dyn #bevy_reflect_path:: Reflect >> {
78
+ ( self . get_boxed_func) ( reflect_value)
79
+ }
48
80
}
49
81
50
82
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
55
87
} ,
56
88
get_mut_func: |reflect_value| {
57
89
reflect_value. downcast_mut:: <T >( ) . map( |value| value as & mut dyn #trait_ident)
90
+ } ,
91
+ get_boxed_func: |reflect_value| {
92
+ reflect_value. downcast:: <T >( ) . map( |value| value as Box <dyn #trait_ident>)
58
93
}
59
94
}
60
95
}
0 commit comments