Skip to content

Commit

Permalink
Round UI coordinates after scaling (#9784)
Browse files Browse the repository at this point in the history
# Objective

Fixes #9754

## Solution

Don't round UI coordinates until they've been multiplied by the inverse
scale factor.
  • Loading branch information
ickshonpe committed Sep 18, 2023
1 parent 4442451 commit 07f61a1
Showing 1 changed file with 67 additions and 12 deletions.
79 changes: 67 additions & 12 deletions crates/bevy_ui/src/layout/mod.rs
Expand Up @@ -317,24 +317,23 @@ pub fn ui_layout_system(
) {
if let Ok((mut node, mut transform)) = node_transform_query.get_mut(entity) {
let layout = ui_surface.get_layout(entity).unwrap();
let layout_size = Vec2::new(layout.size.width, layout.size.height);
let layout_location = Vec2::new(layout.location.x, layout.location.y);
let layout_size =
inverse_target_scale_factor * Vec2::new(layout.size.width, layout.size.height);
let layout_location =
inverse_target_scale_factor * Vec2::new(layout.location.x, layout.location.y);

absolute_location += layout_location;
let rounded_location = round_layout_coords(layout_location);
let rounded_size = round_layout_coords(absolute_location + layout_size)
- round_layout_coords(absolute_location);

let new_size = inverse_target_scale_factor * rounded_size;
let new_position =
inverse_target_scale_factor * rounded_location + 0.5 * (new_size - parent_size);
let rounded_location =
round_layout_coords(layout_location) + 0.5 * (rounded_size - parent_size);

// only trigger change detection when the new values are different
if node.calculated_size != new_size {
node.calculated_size = new_size;
if node.calculated_size != rounded_size {
node.calculated_size = rounded_size;
}
if transform.translation.truncate() != new_position {
transform.translation = new_position.extend(0.);
if transform.translation.truncate() != rounded_location {
transform.translation = rounded_location.extend(0.);
}
if let Ok(children) = children_query.get(entity) {
for &child_uinode in children {
Expand All @@ -344,7 +343,7 @@ pub fn ui_layout_system(
node_transform_query,
children_query,
inverse_target_scale_factor,
new_size,
rounded_size,
absolute_location,
);
}
Expand Down Expand Up @@ -400,11 +399,13 @@ mod tests {
use crate::ui_layout_system;
use crate::ContentSize;
use crate::UiSurface;
use bevy_ecs::entity::Entity;
use bevy_ecs::event::Events;
use bevy_ecs::schedule::Schedule;
use bevy_ecs::world::World;
use bevy_hierarchy::despawn_with_children_recursive;
use bevy_hierarchy::BuildWorldChildren;
use bevy_hierarchy::Children;
use bevy_math::vec2;
use bevy_math::Vec2;
use bevy_utils::prelude::default;
Expand Down Expand Up @@ -714,4 +715,58 @@ mod tests {
assert_eq!(layout.size.width, 0.);
assert_eq!(layout.size.height, 0.);
}

#[test]
fn ui_rounding_test() {
let (mut world, mut ui_schedule) = setup_ui_test_world();

let parent = world
.spawn(NodeBundle {
style: Style {
display: Display::Grid,
grid_template_columns: RepeatedGridTrack::min_content(2),
margin: UiRect::all(Val::Px(4.0)),
..Default::default()
},
..Default::default()
})
.with_children(|commands| {
for _ in 0..2 {
commands.spawn(NodeBundle {
style: Style {
display: Display::Grid,
width: Val::Px(160.),
height: Val::Px(160.),
..Default::default()
},
..Default::default()
});
}
})
.id();

let children = world
.entity(parent)
.get::<Children>()
.unwrap()
.iter()
.copied()
.collect::<Vec<Entity>>();

for r in [2, 3, 5, 7, 11, 13, 17, 19, 21, 23, 29, 31].map(|n| (n as f64).recip()) {
let mut s = r;
while s <= 5. {
world.resource_mut::<UiScale>().0 = s;
ui_schedule.run(&mut world);
let width_sum: f32 = children
.iter()
.map(|child| world.get::<Node>(*child).unwrap().calculated_size.x)
.sum();
let parent_width = world.get::<Node>(parent).unwrap().calculated_size.x;
assert!((width_sum - parent_width).abs() < 0.001);
assert!((width_sum - 320.).abs() <= 1.);
s += r;
}
}
}
}

0 comments on commit 07f61a1

Please sign in to comment.