@@ -49,20 +49,6 @@ pub fn derive_resource(input: TokenStream) -> TokenStream {
4949
5050 let storage = storage_path ( & bevy_ecs_path, StorageTy :: Table ) ;
5151
52- let on_add_path = None ;
53- let on_remove_path = None ;
54- let on_insert_path = None ;
55- let on_replace_path = None ;
56- let on_despawn_path = None ;
57-
58- let on_add = hook_register_function_call ( & bevy_ecs_path, quote ! { on_add} , on_add_path) ;
59- let on_remove = hook_register_function_call ( & bevy_ecs_path, quote ! { on_remove} , on_remove_path) ;
60- let on_insert = hook_register_function_call ( & bevy_ecs_path, quote ! { on_insert} , on_insert_path) ;
61- let on_replace =
62- hook_register_function_call ( & bevy_ecs_path, quote ! { on_replace} , on_replace_path) ;
63- let on_despawn =
64- hook_register_function_call ( & bevy_ecs_path, quote ! { on_despawn} , on_despawn_path) ;
65-
6652 ast. generics
6753 . make_where_clause ( )
6854 . predicates
@@ -95,12 +81,6 @@ pub fn derive_resource(input: TokenStream) -> TokenStream {
9581 #( #register_required) *
9682 }
9783
98- #on_add
99- #on_insert
100- #on_replace
101- #on_remove
102- #on_despawn
103-
10484 fn clone_behavior( ) -> #bevy_ecs_path:: component:: ComponentCloneBehavior {
10585 #bevy_ecs_path:: component:: ComponentCloneBehavior :: Default
10686 }
@@ -160,85 +140,60 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
160140
161141 let storage = storage_path ( & bevy_ecs_path, attrs. storage ) ;
162142
163- let on_add_path = attrs
164- . on_add
165- . map ( |path| path. to_token_stream ( & bevy_ecs_path) ) ;
166- let on_remove_path = attrs
167- . on_remove
168- . map ( |path| path. to_token_stream ( & bevy_ecs_path) ) ;
169-
170- let on_insert_path = if relationship. is_some ( ) {
171- if attrs. on_insert . is_some ( ) {
172- return syn:: Error :: new (
173- ast. span ( ) ,
174- "Custom on_insert hooks are not supported as relationships already define an on_insert hook" ,
175- )
176- . into_compile_error ( )
177- . into ( ) ;
178- }
143+ let on_add_path = Vec :: from_iter (
144+ attrs
145+ . on_add
146+ . map ( |path| path. to_token_stream ( & bevy_ecs_path) ) ,
147+ ) ;
148+ let on_remove_path = Vec :: from_iter (
149+ attrs
150+ . on_remove
151+ . map ( |path| path. to_token_stream ( & bevy_ecs_path) ) ,
152+ ) ;
179153
180- Some ( quote ! ( <Self as #bevy_ecs_path:: relationship:: Relationship >:: on_insert) )
181- } else {
154+ let mut on_insert_path = Vec :: from_iter (
182155 attrs
183156 . on_insert
184- . map ( |path| path. to_token_stream ( & bevy_ecs_path) )
185- } ;
186-
187- let on_discard_path = if relationship. is_some ( ) {
188- if attrs. on_discard . is_some ( ) {
189- return syn:: Error :: new (
190- ast. span ( ) ,
191- "Custom on_discard hooks are not supported as Relationships already define an on_discard hook" ,
192- )
193- . into_compile_error ( )
194- . into ( ) ;
195- }
157+ . map ( |path| path. to_token_stream ( & bevy_ecs_path) ) ,
158+ ) ;
196159
197- Some ( quote ! ( <Self as #bevy_ecs_path:: relationship:: Relationship >:: on_discard) )
198- } else if attrs. relationship_target . is_some ( ) {
199- if attrs. on_discard . is_some ( ) {
200- return syn:: Error :: new (
201- ast. span ( ) ,
202- "Custom on_discard hooks are not supported as RelationshipTarget already defines an on_discard hook" ,
203- )
204- . into_compile_error ( )
205- . into ( ) ;
206- }
207-
208- Some ( quote ! ( <Self as #bevy_ecs_path:: relationship:: RelationshipTarget >:: on_discard) )
209- } else {
160+ let mut on_discard_path = Vec :: from_iter (
210161 attrs
211162 . on_discard
212- . map ( |path| path. to_token_stream ( & bevy_ecs_path) )
213- } ;
163+ . map ( |path| path. to_token_stream ( & bevy_ecs_path) ) ,
164+ ) ;
214165
215- let on_despawn_path = if attrs
216- . relationship_target
217- . is_some_and ( |target| target. linked_spawn )
218- {
219- if attrs. on_despawn . is_some ( ) {
220- return syn:: Error :: new (
221- ast. span ( ) ,
222- "Custom on_despawn hooks are not supported as this RelationshipTarget already defines an on_despawn hook, via the 'linked_spawn' attribute" ,
223- )
224- . into_compile_error ( )
225- . into ( ) ;
226- }
227-
228- Some ( quote ! ( <Self as #bevy_ecs_path:: relationship:: RelationshipTarget >:: on_despawn) )
229- } else {
166+ let mut on_despawn_path = Vec :: from_iter (
230167 attrs
231168 . on_despawn
232- . map ( |path| path. to_token_stream ( & bevy_ecs_path) )
233- } ;
169+ . map ( |path| path. to_token_stream ( & bevy_ecs_path) ) ,
170+ ) ;
171+
172+ if relationship. is_some ( ) {
173+ on_insert_path
174+ . push ( quote ! ( <Self as #bevy_ecs_path:: relationship:: Relationship >:: on_insert) ) ;
175+ on_discard_path
176+ . push ( quote ! ( <Self as #bevy_ecs_path:: relationship:: Relationship >:: on_discard) ) ;
177+ }
178+ if let Some ( target) = attrs. relationship_target {
179+ on_discard_path
180+ . push ( quote ! ( <Self as #bevy_ecs_path:: relationship:: RelationshipTarget >:: on_discard) ) ;
181+ if target. linked_spawn {
182+ on_despawn_path. push (
183+ quote ! ( <Self as #bevy_ecs_path:: relationship:: RelationshipTarget >:: on_despawn) ,
184+ ) ;
185+ }
186+ }
234187
235- let on_add = hook_register_function_call ( & bevy_ecs_path, quote ! { on_add} , on_add_path) ;
236- let on_insert = hook_register_function_call ( & bevy_ecs_path, quote ! { on_insert} , on_insert_path) ;
188+ let on_add = hook_register_function_call ( & bevy_ecs_path, quote ! { on_add} , & on_add_path) ;
189+ let on_insert =
190+ hook_register_function_call ( & bevy_ecs_path, quote ! { on_insert} , & on_insert_path) ;
237191 let on_discard =
238- hook_register_function_call ( & bevy_ecs_path, quote ! { on_discard} , on_discard_path) ;
239- let on_remove = hook_register_function_call ( & bevy_ecs_path, quote ! { on_remove} , on_remove_path) ;
192+ hook_register_function_call ( & bevy_ecs_path, quote ! { on_discard} , & on_discard_path) ;
193+ let on_remove =
194+ hook_register_function_call ( & bevy_ecs_path, quote ! { on_remove} , & on_remove_path) ;
240195 let on_despawn =
241- hook_register_function_call ( & bevy_ecs_path, quote ! { on_despawn} , on_despawn_path) ;
196+ hook_register_function_call ( & bevy_ecs_path, quote ! { on_despawn} , & on_despawn_path) ;
242197
243198 ast. generics
244199 . make_where_clause ( )
@@ -800,15 +755,27 @@ fn storage_path(bevy_ecs_path: &Path, ty: StorageTy) -> TokenStream2 {
800755fn hook_register_function_call (
801756 bevy_ecs_path : & Path ,
802757 hook : TokenStream2 ,
803- function : Option < TokenStream2 > ,
804- ) -> Option < TokenStream2 > {
805- function. map ( |meta| {
806- quote ! {
807- fn #hook( ) -> :: core:: option:: Option <#bevy_ecs_path:: lifecycle:: ComponentHook > {
808- :: core:: option:: Option :: Some ( #meta)
758+ functions : & [ TokenStream2 ] ,
759+ ) -> TokenStream2 {
760+ let hook_function = match functions {
761+ [ ] => return TokenStream2 :: new ( ) ,
762+ [ single] => single. clone ( ) ,
763+ multiple => {
764+ quote ! {
765+ {
766+ fn hook( world: #bevy_ecs_path:: world:: DeferredWorld , context: #bevy_ecs_path:: lifecycle:: HookContext ) {
767+ quote! { #( #multiple( world. reborrow( ) , context. clone( ) ) ; ) * }
768+ }
769+ hook
770+ }
809771 }
810772 }
811- } )
773+ } ;
774+ quote ! {
775+ fn #hook( ) -> :: core:: option:: Option <#bevy_ecs_path:: lifecycle:: ComponentHook > {
776+ :: core:: option:: Option :: Some ( #hook_function)
777+ }
778+ }
812779}
813780
814781mod kw {
0 commit comments