@@ 6,7 6,7 @@
* See LICENSE for licensing information.
*/
-use bevy::prelude::*;
+use bevy::{prelude::*, input::mouse::{MouseScrollUnit, MouseWheel}, a11y::{AccessibilityNode, accesskit::NodeBuilder}};
use crate::AppState;
@@ 14,11 14,13 @@ pub struct LogPlugin;
impl Plugin for LogPlugin {
fn build(&self, app: &mut App) {
- app.add_event::<UpdateLogEvent>()
+ app.add_event::<ToggleLogEvent>()
+ .add_event::<UpdateLogEvent>()
.add_system(setup_log.in_schedule(OnEnter(AppState::InGame)))
.add_system(update_log_button)
.add_system(toggle_log.run_if(on_event::<ToggleLogEvent>()))
- .add_system(update_log.run_if(on_event::<UpdateLogEvent>()));
+ .add_system(update_log.run_if(on_event::<UpdateLogEvent>()))
+ .add_system(log_mouse_scroll);
}
}
@@ 40,8 42,9 @@ fn setup_log(mut commands: Commands, asset_server: Res<AssetServer>) {
let font = asset_server.load("fonts/FiraMono-Bold.ttf");
+ // log toggle button
commands
- .spawn((NodeBundle {
+ .spawn(NodeBundle {
style: Style {
position_type: PositionType::Absolute,
position: UiRect {
@@ 52,7 55,7 @@ fn setup_log(mut commands: Commands, asset_server: Res<AssetServer>) {
..Default::default()
},
..Default::default()
- },))
+ })
.with_children(|parent| {
parent
.spawn((
@@ 82,6 85,73 @@ fn setup_log(mut commands: Commands, asset_server: Res<AssetServer>) {
));
});
});
+
+ // log window
+ commands
+ .spawn(NodeBundle {
+ style: Style {
+ flex_direction: FlexDirection::Column,
+ justify_content: JustifyContent::Center,
+ align_items: AlignItems::Center,
+ size: Size {
+ width: Val::Px(300.),
+ height: Val::Px(300.),
+ },
+ position_type: PositionType::Absolute,
+ position: UiRect {
+ bottom: Val::Percent(12.5),
+ right: Val::Px(100.),
+ ..Default::default()
+ },
+ ..Default::default()
+ },
+ background_color: Color::rgb(0.15, 0.15, 0.15).into(),
+ ..Default::default()
+ })
+ .with_children(|parent| {
+ parent
+ .spawn(NodeBundle {
+ style: Style {
+ flex_direction: FlexDirection::Column,
+ align_self: AlignSelf::Stretch,
+ size: Size::all(Val::Percent(95.)),
+ overflow: Overflow::Hidden,
+ ..Default::default()
+ },
+ ..Default::default()
+ })
+ .with_children(|parent| {
+ parent
+ .spawn((
+ NodeBundle {
+ style: Style {
+ flex_direction: FlexDirection::Column,
+ max_size: Size::UNDEFINED,
+ ..Default::default()
+ },
+ ..Default::default()
+ },
+ AccessibilityNode(NodeBuilder::new(bevy::a11y::accesskit::Role::List)),
+ ScrollingList::default(),
+ LogList,
+ ))
+ .with_children(|parent| {
+ for i in 0..30 {
+ parent.spawn((
+ TextBundle::from_section(
+ format!("Item {i}"),
+ TextStyle {
+ font: font.clone(),
+ font_size: 20.,
+ color: Color::WHITE,
+ },
+ ),
+ AccessibilityNode(NodeBuilder::new(bevy::a11y::accesskit::Role::ListItem)),
+ ));
+ }
+ });
+ });
+ });
}
fn update_log_button(
@@ 115,3 185,32 @@ fn update_log() {
// despawn the children ui nodes, and create new ones.
// update log ui scrolling items with... log items
}
+
+#[derive(Component, Default)]
+struct ScrollingList {
+ position: f32,
+}
+
+fn log_mouse_scroll(
+ mut mouse_wheel_events: EventReader<MouseWheel>,
+ mut query_list: Query<(&mut ScrollingList, &mut Style, &Parent, &Node)>,
+ query_node: Query<&Node>,
+) {
+ for mouse_wheel_event in mouse_wheel_events.iter() {
+ for (mut scrolling_list, mut style, parent, list_node) in &mut query_list {
+ let items_height = list_node.size().y;
+ let container_height = query_node.get(parent.get()).unwrap().size().y;
+
+ let max_scroll = (items_height - container_height).max(0.);
+
+ let dy = match mouse_wheel_event.unit {
+ MouseScrollUnit::Line => mouse_wheel_event.y * 20.,
+ MouseScrollUnit::Pixel => mouse_wheel_event.y,
+ };
+
+ scrolling_list.position += dy;
+ scrolling_list.position = scrolling_list.position.clamp(-max_scroll, 0.);
+ style.position.top = Val::Px(scrolling_list.position);
+ }
+ }
+}