diff --git a/crates/bevy_ui/src/layout/mod.rs b/crates/bevy_ui/src/layout/mod.rs index c192476984ab4..839086a32917b 100644 --- a/crates/bevy_ui/src/layout/mod.rs +++ b/crates/bevy_ui/src/layout/mod.rs @@ -360,13 +360,12 @@ pub fn ui_layout_system( } // Adjust position by the scroll offset of the parent - let x_scroll_position = 0.0; // TODO: implement horizontal scrolling - new_position.x += x_scroll_position; - let y_scroll_position = scroll_position_query + let (x_scroll_position, y_scroll_position) = scroll_position_query .get(**parent) .ok() - .and_then(|(_, p)| p.map(|p| p.offset_y)) - .unwrap_or(0.0); + .and_then(|(_, p)| p.map(|p| (p.offset_x, p.offset_y))) + .unwrap_or((0.0, 0.0)); + new_position.x += x_scroll_position; new_position.y += y_scroll_position; } // only trigger change detection when the new value is different diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index b078f553e8eea..ad32c145d5de2 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -63,6 +63,8 @@ impl Default for Node { #[reflect(Component, Default)] pub struct ScrollPosition { pub is_hovered: bool, + /// How far accross the node is scrolled (0 = not scrolled / scrolled to right) + pub offset_x: f32, /// How far down the node is scrolled (0 = not scrolled / scrolled to top) pub offset_y: f32, } @@ -70,6 +72,7 @@ pub struct ScrollPosition { impl ScrollPosition { pub const DEFAULT: Self = Self { is_hovered: false, + offset_x: 0.0, offset_y: 0.0, }; } diff --git a/crates/bevy_ui/src/update.rs b/crates/bevy_ui/src/update.rs index e0cd62d132012..3b99847f1f2e1 100644 --- a/crates/bevy_ui/src/update.rs +++ b/crates/bevy_ui/src/update.rs @@ -114,22 +114,35 @@ pub fn update_scroll_position( query_node: Query<&Node>, ) { for mouse_wheel_event in mouse_wheel_events.iter() { - for (mut scroll_container, style, children, list_node) in &mut query_list { - if style.overflow.y == OverflowAxis::Scroll && scroll_container.is_hovered { - let container_height = list_node.size().y; - let items_height: f32 = children - .iter() - .map(|child| query_node.get(*child).unwrap().size().y) - .sum(); + let (dx, dy) = match mouse_wheel_event.unit { + MouseScrollUnit::Line => (mouse_wheel_event.x * 20., mouse_wheel_event.y * 20.), + MouseScrollUnit::Pixel => (mouse_wheel_event.x, mouse_wheel_event.y), + }; - let max_scroll = (items_height - container_height).max(0.); + for (mut scroll_container, style, children, list_node) in &mut query_list { + if scroll_container.is_hovered { + if style.overflow.x == OverflowAxis::Scroll { + let container_width = list_node.size().x; + let items_width: f32 = children + .iter() + .map(|child| query_node.get(*child).unwrap().size().x) + .sum(); - let dy = match mouse_wheel_event.unit { - MouseScrollUnit::Line => mouse_wheel_event.y * 20., - MouseScrollUnit::Pixel => mouse_wheel_event.y, - }; + let max_scroll_x = (items_width - container_width).max(0.); + scroll_container.offset_x = + (scroll_container.offset_x + dx).clamp(-max_scroll_x, 0.); + } + if style.overflow.y == OverflowAxis::Scroll { + let container_height = list_node.size().y; + let items_height: f32 = children + .iter() + .map(|child| query_node.get(*child).unwrap().size().y) + .sum(); - scroll_container.offset_y = (scroll_container.offset_y + dy).clamp(-max_scroll, 0.); + let max_scroll_y = (items_height - container_height).max(0.); + scroll_container.offset_y = + (scroll_container.offset_y + dy).clamp(-max_scroll_y, 0.); + } } } } diff --git a/examples/ui/ui.rs b/examples/ui/ui.rs index 945bd1300abb8..3d75e10359d74 100644 --- a/examples/ui/ui.rs +++ b/examples/ui/ui.rs @@ -84,7 +84,8 @@ fn setup(mut commands: Commands, asset_server: Res) { flex_direction: FlexDirection::Column, align_self: AlignSelf::Stretch, size: Size::height(Val::Percent(50.)), - overflow: Overflow::scroll_y(), + align_items: AlignItems::Start, + overflow: Overflow::scroll(), ..default() }, background_color: Color::rgb(0.10, 0.10, 0.10).into(), @@ -97,7 +98,8 @@ fn setup(mut commands: Commands, asset_server: Res) { NodeBundle { style: Style { flex_direction: FlexDirection::Column, - align_items: AlignItems::Center, + align_items: AlignItems::Start, + size: Size::width(Val::Px(600.)), ..default() }, ..default() @@ -109,7 +111,7 @@ fn setup(mut commands: Commands, asset_server: Res) { for i in 0..100 { parent.spawn(( TextBundle::from_section( - format!("Item {}", i + 1), + format!("Item {} rhgiuherwiofhioewhfgioewhgioewhioghweioghiowhewiohgio", i + 1), TextStyle { font: asset_server .load("fonts/FiraSans-Bold.ttf"),