use bevy::{input::mouse::{MouseScrollUnit, MouseWheel}, picking::focus::HoverMap, prelude::*};
use bevy_simple_scrollbar::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, SimpleScrollbarPlugin::default()))
.add_systems(Startup, setup)
.add_systems(Update, (update_scroll_position, change_ui_scale))
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn((
Node {
left: Val::Percent(50.0),
top: Val::Percent(20.0),
height: Val::Percent(50.0),
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::FlexStart,
align_items: AlignItems::FlexStart,
..default()
},
BackgroundColor (Color::Srgba(Srgba { red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0 })),
)).with_children(|parent| {
let scroll_area_id = parent.spawn((
Node {
flex_direction: FlexDirection::Column,
align_self: AlignSelf::Stretch,
overflow: Overflow::scroll_y(),
..default()
},
)).with_children(|parent| {
for i in 0..50 {
parent.spawn((
Node {
margin: UiRect { left: Val::Px(3.0), right: Val::Px(3.0), top: Val::Px(3.0), bottom: Val::Px(3.0) },
..default()
},
Text(format!("Item {i}")),
TextFont {
font: asset_server.load(
"fonts/Gantari-Regular.ttf",
),
..default()
},
))
.insert(PickingBehavior {
should_block_lower: false,
..default()
});
}
}).id();
parent.spawn((
Node {
width: Val::Px(8.0),
height: Val::Percent(100.0), top: Val::Px(0.0), ..default()
},
BackgroundColor (Color::Srgba(Srgba { red: 0.3, green: 0.3, blue: 0.3, alpha: 1.0 })),
Scrollbar::new(
ScrollbarDirection::Vertical,
scroll_area_id,
),
));
});
commands.spawn((
Node {
left: Val::Percent(25.0),
top: Val::Percent(75.0),
width: Val::Percent(50.0),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::FlexStart,
align_items: AlignItems::FlexStart,
..default()
},
BackgroundColor (Color::Srgba(Srgba { red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0 })),
)).with_children(|parent| {
let scroll_area_id = parent.spawn((
Node {
flex_direction: FlexDirection::Row,
align_self: AlignSelf::Stretch,
overflow: Overflow::scroll_x(),
..default()
},
)).with_children(|parent| {
for i in 0..50 {
parent.spawn((
Node {
margin: UiRect { left: Val::Px(3.0), right: Val::Px(3.0), top: Val::Px(3.0), bottom: Val::Px(3.0) },
..default()
},
Text(format!("Item {i}")),
TextFont {
font: asset_server.load(
"fonts/Gantari-Regular.ttf",
),
..default()
},
))
.insert(PickingBehavior {
should_block_lower: false,
..default()
});
}
}).id();
parent.spawn((
Node {
height: Val::Px(8.0),
width: Val::Percent(100.0), left: Val::Px(0.0), ..default()
},
BackgroundColor (Color::Srgba(Srgba { red: 0.3, green: 0.3, blue: 0.3, alpha: 1.0 })),
Scrollbar::new(
ScrollbarDirection::Horizontal,
scroll_area_id,
),
));
});
}
fn update_scroll_position(
mut mouse_wheel_events: EventReader<MouseWheel>,
hover_map: Res<HoverMap>,
mut scrolled_node_query: Query<&mut ScrollPosition>,
keyboard_input: Res<ButtonInput<KeyCode>>,
) {
for mouse_wheel_event in mouse_wheel_events.read() {
let (mut dx, mut dy) = match mouse_wheel_event.unit {
MouseScrollUnit::Line => (
mouse_wheel_event.x * 21.0,
mouse_wheel_event.y * 21.0,
),
MouseScrollUnit::Pixel => (mouse_wheel_event.x, mouse_wheel_event.y),
};
if keyboard_input.pressed(KeyCode::ControlLeft) || keyboard_input.pressed(KeyCode::ControlRight) {
std::mem::swap(&mut dx, &mut dy);
}
for (_pointer, pointer_map) in hover_map.iter() {
for (entity, _hit) in pointer_map.iter() {
if let Ok(mut scroll_position) = scrolled_node_query.get_mut(*entity) {
scroll_position.offset_x -= dx;
scroll_position.offset_y -= dy;
}
}
}
}
}
fn change_ui_scale(
mut ui_scale: ResMut<UiScale>,
keyboard_input: Res<ButtonInput<KeyCode>>,
) {
if keyboard_input.just_pressed(KeyCode::PageUp) {
ui_scale.0 += ui_scale.0/10.0;
}
if keyboard_input.just_pressed(KeyCode::PageDown) {
ui_scale.0 -= ui_scale.0/10.0;
}
ui_scale.0 = ui_scale.0.clamp(0.25, 3.0)
}