Skip to content

Commit

Permalink
fix issue with phantom ui node children (bevyengine#14490)
Browse files Browse the repository at this point in the history
# Objective

The `ui_layout_system` relies on change detection to sync parent-child
relation to taffy. The children need to by synced before node removal to
avoid trying to set deleted nodes as children (due to how the different
queries collect entities). This however may leave nodes that were
removed set as children to other nodes in special cases.

Fixes bevyengine#11385

## Solution

The solution is simply to re-sync the changed children after the nodes
are removed.

## Testing

Tested with `sickle_ui` where docking zone highlights would end up
glitched when docking was done in a certain manner:
- run the `docking_zone_splits` example
- pop out a tab from the top
- dock the floating panel in the center right
- grab another tab and try to hover the original static docking zone:
the highlight is semi-stuck
- (NOTE: sometimes it worked even without the fix due to scheduling
order not producing the bugged query results)

After the fix, the issue is no longer present.

NOTE: The performance impact should be minimal, as the child sync relies
on change detection. The change detection was also the reason the parent
nodes remained "stuck" with the phantom children if no other update were
done to them.
  • Loading branch information
eidloi authored Jul 29, 2024
1 parent 23cb0f9 commit 396153a
Showing 1 changed file with 7 additions and 0 deletions.
7 changes: 7 additions & 0 deletions crates/bevy_ui/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,13 @@ pub fn ui_layout_system(
// clean up removed nodes after syncing children to avoid potential panic (invalid SlotMap key used)
ui_surface.remove_entities(removed_components.removed_nodes.read());

// Re-sync changed children: avoid layout glitches caused by removed nodes that are still set as a child of another node
children_query.iter().for_each(|(entity, children)| {
if children.is_changed() {
ui_surface.update_children(entity, &children);
}
});

for (camera_id, camera) in &camera_layout_info {
let inverse_target_scale_factor = camera.scale_factor.recip();

Expand Down

0 comments on commit 396153a

Please sign in to comment.