Skip to content

Commit

Permalink
Implement horizontal scrolling and per-axis scroll control
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoburns committed Apr 18, 2023
1 parent 4033477 commit 29aa3a0
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 21 deletions.
9 changes: 4 additions & 5 deletions crates/bevy_ui/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_ui/src/ui_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,16 @@ 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,
}

impl ScrollPosition {
pub const DEFAULT: Self = Self {
is_hovered: false,
offset_x: 0.0,
offset_y: 0.0,
};
}
Expand Down
39 changes: 26 additions & 13 deletions crates/bevy_ui/src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.);
}
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions examples/ui/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
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(),
Expand All @@ -97,7 +98,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
NodeBundle {
style: Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
align_items: AlignItems::Start,
size: Size::width(Val::Px(600.)),
..default()
},
..default()
Expand All @@ -109,7 +111,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
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"),
Expand Down

0 comments on commit 29aa3a0

Please sign in to comment.