-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restore pre 0.13.1 Root Node Layout behavior #12698
Restore pre 0.13.1 Root Node Layout behavior #12698
Conversation
…f they were absolutely positioned
1e2fe00
to
f7b420a
Compare
Following @nicoburns suggestion, I was able to reduce the complexity/redundant maps in the unapplied Diff below.
Edit: figured it out, see comment below Click to show DiffIndex: crates/bevy_ui/src/layout/mod.rs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/crates/bevy_ui/src/layout/mod.rs b/crates/bevy_ui/src/layout/mod.rs
--- a/crates/bevy_ui/src/layout/mod.rs (revision Staged)
+++ b/crates/bevy_ui/src/layout/mod.rs (date 1711341109941)
@@ -52,8 +52,7 @@
#[derive(Resource)]
pub struct UiSurface {
entity_to_taffy: EntityHashMap<taffy::node::Node>,
- camera_entity_to_taffy: EntityHashMap<EntityHashMap<taffy::node::Node>>,
- camera_roots: EntityHashMap<Vec<RootNodePair>>,
+ camera_to_root_to_root_node_pair: EntityHashMap<EntityHashMap<RootNodePair>>,
taffy: Taffy,
}
@@ -68,7 +67,10 @@
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("UiSurface")
.field("entity_to_taffy", &self.entity_to_taffy)
- .field("camera_roots", &self.camera_roots)
+ .field(
+ "camera_to_root_to_root_node_pair",
+ &self.camera_to_root_to_root_node_pair,
+ )
.finish()
}
}
@@ -79,8 +81,7 @@
taffy.disable_rounding();
Self {
entity_to_taffy: Default::default(),
- camera_entity_to_taffy: Default::default(),
- camera_roots: Default::default(),
+ camera_to_root_to_root_node_pair: Default::default(),
taffy,
}
}
@@ -168,40 +169,34 @@
..default()
};
- let camera_root_node_map = self.camera_entity_to_taffy.entry(camera_id).or_default();
- let existing_roots = self.camera_roots.entry(camera_id).or_default();
- let mut new_roots = Vec::new();
+ let entity_to_root_node_pair = self
+ .camera_to_root_to_root_node_pair
+ .entry(camera_id)
+ .or_default();
for entity in children {
- let node = *self.entity_to_taffy.get(&entity).unwrap();
- let root_node = existing_roots
- .iter()
- .find(|n| n.user_root_node == node)
- .cloned()
- .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();
- }
-
- let viewport_node = *camera_root_node_map
- .entry(entity)
- .or_insert_with(|| self.taffy.new_leaf(viewport_style.clone()).unwrap());
- self.taffy.add_child(viewport_node, node).unwrap();
-
- RootNodePair {
- implicit_viewport_node: viewport_node,
- user_root_node: node,
- }
- });
- new_roots.push(root_node);
+ let root_node_pair = entity_to_root_node_pair.entry(entity).or_insert_with(|| RootNodePair {
+ implicit_viewport_node: self.taffy.new_leaf(viewport_style.clone()).unwrap(),
+ user_root_node: *self.entity_to_taffy.get(&entity).expect("root node was not created yet or has been deleted from `entity_to_taffy` prematurely"),
+ });
+ if let Some(previous_parent) = self.taffy.parent(root_node_pair.user_root_node) {
+ // remove the root node from the previous implicit node's children
+ self.taffy
+ .remove_child(previous_parent, root_node_pair.user_root_node)
+ .unwrap();
+ }
+ self.taffy
+ .add_child(
+ root_node_pair.implicit_viewport_node,
+ root_node_pair.user_root_node,
+ )
+ .unwrap();
}
-
- self.camera_roots.insert(camera_id, new_roots);
}
/// Compute the layout for each window entity's corresponding root node in the layout.
pub fn compute_camera_layout(&mut self, camera: Entity, render_target_resolution: UVec2) {
- let Some(camera_root_nodes) = self.camera_roots.get(&camera) else {
+ let Some(entity_to_root_node_pair) = self.camera_to_root_to_root_node_pair.get(&camera)
+ else {
return;
};
@@ -209,9 +204,9 @@
width: taffy::style::AvailableSpace::Definite(render_target_resolution.x as f32),
height: taffy::style::AvailableSpace::Definite(render_target_resolution.y as f32),
};
- for root_nodes in camera_root_nodes {
+ for (_, root_node_pair) in entity_to_root_node_pair.iter() {
self.taffy
- .compute_layout(root_nodes.implicit_viewport_node, available_space)
+ .compute_layout(root_node_pair.implicit_viewport_node, available_space)
.unwrap();
}
}
@@ -219,9 +214,14 @@
/// Removes each camera entity from the internal map and then removes their associated node from taffy
pub fn remove_camera_entities(&mut self, entities: impl IntoIterator<Item = Entity>) {
for entity in entities {
- if let Some(camera_root_node_map) = self.camera_entity_to_taffy.remove(&entity) {
- for (_, node) in camera_root_node_map.iter() {
- self.taffy.remove(*node).unwrap();
+ if let Some(entity_to_root_node_pair) =
+ self.camera_to_root_to_root_node_pair.remove(&entity)
+ {
+ for (_, remove_root_node_pair) in entity_to_root_node_pair.iter() {
+ //self.taffy.remove(remove_root_node_pair.user_root_node).unwrap();
+ self.taffy
+ .remove(remove_root_node_pair.implicit_viewport_node)
+ .unwrap();
}
}
}
@@ -699,7 +699,7 @@
// no UI entities in world, none in UiSurface
let ui_surface = world.resource::<UiSurface>();
- assert!(ui_surface.camera_entity_to_taffy.is_empty());
+ assert!(ui_surface.camera_to_root_to_root_node_pair.is_empty());
// respawn camera
let camera_entity = world.spawn(Camera2dBundle::default()).id();
@@ -713,9 +713,9 @@
let ui_surface = world.resource::<UiSurface>();
assert!(ui_surface
- .camera_entity_to_taffy
+ .camera_to_root_to_root_node_pair
.contains_key(&camera_entity));
- assert_eq!(ui_surface.camera_entity_to_taffy.len(), 1);
+ assert_eq!(ui_surface.camera_to_root_to_root_node_pair.len(), 1);
world.despawn(ui_entity);
world.despawn(camera_entity);
@@ -725,9 +725,9 @@
let ui_surface = world.resource::<UiSurface>();
assert!(!ui_surface
- .camera_entity_to_taffy
+ .camera_to_root_to_root_node_pair
.contains_key(&camera_entity));
- assert!(ui_surface.camera_entity_to_taffy.is_empty());
+ assert!(ui_surface.camera_to_root_to_root_node_pair.is_empty());
}
#[test]
Index: crates/bevy_ui/src/layout/debug.rs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/crates/bevy_ui/src/layout/debug.rs b/crates/bevy_ui/src/layout/debug.rs
--- a/crates/bevy_ui/src/layout/debug.rs (revision Staged)
+++ b/crates/bevy_ui/src/layout/debug.rs (date 1711341205596)
@@ -12,20 +12,20 @@
.iter()
.map(|(entity, node)| (*node, *entity))
.collect();
- for (&entity, roots) in &ui_surface.camera_roots {
+ for (&camera_entity, entity_to_root_pair) in &ui_surface.camera_to_root_to_root_node_pair {
let mut out = String::new();
- for root in roots {
+ for (root_node_entity, entity_to_root_node_pair) in entity_to_root_pair.iter() {
print_node(
ui_surface,
&taffy_to_entity,
- entity,
- root.implicit_viewport_node,
+ *root_node_entity,
+ entity_to_root_node_pair.implicit_viewport_node,
false,
String::new(),
&mut out,
);
}
- bevy_utils::tracing::info!("Layout tree for camera entity: {entity:?}\n{out}");
+ bevy_utils::tracing::info!("Layout tree for camera entity: {camera_entity:?}\n{out}");
}
}
@@ -33,6 +33,7 @@
fn print_node(
ui_surface: &UiSurface,
taffy_to_entity: &HashMap<Node, Entity>,
+ // TODO: unused
entity: Entity,
node: Node,
has_sibling: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tested this, but the code change looks about right to me.
Not sure what's going on with that diff, but it's not rendering properly at all. |
@ethereumdegen @extrawurst @FylmTM: if one of you can test that this fix resolves the regression you saw for your UI, that would be very helpful. |
Whoops. Fixed. |
@nicoburns I was able to dedupe the mappings here I was thinking of keeping the But IMO, either way, that should be a follow-up PR with its own discussion on semantics/optimization suggestions, as the scope of this one is to fix the regression. |
# Objective Fix the regression for Root Node's Layout behavior introduced in #12268 - Add regression test for Root Node Layout's behaving as they did before 0.13.1 - Restore pre 0.13.1 Root Node Layout behavior (fixes #12624) ## Solution This implements [@nicoburns suggestion ](https://discord.com/channels/691052431525675048/743663673393938453/1221593626476548146), where instead of adding the camera to the taffy node tree, we revert back to adding a new "parent" node for each root node while maintaining their relationship with the camera. > If you can do the ecs change detection to move the node to the correct Taffy instance for the camera then you should also be able to move it to a `Vec` of root nodes for that camera. --- ## Changelog Fixed #12624 - Restores pre 0.13.1 Root Node Layout behavior ## Migration Guide If you were affected by the 0.13.1 regression and added `position_type: Absolute` to all your root nodes you might be able to reclaim some LOC by removing them now that the 0.13 behavior is restored.
Apply rustfmt Move test_initialization next to other tests Add doc comment to is_root_node_pair_valid Move helper methods into the single test case where they are used Add tests for helper methods Remove trait helpers to reduce complexity of tests Mark specific test functions as unreachable Move ui_surface test only methods into mod tests as trait Fix tests after rebase Add tests for bevy_ui/layout/ui_surface Widen type for parameter children in UiSurface::update_children Add missing asserts and Debug fields in UiSurface from bevyengine#12268 and bevyengine#12698
Objective
Fix the regression for Root Node's Layout behavior introduced in #12268
Solution
This implements @nicoburns suggestion , where instead of adding the camera to the taffy node tree, we revert back to adding a new "parent" node for each root node while maintaining their relationship with the camera.
Changelog
Fixed #12624 - Restores pre 0.13.1 Root Node Layout behavior
Migration Guide
If you were affected by the 0.13.1 regression and added
position_type: Absolute
to all your root nodes you might be able to reclaim some LOC by removing them now that the 0.13 behavior is restored.