`ScrollPositions` does not work on `Node` with `flex_direction` set to `RowReverse`
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## Bevy version
v0.15
## \[Optional\] Relevant system information
```
2025-01-03T20:16:22.418810Z INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Linux 24.11 NixOS", kernel: "6.6.63", cpu: "Intel(R) Core(TM) i7-14700KF", core_count: "20", memory: "31.2 GiB" }
2025-01-03T20:16:22.566379Z INFO bevy_render::renderer: AdapterInfo { name: "NVIDIA GeForce RTX 4060 Ti", vendor: 4318, device: 10243, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "560.35.03", backend: Vulkan }
```
## What you did
Created a `Node` with `flex_direction` set to `RowReverse` or `ColumnReverse` and scrolling enabled, updated the value of the offset in `ScrollPosition`.
## What went wrong
Offsets of `ScrollPosition` are clamped to `0, 0` as if already scrolled to the end, when trying to scroll either way.
## Additional information
```rust
use bevy::{
app::{App, Startup, Update},
color::{palettes, Color},
prelude::{
BuildChildren, Camera2d, ChildBuild, ChildBuilder, Commands, Component, Local, Query, Text,
With, Without,
},
text::TextColor,
ui::{BackgroundColor, FlexDirection, Node, Overflow, ScrollPosition, Val},
DefaultPlugins,
};
#[derive(Component)]
struct Row;
#[derive(Component)]
struct Column;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, (scroll_x, scroll_y))
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d);
let colors: &[Color] = &[
palettes::tailwind::BLUE_100.into(),
palettes::tailwind::GREEN_100.into(),
];
let row_spawner = |parent: &mut ChildBuilder, flex_direction, max_width| {
parent
.spawn((
Row,
Node {
max_width,
flex_direction,
overflow: Overflow::scroll_x(),
..Default::default()
},
))
.with_children(|parent| {
for i in 0..50 {
parent
.spawn((
Node {
min_width: Val::Px(50.),
min_height: Val::Px(50.),
justify_content: bevy::ui::JustifyContent::SpaceEvenly,
align_content: bevy::ui::AlignContent::SpaceEvenly,
..Default::default()
},
BackgroundColor(colors[i % 2]),
))
.with_child((Text::new(i.to_string()), TextColor(Color::BLACK)));
}
});
};
let col_spawner = |parent: &mut ChildBuilder, flex_direction, max_height| {
parent
.spawn((
Column,
Node {
max_height,
flex_direction,
overflow: Overflow::scroll_y(),
..Default::default()
},
))
.with_children(|parent| {
for i in 0..50 {
parent
.spawn((
Node {
min_width: Val::Px(50.),
min_height: Val::Px(50.),
justify_content: bevy::ui::JustifyContent::SpaceEvenly,
align_content: bevy::ui::AlignContent::SpaceEvenly,
..Default::default()
},
BackgroundColor(colors[i % 2]),
))
.with_child((Text::new(i.to_string()), TextColor(Color::BLACK)));
}
});
};
commands
.spawn(Node {
flex_direction: FlexDirection::Column,
..Default::default()
})
.with_children(|parent| {
row_spawner(parent, FlexDirection::Row, Val::Vw(50.));
row_spawner(parent, FlexDirection::RowReverse, Val::Vw(50.));
parent.spawn(Node::default()).with_children(|parent| {
col_spawner(parent, FlexDirection::Column, Val::Vh(50.));
col_spawner(parent, FlexDirection::ColumnReverse, Val::Vh(50.));
});
});
}
fn scroll_x(
mut rows: Query<&mut ScrollPosition, (With, Without)>,
mut local: Local,
) {
let f: fn(&mut f32) = if *local & 0x100 != 0 {
|x| *x -= 2.
} else {
|x| *x += 2.
};
for mut row in rows.iter_mut() {
f(&mut row.offset_x);
}
*local += 1;
}
fn scroll_y(
mut columns: Query<&mut ScrollPosition, (With, Without)>,
mut local: Local,
) {
let f: fn(&mut f32) = if *local & 0x100 != 0 {
|x| *x -= 2.
} else {
|x| *x += 2.
};
for mut column in columns.iter_mut() {
f(&mut column.offset_y);
}
*local += 1;
}
```
Contributor guide
Assessment
This issue has not been assessed yet.