fix occasional crash moving ui root nodes (#11371)
# Objective fix an occasional crash when moving ui root nodes between cameras. occasionally, updating the TargetCamera of a ui element and then removing the element causes a crash. i believe that is because when we assign a child in taffy, the old parent doesn't remove that child from it's children, so we have: ``` user: create root node N1, camera A -> layout::set_camera_children(A) : - create implicit node A1 - assign 1 as child -> taffy.children[A1] = [N1], taffy.parents[1] = A1 user: move root node N1 to camera B -> layout::set_camera_children(B) : - create implicit node B1 - assign 1 as child -> taffy.children[A1] = [N1], taffy.children[B1] = [N1], taffy.parents[1] = B1 -> layout::set_camera_children(A) : - remove implicit node A1 (which still has N1 as a child) -> -> taffy sets parent[N1] = None *** -> taffy.children[B1] = [N1], taffy.parents[1] = None user: remove N1 -> layout::remove_entities(N1) - since parent[N1] is None, it's not removed from B1 -> taffy.children[B1] = [N1], taffy.parents[1] is removed -> layout::set_camera_children(B) - remove implicit node B1 - taffy crash accessing taffy.parents[N1] ``` ## Solution we can work around this by making sure to remove the child from the old parent if one exists (this pr). i think a better fix may be for taffy to check in `Taffy::remove` and only set the child's parent to None if it is currently equal to the node being removed but i'm not sure if there's an explicit assumption we're violating here (@nicoburns).
This commit is contained in:
parent
43f83d5e7c
commit
30940e5cb4
@ -19,7 +19,7 @@ use bevy_transform::components::Transform;
|
|||||||
use bevy_utils::{default, EntityHashMap, HashMap, HashSet};
|
use bevy_utils::{default, EntityHashMap, HashMap, HashSet};
|
||||||
use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged};
|
use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use taffy::Taffy;
|
use taffy::{tree::LayoutTree, Taffy};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
pub struct LayoutContext {
|
pub struct LayoutContext {
|
||||||
@ -169,12 +169,19 @@ without UI components as a child of an entity with UI components, results may be
|
|||||||
.iter()
|
.iter()
|
||||||
.find(|n| n.user_root_node == node)
|
.find(|n| n.user_root_node == node)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_else(|| RootNodePair {
|
.unwrap_or_else(|| {
|
||||||
|
if let Some(previous_parent) = self.taffy.parent(node) {
|
||||||
|
// remove the root node from the previous implicit node's children
|
||||||
|
self.taffy.remove_child(previous_parent, node).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
RootNodePair {
|
||||||
implicit_viewport_node: self
|
implicit_viewport_node: self
|
||||||
.taffy
|
.taffy
|
||||||
.new_with_children(viewport_style.clone(), &[node])
|
.new_with_children(viewport_style.clone(), &[node])
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
user_root_node: node,
|
user_root_node: node,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
new_roots.push(root_node);
|
new_roots.push(root_node);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user