Skip to content

Commit

Permalink
Add scroll functionality to bevy_picking (#17704)
Browse files Browse the repository at this point in the history
# Objective

`bevy_picking` currently does not support scroll events.

## Solution

This pr adds a new event type for scroll, and updates the default input
system for mouse pointers to read and emit this event.

## Testing

- Did you test these changes? If so, how?
- Are there any parts that need more testing?
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?

I haven't tested these changes, if the reviewers can advise me how to do
so I'd appreciate it!
  • Loading branch information
colepoirier authored Feb 10, 2025
1 parent 2660ddc commit 8435951
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 0 deletions.
37 changes: 37 additions & 0 deletions crates/bevy_picking/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
use core::{fmt::Debug, time::Duration};

use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam, traversal::Traversal};
use bevy_input::mouse::MouseScrollUnit;
use bevy_math::Vec2;
use bevy_platform_support::collections::HashMap;
use bevy_platform_support::time::Instant;
Expand Down Expand Up @@ -285,6 +286,19 @@ pub struct DragEntry {
pub latest_pos: Vec2,
}

/// Fires while a pointer is scrolling over the `target` entity.
#[derive(Clone, PartialEq, Debug, Reflect)]
pub struct Scroll {
/// The mouse scroll unit.
pub unit: MouseScrollUnit,
/// The horizontal scroll value.
pub x: f32,
/// The vertical scroll value.
pub y: f32,
/// Information about the picking intersection.
pub hit: HitData,
}

/// An entry in the cache that drives the `pointer_events` system, storing additional data
/// about pointer button presses.
#[derive(Debug, Clone, Default)]
Expand Down Expand Up @@ -346,6 +360,7 @@ pub struct PickingEventWriters<'w> {
drag_leave_events: EventWriter<'w, Pointer<DragLeave>>,
drag_over_events: EventWriter<'w, Pointer<DragOver>>,
drag_start_events: EventWriter<'w, Pointer<DragStart>>,
scroll_events: EventWriter<'w, Pointer<Scroll>>,
move_events: EventWriter<'w, Pointer<Move>>,
out_events: EventWriter<'w, Pointer<Out>>,
over_events: EventWriter<'w, Pointer<Over>>,
Expand Down Expand Up @@ -750,6 +765,28 @@ pub fn pointer_events(
event_writers.move_events.send(move_event);
}
}
PointerAction::Scroll { x, y, unit } => {
for (hovered_entity, hit) in hover_map
.get(&pointer_id)
.iter()
.flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
{
// Emit Scroll events to the entities we are hovering
let scroll_event = Pointer::new(
pointer_id,
location.clone(),
hovered_entity,
Scroll {
unit,
x,
y,
hit: hit.clone(),
},
);
commands.trigger_targets(scroll_event.clone(), hovered_entity);
event_writers.scroll_events.send(scroll_event);
}
}
// Canceled
PointerAction::Cancel => {
// Emit a Cancel to the hovered entity.
Expand Down
18 changes: 18 additions & 0 deletions crates/bevy_picking/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_input::{
mouse::MouseWheel,
prelude::*,
touch::{TouchInput, TouchPhase},
ButtonState,
Expand Down Expand Up @@ -156,6 +157,23 @@ pub fn mouse_pick_events(
};
pointer_events.send(PointerInput::new(PointerId::Mouse, location, action));
}
WindowEvent::MouseWheel(event) => {
let MouseWheel { unit, x, y, window } = *event;

let location = Location {
target: match RenderTarget::Window(WindowRef::Entity(window))
.normalize(primary_window.get_single().ok())
{
Some(target) => target,
None => continue,
},
position: *cursor_last,
};

let action = PointerAction::Scroll { x, y, unit };

pointer_events.send(PointerInput::new(PointerId::Mouse, location, action));
}
_ => {}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_picking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ impl Plugin for InteractionPlugin {
.add_event::<Pointer<Out>>()
.add_event::<Pointer<Over>>()
.add_event::<Pointer<Released>>()
.add_event::<Pointer<Scroll>>()
.add_systems(
PreUpdate,
(generate_hovermap, update_interactions, pointer_events)
Expand Down
10 changes: 10 additions & 0 deletions crates/bevy_picking/src/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! driven by lower-level input devices and consumed by higher-level interaction systems.
use bevy_ecs::prelude::*;
use bevy_input::mouse::MouseScrollUnit;
use bevy_math::Vec2;
use bevy_platform_support::collections::HashMap;
use bevy_reflect::prelude::*;
Expand Down Expand Up @@ -251,6 +252,15 @@ pub enum PointerAction {
/// How much the pointer moved from the previous position.
delta: Vec2,
},
/// Scroll the pointer
Scroll {
/// The mouse scroll unit.
unit: MouseScrollUnit,
/// The horizontal scroll value.
x: f32,
/// The vertical scroll value.
y: f32,
},
/// Cancel the pointer. Often used for touch events.
Cancel,
}
Expand Down

0 comments on commit 8435951

Please sign in to comment.