@@ -2,6 +2,7 @@ use crate::components::{GlobalTransform, Transform};
2
2
use bevy_ecs:: {
3
3
change_detection:: Ref ,
4
4
prelude:: { Changed , DetectChanges , Entity , Query , With , Without } ,
5
+ system:: { ParamSet , RemovedComponents } ,
5
6
} ;
6
7
use bevy_hierarchy:: { Children , Parent } ;
7
8
@@ -10,16 +11,29 @@ use bevy_hierarchy::{Children, Parent};
10
11
/// Third party plugins should use [`transform_propagate_system_set`](crate::transform_propagate_system_set)
11
12
/// to propagate transforms correctly.
12
13
pub fn sync_simple_transforms (
13
- mut query : Query <
14
- ( & Transform , & mut GlobalTransform ) ,
15
- ( Changed < Transform > , Without < Parent > , Without < Children > ) ,
16
- > ,
14
+ mut query : ParamSet < (
15
+ Query <
16
+ ( & Transform , & mut GlobalTransform ) ,
17
+ ( Changed < Transform > , Without < Parent > , Without < Children > ) ,
18
+ > ,
19
+ Query < ( Ref < Transform > , & mut GlobalTransform ) , Without < Children > > ,
20
+ ) > ,
21
+ orphaned : RemovedComponents < Parent > ,
17
22
) {
18
23
query
24
+ . p0 ( )
19
25
. par_iter_mut ( )
20
26
. for_each_mut ( |( transform, mut global_transform) | {
21
27
* global_transform = GlobalTransform :: from ( * transform) ;
22
28
} ) ;
29
+ // updated orphaned entities
30
+ let mut query = query. p1 ( ) ;
31
+ let mut iter = query. iter_many_mut ( orphaned. iter ( ) ) ;
32
+ while let Some ( ( transform, mut global_transform) ) = iter. fetch_next ( ) {
33
+ if !transform. is_changed ( ) {
34
+ * global_transform = GlobalTransform :: from ( * transform) ;
35
+ }
36
+ }
23
37
}
24
38
25
39
/// Update [`GlobalTransform`] component of entities based on entity hierarchy and
@@ -32,12 +46,15 @@ pub fn propagate_transforms(
32
46
( Entity , & Children , Ref < Transform > , & mut GlobalTransform ) ,
33
47
Without < Parent > ,
34
48
> ,
49
+ orphaned : RemovedComponents < Parent > ,
35
50
transform_query : Query < ( Ref < Transform > , & mut GlobalTransform , Option < & Children > ) , With < Parent > > ,
36
51
parent_query : Query < ( Entity , Ref < Parent > ) > ,
37
52
) {
53
+ let mut orphaned = orphaned. iter ( ) . collect :: < Vec < _ > > ( ) ;
54
+ orphaned. sort_unstable ( ) ;
38
55
root_query. par_iter_mut ( ) . for_each_mut (
39
56
|( entity, children, transform, mut global_transform) | {
40
- let changed = transform. is_changed ( ) ;
57
+ let changed = transform. is_changed ( ) || orphaned . binary_search ( & entity ) . is_ok ( ) ;
41
58
if changed {
42
59
* global_transform = GlobalTransform :: from ( * transform) ;
43
60
}
@@ -163,21 +180,74 @@ mod test {
163
180
use bevy_tasks:: { ComputeTaskPool , TaskPool } ;
164
181
165
182
use crate :: components:: { GlobalTransform , Transform } ;
166
- use crate :: systems:: * ;
167
- use crate :: TransformBundle ;
183
+ use crate :: { transform_propagate_system_set, TransformBundle } ;
168
184
use bevy_hierarchy:: { BuildChildren , BuildWorldChildren , Children , Parent } ;
169
185
170
186
#[ derive( StageLabel ) ]
171
187
struct Update ;
172
188
189
+ #[ test]
190
+ fn correct_parent_removed ( ) {
191
+ ComputeTaskPool :: init ( TaskPool :: default) ;
192
+ let mut world = World :: default ( ) ;
193
+ let offset_global_transform =
194
+ |offset| GlobalTransform :: from ( Transform :: from_xyz ( offset, offset, offset) ) ;
195
+ let offset_transform =
196
+ |offset| TransformBundle :: from_transform ( Transform :: from_xyz ( offset, offset, offset) ) ;
197
+
198
+ let mut update_stage = SystemStage :: parallel ( ) ;
199
+ update_stage. add_system_set ( transform_propagate_system_set ( ) ) ;
200
+
201
+ let mut schedule = Schedule :: default ( ) ;
202
+ schedule. add_stage ( Update , update_stage) ;
203
+
204
+ let mut command_queue = CommandQueue :: default ( ) ;
205
+ let mut commands = Commands :: new ( & mut command_queue, & world) ;
206
+ let root = commands. spawn ( offset_transform ( 3.3 ) ) . id ( ) ;
207
+ let parent = commands. spawn ( offset_transform ( 4.4 ) ) . id ( ) ;
208
+ let child = commands. spawn ( offset_transform ( 5.5 ) ) . id ( ) ;
209
+ commands. entity ( parent) . set_parent ( root) ;
210
+ commands. entity ( child) . set_parent ( parent) ;
211
+ command_queue. apply ( & mut world) ;
212
+ schedule. run ( & mut world) ;
213
+
214
+ assert_ne ! (
215
+ world. get:: <GlobalTransform >( parent) . unwrap( ) ,
216
+ & GlobalTransform :: from( Transform :: IDENTITY )
217
+ ) ;
218
+
219
+ // Remove parent of `parent`
220
+ let mut command_queue = CommandQueue :: default ( ) ;
221
+ let mut commands = Commands :: new ( & mut command_queue, & world) ;
222
+ commands. entity ( parent) . remove_parent ( ) ;
223
+ command_queue. apply ( & mut world) ;
224
+ schedule. run ( & mut world) ;
225
+
226
+ assert_eq ! (
227
+ world. get:: <GlobalTransform >( parent) . unwrap( ) ,
228
+ & offset_global_transform( 4.4 )
229
+ ) ;
230
+
231
+ // Remove parent of `child`
232
+ let mut command_queue = CommandQueue :: default ( ) ;
233
+ let mut commands = Commands :: new ( & mut command_queue, & world) ;
234
+ commands. entity ( child) . remove_parent ( ) ;
235
+ command_queue. apply ( & mut world) ;
236
+ schedule. run ( & mut world) ;
237
+
238
+ assert_eq ! (
239
+ world. get:: <GlobalTransform >( child) . unwrap( ) ,
240
+ & offset_global_transform( 5.5 )
241
+ ) ;
242
+ }
243
+
173
244
#[ test]
174
245
fn did_propagate ( ) {
175
246
ComputeTaskPool :: init ( TaskPool :: default) ;
176
247
let mut world = World :: default ( ) ;
177
248
178
249
let mut update_stage = SystemStage :: parallel ( ) ;
179
- update_stage. add_system ( sync_simple_transforms) ;
180
- update_stage. add_system ( propagate_transforms) ;
250
+ update_stage. add_system_set ( transform_propagate_system_set ( ) ) ;
181
251
182
252
let mut schedule = Schedule :: default ( ) ;
183
253
schedule. add_stage ( Update , update_stage) ;
@@ -218,8 +288,7 @@ mod test {
218
288
let mut world = World :: default ( ) ;
219
289
220
290
let mut update_stage = SystemStage :: parallel ( ) ;
221
- update_stage. add_system ( sync_simple_transforms) ;
222
- update_stage. add_system ( propagate_transforms) ;
291
+ update_stage. add_system_set ( transform_propagate_system_set ( ) ) ;
223
292
224
293
let mut schedule = Schedule :: default ( ) ;
225
294
schedule. add_stage ( Update , update_stage) ;
@@ -262,8 +331,7 @@ mod test {
262
331
let mut world = World :: default ( ) ;
263
332
264
333
let mut update_stage = SystemStage :: parallel ( ) ;
265
- update_stage. add_system ( sync_simple_transforms) ;
266
- update_stage. add_system ( propagate_transforms) ;
334
+ update_stage. add_system_set ( transform_propagate_system_set ( ) ) ;
267
335
268
336
let mut schedule = Schedule :: default ( ) ;
269
337
schedule. add_stage ( Update , update_stage) ;
@@ -342,8 +410,7 @@ mod test {
342
410
let mut app = App :: new ( ) ;
343
411
ComputeTaskPool :: init ( TaskPool :: default) ;
344
412
345
- app. add_system ( sync_simple_transforms) ;
346
- app. add_system ( propagate_transforms) ;
413
+ app. add_system_set ( transform_propagate_system_set ( ) ) ;
347
414
348
415
let translation = vec3 ( 1.0 , 0.0 , 0.0 ) ;
349
416
@@ -389,8 +456,7 @@ mod test {
389
456
let mut temp = World :: new ( ) ;
390
457
let mut app = App :: new ( ) ;
391
458
392
- app. add_system ( propagate_transforms)
393
- . add_system ( sync_simple_transforms) ;
459
+ app. add_system_set ( transform_propagate_system_set ( ) ) ;
394
460
395
461
fn setup_world ( world : & mut World ) -> ( Entity , Entity ) {
396
462
let mut grandchild = Entity :: from_raw ( 0 ) ;
0 commit comments