fix issue with phantom ui node children (#14490)

# 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 #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.
This commit is contained in:
Tamás Kiss 2024-07-30 01:42:56 +02:00 committed by François
parent 0886e6a302
commit ebfe545f79
No known key found for this signature in database

View file

@ -217,6 +217,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();