@@ -11,16 +11,21 @@ pub fn transform_propagate_system(
1111            & Transform , 
1212            Changed < Transform > , 
1313            & mut  GlobalTransform , 
14+             Entity , 
1415        ) , 
1516        Without < Parent > , 
1617    > , 
17-     mut  transform_query :  Query < 
18-         ( & Transform ,  Changed < Transform > ,  & mut  GlobalTransform ) , 
19-         With < Parent > , 
20-     > , 
18+     mut  transform_query :  Query < ( 
19+         & Transform , 
20+         Changed < Transform > , 
21+         & mut  GlobalTransform , 
22+         & Parent , 
23+     ) > , 
2124    children_query :  Query < ( & Children ,  Changed < Children > ) ,  ( With < Parent > ,  With < GlobalTransform > ) > , 
2225)  { 
23-     for  ( children,  transform,  transform_changed,  mut  global_transform)  in  root_query. iter_mut ( )  { 
26+     for  ( children,  transform,  transform_changed,  mut  global_transform,  entity)  in 
27+         root_query. iter_mut ( ) 
28+     { 
2429        let  mut  changed = transform_changed; 
2530        if  transform_changed { 
2631            * global_transform = GlobalTransform :: from ( * transform) ; 
@@ -35,6 +40,7 @@ pub fn transform_propagate_system(
3540                    & mut  transform_query, 
3641                    & children_query, 
3742                    * child, 
43+                     entity, 
3844                    changed, 
3945                ) ; 
4046            } 
@@ -44,19 +50,26 @@ pub fn transform_propagate_system(
4450
4551fn  propagate_recursive ( 
4652    parent :  & GlobalTransform , 
47-     transform_query :  & mut  Query < 
48-         ( & Transform ,  Changed < Transform > ,  & mut  GlobalTransform ) , 
49-         With < Parent > , 
50-     > , 
53+     transform_query :  & mut  Query < ( 
54+         & Transform , 
55+         Changed < Transform > , 
56+         & mut  GlobalTransform , 
57+         & Parent , 
58+     ) > , 
5159    children_query :  & Query < ( & Children ,  Changed < Children > ) ,  ( With < Parent > ,  With < GlobalTransform > ) > , 
5260    entity :  Entity , 
61+     expected_parent :  Entity , 
5362    mut  changed :  bool , 
5463    // We use a result here to use the `?` operator. Ideally we'd use a try block instead 
5564)  -> Result < ( ) ,  ( ) >  { 
5665    let  global_matrix = { 
57-         let  ( transform,  transform_changed,  mut  global_transform)  =
66+         let  ( transform,  transform_changed,  mut  global_transform,  child_parent )  =
5867            transform_query. get_mut ( entity) . map_err ( drop) ?; 
59- 
68+         // Note that for parallelising, this check cannot occur here, since there is an `&mut GlobalTransform` (in global_transform) 
69+         assert_eq ! ( 
70+             child_parent. 0 ,  expected_parent, 
71+             "Malformed hierarchy. This probably means that your hierarchy has been improperly maintained, or contains a cycle" 
72+         ) ; 
6073        changed |= transform_changed; 
6174        if  changed { 
6275            * global_transform = parent. mul_transform ( * transform) ; 
@@ -73,6 +86,7 @@ fn propagate_recursive(
7386            transform_query, 
7487            children_query, 
7588            * child, 
89+             entity, 
7690            changed, 
7791        ) ; 
7892    } 
@@ -322,4 +336,36 @@ mod test {
322336            ) ; 
323337        } 
324338    } 
339+     #[ test]  
340+     #[ should_panic]  
341+     fn  panic_when_hierarchy_cycle ( )  { 
342+         let  mut  app = App :: new ( ) ; 
343+ 
344+         app. add_system ( parent_update_system) ; 
345+         app. add_system ( transform_propagate_system) ; 
346+ 
347+         let  child = app
348+             . world 
349+             . spawn ( ) 
350+             . insert_bundle ( ( Transform :: identity ( ) ,  GlobalTransform :: default ( ) ) ) 
351+             . id ( ) ; 
352+ 
353+         let  grandchild = app
354+             . world 
355+             . spawn ( ) 
356+             . insert_bundle ( ( 
357+                 Transform :: identity ( ) , 
358+                 GlobalTransform :: default ( ) , 
359+                 Parent ( child) , 
360+             ) ) 
361+             . id ( ) ; 
362+         app. world . spawn ( ) . insert_bundle ( ( 
363+             Transform :: default ( ) , 
364+             GlobalTransform :: default ( ) , 
365+             Children :: with ( & [ child] ) , 
366+         ) ) ; 
367+         app. world . entity_mut ( child) . insert ( Parent ( grandchild) ) ; 
368+ 
369+         app. update ( ) ; 
370+     } 
325371} 
0 commit comments