@@ -16,7 +16,7 @@ use crate::{
16
16
use bevy_macro_utils:: { derive_label, ensure_no_collision, get_struct_fields, BevyManifest } ;
17
17
use proc_macro:: TokenStream ;
18
18
use proc_macro2:: { Ident , Span } ;
19
- use quote:: { format_ident, quote} ;
19
+ use quote:: { format_ident, quote, ToTokens } ;
20
20
use syn:: {
21
21
parse_macro_input, parse_quote, punctuated:: Punctuated , spanned:: Spanned , token:: Comma ,
22
22
ConstParam , Data , DataStruct , DeriveInput , GenericParam , Index , TypeParam ,
@@ -79,14 +79,16 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
79
79
let mut field_kind = Vec :: with_capacity ( named_fields. len ( ) ) ;
80
80
81
81
for field in named_fields {
82
+ let mut kind = BundleFieldKind :: Component ;
83
+
82
84
for attr in field
83
85
. attrs
84
86
. iter ( )
85
87
. filter ( |a| a. path ( ) . is_ident ( BUNDLE_ATTRIBUTE_NAME ) )
86
88
{
87
89
if let Err ( error) = attr. parse_nested_meta ( |meta| {
88
90
if meta. path . is_ident ( BUNDLE_ATTRIBUTE_IGNORE_NAME ) {
89
- field_kind . push ( BundleFieldKind :: Ignore ) ;
91
+ kind = BundleFieldKind :: Ignore ;
90
92
Ok ( ( ) )
91
93
} else {
92
94
Err ( meta. error ( format ! (
@@ -98,7 +100,7 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
98
100
}
99
101
}
100
102
101
- field_kind. push ( BundleFieldKind :: Component ) ;
103
+ field_kind. push ( kind ) ;
102
104
}
103
105
104
106
let field = named_fields
@@ -111,82 +113,33 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
111
113
. map ( |field| & field. ty )
112
114
. collect :: < Vec < _ > > ( ) ;
113
115
114
- let mut field_component_ids = Vec :: new ( ) ;
115
- let mut field_get_component_ids = Vec :: new ( ) ;
116
- let mut field_get_components = Vec :: new ( ) ;
117
- let mut field_from_components = Vec :: new ( ) ;
118
- let mut field_required_components = Vec :: new ( ) ;
116
+ let mut active_field_types = Vec :: new ( ) ;
117
+ let mut active_field_tokens = Vec :: new ( ) ;
118
+ let mut inactive_field_tokens = Vec :: new ( ) ;
119
119
for ( ( ( i, field_type) , field_kind) , field) in field_type
120
120
. iter ( )
121
121
. enumerate ( )
122
122
. zip ( field_kind. iter ( ) )
123
123
. zip ( field. iter ( ) )
124
124
{
125
+ let field_tokens = match field {
126
+ Some ( field) => field. to_token_stream ( ) ,
127
+ None => Index :: from ( i) . to_token_stream ( ) ,
128
+ } ;
125
129
match field_kind {
126
130
BundleFieldKind :: Component => {
127
- field_component_ids. push ( quote ! {
128
- <#field_type as #ecs_path:: bundle:: Bundle >:: component_ids( components, & mut * ids) ;
129
- } ) ;
130
- field_required_components. push ( quote ! {
131
- <#field_type as #ecs_path:: bundle:: Bundle >:: register_required_components( components, required_components) ;
132
- } ) ;
133
- field_get_component_ids. push ( quote ! {
134
- <#field_type as #ecs_path:: bundle:: Bundle >:: get_component_ids( components, & mut * ids) ;
135
- } ) ;
136
- match field {
137
- Some ( field) => {
138
- field_get_components. push ( quote ! {
139
- self . #field. get_components( & mut * func) ;
140
- } ) ;
141
- field_from_components. push ( quote ! {
142
- #field: <#field_type as #ecs_path:: bundle:: BundleFromComponents >:: from_components( ctx, & mut * func) ,
143
- } ) ;
144
- }
145
- None => {
146
- let index = Index :: from ( i) ;
147
- field_get_components. push ( quote ! {
148
- self . #index. get_components( & mut * func) ;
149
- } ) ;
150
- field_from_components. push ( quote ! {
151
- #index: <#field_type as #ecs_path:: bundle:: BundleFromComponents >:: from_components( ctx, & mut * func) ,
152
- } ) ;
153
- }
154
- }
131
+ active_field_types. push ( field_type) ;
132
+ active_field_tokens. push ( field_tokens) ;
155
133
}
156
134
157
- BundleFieldKind :: Ignore => {
158
- field_from_components. push ( quote ! {
159
- #field: :: core:: default :: Default :: default ( ) ,
160
- } ) ;
161
- }
135
+ BundleFieldKind :: Ignore => inactive_field_tokens. push ( field_tokens) ,
162
136
}
163
137
}
164
138
let generics = ast. generics ;
165
139
let ( impl_generics, ty_generics, where_clause) = generics. split_for_impl ( ) ;
166
140
let struct_name = & ast. ident ;
167
141
168
- let from_components = attributes. impl_from_components . then ( || quote ! {
169
- // SAFETY:
170
- // - ComponentId is returned in field-definition-order. [from_components] uses field-definition-order
171
- #[ allow( deprecated) ]
172
- unsafe impl #impl_generics #ecs_path:: bundle:: BundleFromComponents for #struct_name #ty_generics #where_clause {
173
- #[ allow( unused_variables, non_snake_case) ]
174
- unsafe fn from_components<__T, __F>( ctx: & mut __T, func: & mut __F) -> Self
175
- where
176
- __F: FnMut ( & mut __T) -> #ecs_path:: ptr:: OwningPtr <' _>
177
- {
178
- Self {
179
- #( #field_from_components) *
180
- }
181
- }
182
- }
183
- } ) ;
184
-
185
- let attribute_errors = & errors;
186
-
187
- TokenStream :: from ( quote ! {
188
- #( #attribute_errors) *
189
-
142
+ let bundle_impl = quote ! {
190
143
// SAFETY:
191
144
// - ComponentId is returned in field-definition-order. [get_components] uses field-definition-order
192
145
// - `Bundle::get_components` is exactly once for each member. Rely's on the Component -> Bundle implementation to properly pass
@@ -196,27 +149,27 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
196
149
fn component_ids(
197
150
components: & mut #ecs_path:: component:: ComponentsRegistrator ,
198
151
ids: & mut impl FnMut ( #ecs_path:: component:: ComponentId )
199
- ) {
200
- #( #field_component_ids ) *
152
+ ) {
153
+ #( <#active_field_types as #ecs_path :: bundle :: Bundle > :: component_ids ( components , ids ) ; ) *
201
154
}
202
155
203
156
fn get_component_ids(
204
157
components: & #ecs_path:: component:: Components ,
205
158
ids: & mut impl FnMut ( Option <#ecs_path:: component:: ComponentId >)
206
- ) {
207
- #( #field_get_component_ids ) *
159
+ ) {
160
+ #( <#active_field_types as #ecs_path :: bundle :: Bundle > :: get_component_ids ( components , & mut * ids ) ; ) *
208
161
}
209
162
210
163
fn register_required_components(
211
164
components: & mut #ecs_path:: component:: ComponentsRegistrator ,
212
165
required_components: & mut #ecs_path:: component:: RequiredComponents
213
- ) {
214
- #( #field_required_components ) *
166
+ ) {
167
+ #( <#active_field_types as #ecs_path :: bundle :: Bundle > :: register_required_components ( components , required_components ) ; ) *
215
168
}
216
169
}
170
+ } ;
217
171
218
- #from_components
219
-
172
+ let dynamic_bundle_impl = quote ! {
220
173
#[ allow( deprecated) ]
221
174
impl #impl_generics #ecs_path:: bundle:: DynamicBundle for #struct_name #ty_generics #where_clause {
222
175
type Effect = ( ) ;
@@ -226,9 +179,36 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
226
179
self ,
227
180
func: & mut impl FnMut ( #ecs_path:: component:: StorageType , #ecs_path:: ptr:: OwningPtr <' _>)
228
181
) {
229
- #( #field_get_components ) *
182
+ #( <#active_field_types as #ecs_path :: bundle :: DynamicBundle > :: get_components ( self . #active_field_tokens , & mut * func ) ; ) *
230
183
}
231
184
}
185
+ } ;
186
+
187
+ let from_components_impl = attributes. impl_from_components . then ( || quote ! {
188
+ // SAFETY:
189
+ // - ComponentId is returned in field-definition-order. [from_components] uses field-definition-order
190
+ #[ allow( deprecated) ]
191
+ unsafe impl #impl_generics #ecs_path:: bundle:: BundleFromComponents for #struct_name #ty_generics #where_clause {
192
+ #[ allow( unused_variables, non_snake_case) ]
193
+ unsafe fn from_components<__T, __F>( ctx: & mut __T, func: & mut __F) -> Self
194
+ where
195
+ __F: FnMut ( & mut __T) -> #ecs_path:: ptr:: OwningPtr <' _>
196
+ {
197
+ Self {
198
+ #( #active_field_tokens: <#active_field_types as #ecs_path:: bundle:: BundleFromComponents >:: from_components( ctx, & mut * func) , ) *
199
+ #( #inactive_field_tokens: :: core:: default :: Default :: default ( ) , ) *
200
+ }
201
+ }
202
+ }
203
+ } ) ;
204
+
205
+ let attribute_errors = & errors;
206
+
207
+ TokenStream :: from ( quote ! {
208
+ #( #attribute_errors) *
209
+ #bundle_impl
210
+ #from_components_impl
211
+ #dynamic_bundle_impl
232
212
} )
233
213
}
234
214
0 commit comments