diff --git a/crates/bevy_ui/src/layout/mod.rs b/crates/bevy_ui/src/layout/mod.rs index 2ea6894b49b84..9a39924e0d753 100644 --- a/crates/bevy_ui/src/layout/mod.rs +++ b/crates/bevy_ui/src/layout/mod.rs @@ -2934,4 +2934,42 @@ mod tests { .abs_diff_eq(Vec2::new(50., 30.), 1e-5)); } } + + #[test] + fn rounding_test() { + // Regression test to ensure that updating layout properties (like width) + // and computing layouts with/without rounding works correctly + // without corrupting Taffy state or the calculated size. + let mut app = setup_ui_test_app(); + + let root = app + .world_mut() + .spawn(Node { + width: px(100.), + height: px(100.), + ..default() + }) + .with_child(( + Node::default(), + LayoutConfig { + use_rounding: false, + }, + )) + .id(); + + app.update(); + + assert_eq!( + app.world().get::(root).unwrap().size(), + Vec2::splat(100.) + ); + + app.world_mut().get_mut::(root).unwrap().width = px(200.); + app.update(); + + assert_eq!( + app.world().get::(root).unwrap().size(), + Vec2::new(200., 100.) + ); + } } diff --git a/crates/bevy_ui/src/layout/ui_surface.rs b/crates/bevy_ui/src/layout/ui_surface.rs index 813128f4e16da..65ea8e9ea9e2b 100644 --- a/crates/bevy_ui/src/layout/ui_surface.rs +++ b/crates/bevy_ui/src/layout/ui_surface.rs @@ -232,6 +232,10 @@ impl UiSurface { ) { let implicit_viewport_node = self.get_or_insert_taffy_viewport_node(ui_root_entity); + // Ensure rounding is enabled globally before computing the layout tree, + // as enable/disable_rounding controls whether rounded node geometry is created during layout. + self.taffy.enable_rounding(); + let available_space = taffy::geometry::Size { width: taffy::style::AvailableSpace::Definite(render_target_resolution.x as f32), height: taffy::style::AvailableSpace::Definite(render_target_resolution.y as f32), @@ -315,24 +319,26 @@ impl UiSurface { return Err(UiSurfaceError::NoAssociatedTaffyNode); }; + // Note: Taffy's enable/disable_rounding has a dual purpose: + // 1. It controls whether rounded geometry is generated during compute_layout. + // 2. It controls whether the per-node layout() getter returns rounded or unrounded geometry. + // Here we temporarily toggle it to fetch the unrounded size regardless of the global state. if use_rounding { self.taffy.enable_rounding(); } else { self.taffy.disable_rounding(); } - let out = match self.taffy.layout(taffy_node.id).cloned() { - Ok(layout) => { - self.taffy.disable_rounding(); - let taffy_size = self.taffy.layout(taffy_node.id).unwrap().size; - let unrounded_size = Vec2::new(taffy_size.width, taffy_size.height); - Ok((layout, unrounded_size)) - } - Err(taffy_error) => Err(UiSurfaceError::TaffyError(taffy_error)), - }; + let layout = self.taffy.layout(taffy_node.id).cloned(); - self.taffy.enable_rounding(); - out + self.taffy.disable_rounding(); + let taffy_size = self.taffy.layout(taffy_node.id).unwrap().size; + let unrounded_size = Vec2::new(taffy_size.width, taffy_size.height); + + match layout { + Ok(l) => Ok((l, unrounded_size)), + Err(taffy_error) => Err(UiSurfaceError::TaffyError(taffy_error)), + } } /// Returns the number of children belonging to the entity's associated taffy node.