@@ -6,15 +6,86 @@ use crate::Result;
6
6
7
7
pub ( crate ) fn impl_joined_value ( ast : DeriveInput ) -> Result < TokenStream > {
8
8
let struct_ident = ast. ident ;
9
- let ( field_ident, field_type) = match ast. data {
10
- syn:: Data :: Struct ( data) => get_fields_map ( data. fields ) ?,
9
+ let ( field_ident, field_type) : ( Vec < Ident > , Vec < Type > ) = match ast. data {
10
+ syn:: Data :: Struct ( data) => get_fields_map ( data. fields ) ?. into_iter ( ) . unzip ( ) ,
11
11
_ => return Err ( "expected struct" . to_string ( ) ) ,
12
12
} ;
13
13
let map_key: Vec < String > = field_ident. iter ( ) . map ( |v| v. to_string ( ) ) . collect ( ) ;
14
14
let struct_buffer_ident = format_ident ! ( "__{}Buffers" , struct_ident) ;
15
15
16
+ let impl_buffer_map_layout =
17
+ buffer_map_layout ( & struct_ident, & field_ident, & field_type, & map_key) ;
18
+
16
19
let gen = quote ! {
17
- impl BufferMapLayout for #struct_ident {
20
+ #impl_buffer_map_layout
21
+
22
+ impl :: bevy_impulse:: JoinedValue for #struct_ident {
23
+ type Buffers = #struct_buffer_ident;
24
+
25
+ fn pull(
26
+ buffers: & :: bevy_impulse:: BufferMap ,
27
+ session: :: bevy_ecs:: prelude:: Entity ,
28
+ world: & mut :: bevy_ecs:: prelude:: World ,
29
+ ) -> Result <Self , :: bevy_impulse:: OperationError > {
30
+ use :: bevy_impulse:: { ManageBuffer , OrBroken } ;
31
+
32
+ #(
33
+ let #field_ident = world
34
+ . get_entity_mut( buffers. get( #map_key) . or_broken( ) ?. id( ) )
35
+ . or_broken( ) ?
36
+ . pull_from_buffer:: <#field_type>( session) ?;
37
+ ) *
38
+
39
+ Ok ( Self {
40
+ #(
41
+ #field_ident
42
+ ) , *
43
+ } )
44
+ }
45
+ }
46
+
47
+ struct #struct_buffer_ident {
48
+ #(
49
+ #field_ident: :: bevy_impulse:: Buffer <#field_type>
50
+ ) , *
51
+ }
52
+
53
+ impl From <#struct_buffer_ident> for :: bevy_impulse:: BufferMap {
54
+ fn from( value: #struct_buffer_ident) -> Self {
55
+ let mut buffers = :: bevy_impulse:: BufferMap :: default ( ) ;
56
+ #(
57
+ buffers. insert( std:: borrow:: Cow :: Borrowed ( #map_key) , value. #field_ident) ;
58
+ ) *
59
+ buffers
60
+ }
61
+ }
62
+ } ;
63
+
64
+ Ok ( gen. into ( ) )
65
+ }
66
+
67
+ fn get_fields_map ( fields : syn:: Fields ) -> Result < Vec < ( Ident , Type ) > > {
68
+ match fields {
69
+ syn:: Fields :: Named ( data) => {
70
+ let mut idents_types = Vec :: with_capacity ( data. named . len ( ) ) ;
71
+ for field in data. named {
72
+ let ident = field. ident . ok_or ( "expected named fields" . to_string ( ) ) ?;
73
+ idents_types. push ( ( ident, field. ty ) ) ;
74
+ }
75
+ Ok ( idents_types)
76
+ }
77
+ _ => return Err ( "expected named fields" . to_string ( ) ) ,
78
+ }
79
+ }
80
+
81
+ fn buffer_map_layout (
82
+ struct_ident : & Ident ,
83
+ field_ident : & Vec < Ident > ,
84
+ field_type : & Vec < Type > ,
85
+ map_key : & Vec < String > ,
86
+ ) -> proc_macro2:: TokenStream {
87
+ quote ! {
88
+ impl :: bevy_impulse:: BufferMapLayout for #struct_ident {
18
89
fn is_compatible( buffers: & BufferMap ) -> Result <( ) , :: bevy_impulse:: IncompatibleLayout > {
19
90
let mut compatibility = :: bevy_impulse:: IncompatibleLayout :: default ( ) ;
20
91
#(
@@ -61,64 +132,57 @@ pub(crate) fn impl_joined_value(ast: DeriveInput) -> Result<TokenStream> {
61
132
Ok ( ( ) )
62
133
}
63
134
}
135
+ }
136
+ }
64
137
65
- impl :: bevy_impulse:: JoinedValue for #struct_ident {
66
- type Buffers = #struct_buffer_ident;
138
+ pub ( crate ) fn impl_buffer_key_map ( ast : DeriveInput ) -> Result < TokenStream > {
139
+ let struct_ident = ast. ident ;
140
+ let ( field_ident, field_type) : ( Vec < Ident > , Vec < Type > ) = match ast. data {
141
+ syn:: Data :: Struct ( data) => get_fields_map ( data. fields ) ?. into_iter ( ) . unzip ( ) ,
142
+ _ => return Err ( "expected struct" . to_string ( ) ) ,
143
+ } ;
144
+ let map_key: Vec < String > = field_ident. iter ( ) . map ( |v| v. to_string ( ) ) . collect ( ) ;
67
145
68
- fn pull(
69
- buffers: & :: bevy_impulse:: BufferMap ,
70
- session: :: bevy_ecs:: prelude:: Entity ,
71
- world: & mut :: bevy_ecs:: prelude:: World ,
72
- ) -> Result <Self , :: bevy_impulse:: OperationError > {
73
- use :: bevy_impulse:: { ManageBuffer , OrBroken } ;
146
+ let impl_buffer_map_layout =
147
+ buffer_map_layout ( & struct_ident, & field_ident, & field_type, & map_key) ;
148
+
149
+ // FIXME(koonpeng): `create_key` does not allow failure and we can't guarantee that the buffer
150
+ // from buffer is valid.
151
+ let gen = quote ! {
152
+ impl :: bevy_impulse:: BufferKeyMap for #struct_ident {
153
+ fn add_accessor( buffers: & :: bevy_impulse:: BufferMap , accessor: :: bevy_ecs:: prelude:: Entity , world: & mut :: bevy_ecs:: prelude:: World ) -> :: bevy_impulse:: OperationResult {
154
+ use :: bevy_impulse:: { Accessed , OrBroken } ;
74
155
75
156
#(
76
- let #field_ident = world
77
- . get_entity_mut( buffers. get( #map_key) . or_broken( ) ?. id( ) )
78
- . or_broken( ) ?
79
- . pull_from_buffer:: <#field_type>( session) ?;
157
+ buffers. get( #map_key) . or_broken( ) ?. add_accessor( accessor, world) ?;
80
158
) *
81
159
82
- Ok ( Self {
83
- #(
84
- #field_ident
85
- ) , *
86
- } )
160
+ Ok ( ( ) )
87
161
}
88
- }
89
162
90
- struct #struct_buffer_ident {
91
- #(
92
- #field_ident: :: bevy_impulse:: Buffer <#field_type>
93
- ) , *
94
- }
163
+ fn create_key( buffers: & :: bevy_impulse:: BufferMap , builder: & :: bevy_impulse:: BufferKeyBuilder ) -> Self {
164
+ use :: bevy_impulse:: { Accessed , OrBroken } ;
95
165
96
- impl From <#struct_buffer_ident> for :: bevy_impulse:: BufferMap {
97
- fn from( value: #struct_buffer_ident) -> Self {
98
- let mut buffers = :: bevy_impulse:: BufferMap :: default ( ) ;
166
+ Self { #(
167
+ #field_ident: buffers. get( #map_key) . unwrap( ) . create_key( builder) . try_into( ) . unwrap( ) ,
168
+ ) * }
169
+ }
170
+
171
+ fn deep_clone_key( & self ) -> Self {
172
+ Self { #(
173
+ #field_ident: self . #field_ident. deep_clone( ) ,
174
+ ) * }
175
+ }
176
+
177
+ fn is_key_in_use( & self ) -> bool {
99
178
#(
100
- buffers. insert( std:: borrow:: Cow :: Borrowed ( #map_key) , value. #field_ident) ;
101
- ) *
102
- buffers
179
+ self . #field_ident. is_in_use( )
180
+ ) ||*
103
181
}
104
182
}
183
+
184
+ #impl_buffer_map_layout
105
185
} ;
106
186
107
187
Ok ( gen. into ( ) )
108
188
}
109
-
110
- fn get_fields_map ( fields : syn:: Fields ) -> Result < ( Vec < Ident > , Vec < Type > ) > {
111
- match fields {
112
- syn:: Fields :: Named ( data) => {
113
- let mut idents = Vec :: with_capacity ( data. named . len ( ) ) ;
114
- let mut types = Vec :: with_capacity ( data. named . len ( ) ) ;
115
- for field in data. named {
116
- let ident = field. ident . ok_or ( "expected named fields" . to_string ( ) ) ?;
117
- idents. push ( ident) ;
118
- types. push ( field. ty ) ;
119
- }
120
- Ok ( ( idents, types) )
121
- }
122
- _ => return Err ( "expected named fields" . to_string ( ) ) ,
123
- }
124
- }
0 commit comments