ScrollPosition scale factor fix (#16617)

# Objective

Scroll position uses physical coordinates. This means scrolling may go
faster or slower depending on the scroll factor. Also the scrolled
position will change when the scale factor changes.

## Solution

In `ui_layout_system` convert `max_possible_offset` to logical
coordinates before clamping the scroll position. Then convert the
clamped scroll position to physical coordinates before propagating it to
the node's children.

## Testing

Look at the `scroll` example. On main if you change your display's scale
factor the items displayed by the scrolling lists will change because
`ScrollPosition`'s displacement values don't respect scale factor. With
this PR the displacement will be scaled too, and the won't move.
This commit is contained in:
ickshonpe 2024-12-16 23:31:21 +00:00 committed by François Mockers
parent 54733e82ae
commit 75c9e7a198
2 changed files with 13 additions and 7 deletions

View File

@ -433,14 +433,20 @@ with UI components as a child of an entity without UI components, your UI layout
let content_size = Vec2::new(layout.content_size.width, layout.content_size.height);
let max_possible_offset = (content_size - layout_size).max(Vec2::ZERO);
let clamped_scroll_position = scroll_position.clamp(Vec2::ZERO, max_possible_offset);
let clamped_scroll_position = scroll_position.clamp(
Vec2::ZERO,
max_possible_offset * inverse_target_scale_factor,
);
if clamped_scroll_position != scroll_position {
commands
.entity(entity)
.insert(ScrollPosition::from(&clamped_scroll_position));
.insert(ScrollPosition::from(clamped_scroll_position));
}
let physical_scroll_position =
(clamped_scroll_position / inverse_target_scale_factor).round();
for child_uinode in ui_children.iter_ui_children(entity) {
update_uinode_geometry_recursive(
commands,
@ -451,7 +457,7 @@ with UI components as a child of an entity without UI components, your UI layout
ui_children,
inverse_target_scale_factor,
layout_size,
clamped_scroll_position,
physical_scroll_position,
);
}
}

View File

@ -237,9 +237,9 @@ impl Default for ComputedNode {
#[derive(Component, Debug, Clone, Reflect)]
#[reflect(Component, Default)]
pub struct ScrollPosition {
/// How far across the node is scrolled, in pixels. (0 = not scrolled / scrolled to right)
/// How far across the node is scrolled, in logical pixels. (0 = not scrolled / scrolled to right)
pub offset_x: f32,
/// How far down the node is scrolled, in pixels. (0 = not scrolled / scrolled to top)
/// How far down the node is scrolled, in logical pixels. (0 = not scrolled / scrolled to top)
pub offset_y: f32,
}
@ -262,8 +262,8 @@ impl From<&ScrollPosition> for Vec2 {
}
}
impl From<&Vec2> for ScrollPosition {
fn from(vec: &Vec2) -> Self {
impl From<Vec2> for ScrollPosition {
fn from(vec: Vec2) -> Self {
ScrollPosition {
offset_x: vec.x,
offset_y: vec.y,