Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mouse input events being read multiple times #418

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions src/input_mocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,25 +175,25 @@ impl MockInput for MutableInputStreams<'_> {
// Discrete mouse wheel events
for mouse_wheel_direction in raw_inputs.mouse_wheel {
match mouse_wheel_direction {
MouseWheelDirection::Left => self.mouse_wheel.send(MouseWheel {
MouseWheelDirection::Left => self.mouse_wheel.push(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: -1.0,
y: 0.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelDirection::Right => self.mouse_wheel.send(MouseWheel {
MouseWheelDirection::Right => self.mouse_wheel.push(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: 1.0,
y: 0.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelDirection::Up => self.mouse_wheel.send(MouseWheel {
MouseWheelDirection::Up => self.mouse_wheel.push(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: 0.0,
y: 1.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelDirection::Down => self.mouse_wheel.send(MouseWheel {
MouseWheelDirection::Down => self.mouse_wheel.push(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: 0.0,
y: -1.0,
Expand All @@ -205,16 +205,16 @@ impl MockInput for MutableInputStreams<'_> {
// Discrete mouse motion event
for mouse_motion_direction in raw_inputs.mouse_motion {
match mouse_motion_direction {
MouseMotionDirection::Up => self.mouse_motion.send(MouseMotion {
MouseMotionDirection::Up => self.mouse_motion.push(MouseMotion {
delta: Vec2 { x: 0.0, y: 1.0 },
}),
MouseMotionDirection::Down => self.mouse_motion.send(MouseMotion {
MouseMotionDirection::Down => self.mouse_motion.push(MouseMotion {
delta: Vec2 { x: 0.0, y: -1.0 },
}),
MouseMotionDirection::Right => self.mouse_motion.send(MouseMotion {
MouseMotionDirection::Right => self.mouse_motion.push(MouseMotion {
delta: Vec2 { x: 1.0, y: 0.0 },
}),
MouseMotionDirection::Left => self.mouse_motion.send(MouseMotion {
MouseMotionDirection::Left => self.mouse_motion.push(MouseMotion {
delta: Vec2 { x: -1.0, y: 0.0 },
}),
}
Expand Down Expand Up @@ -249,13 +249,13 @@ impl MockInput for MutableInputStreams<'_> {
AxisType::MouseWheel(axis_type) => {
match axis_type {
// FIXME: MouseScrollUnit is not recorded and is always assumed to be Pixel
MouseWheelAxisType::X => self.mouse_wheel.send(MouseWheel {
MouseWheelAxisType::X => self.mouse_wheel.push(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: position_data,
y: 0.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelAxisType::Y => self.mouse_wheel.send(MouseWheel {
MouseWheelAxisType::Y => self.mouse_wheel.push(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: 0.0,
y: position_data,
Expand All @@ -264,13 +264,13 @@ impl MockInput for MutableInputStreams<'_> {
}
}
AxisType::MouseMotion(axis_type) => match axis_type {
MouseMotionAxisType::X => self.mouse_motion.send(MouseMotion {
MouseMotionAxisType::X => self.mouse_motion.push(MouseMotion {
delta: Vec2 {
x: position_data,
y: 0.0,
},
}),
MouseMotionAxisType::Y => self.mouse_motion.send(MouseMotion {
MouseMotionAxisType::Y => self.mouse_motion.push(MouseMotion {
delta: Vec2 {
x: 0.0,
y: position_data,
Expand Down Expand Up @@ -341,8 +341,8 @@ impl MockInput for MutableInputStreams<'_> {
*self.gamepad_axes = Default::default();
*self.keycodes = Default::default();
*self.mouse_buttons = Default::default();
*self.mouse_wheel = Default::default();
*self.mouse_motion = Default::default();
self.mouse_wheel = Default::default();
self.mouse_motion = Default::default();
}

#[cfg(feature = "ui")]
Expand Down
65 changes: 39 additions & 26 deletions src/input_streams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ pub struct InputStreams<'a> {
/// A [`MouseButton`] [`Input`] stream
pub mouse_buttons: Option<&'a Input<MouseButton>>,
/// A [`MouseWheel`] event stream
pub mouse_wheel: Option<&'a Events<MouseWheel>>,
pub mouse_wheel: Option<Vec<MouseWheel>>,
/// A [`MouseMotion`] event stream
pub mouse_motion: &'a Events<MouseMotion>,
pub mouse_motion: Vec<MouseMotion>,
/// The [`Gamepad`] that this struct will detect inputs from
pub associated_gamepad: Option<Gamepad>,
}
Expand All @@ -56,9 +56,20 @@ impl<'a> InputStreams<'a> {
let keycodes = world.get_resource::<Input<KeyCode>>();
let scan_codes = world.get_resource::<Input<ScanCode>>();
let mouse_buttons = world.get_resource::<Input<MouseButton>>();
let mouse_wheel = world.get_resource::<Events<MouseWheel>>();
let mouse_wheel = world.resource::<Events<MouseWheel>>();
let mouse_motion = world.resource::<Events<MouseMotion>>();

let mouse_wheel: Vec<MouseWheel> = mouse_wheel
.get_reader()
Comment on lines +62 to +63
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no way to correctly read the events from here.
Same thing for the from_world method on MutableInputStreams .

.read(mouse_wheel)
.cloned()
.collect();
let mouse_motion: Vec<MouseMotion> = mouse_motion
.get_reader()
.read(mouse_motion)
.cloned()
.collect();

InputStreams {
gamepad_buttons,
gamepad_button_axes,
Expand All @@ -67,7 +78,7 @@ impl<'a> InputStreams<'a> {
keycodes,
scan_codes,
mouse_buttons,
mouse_wheel,
mouse_wheel: Some(mouse_wheel),
mouse_motion,
associated_gamepad: gamepad,
}
Expand Down Expand Up @@ -165,19 +176,16 @@ impl<'a> InputStreams<'a> {
matches!(self.mouse_buttons, Some(mouse_buttons) if mouse_buttons.pressed(mouse_button))
}
InputKind::MouseWheel(mouse_wheel_direction) => {
let Some(mouse_wheel) = self.mouse_wheel else {
let Some(mouse_wheel) = &self.mouse_wheel else {
return false;
};

let mut total_mouse_wheel_movement = 0.0;

// FIXME: verify that this works and doesn't double count events
let mut event_reader = mouse_wheel.get_reader();

// PERF: this summing is computed for every individual input
// This should probably be computed once, and then cached / read
// Fix upstream!
for mouse_wheel_event in event_reader.read(mouse_wheel) {
for mouse_wheel_event in mouse_wheel {
total_mouse_wheel_movement += match mouse_wheel_direction {
MouseWheelDirection::Up | MouseWheelDirection::Down => mouse_wheel_event.y,
MouseWheelDirection::Left | MouseWheelDirection::Right => {
Expand All @@ -199,10 +207,7 @@ impl<'a> InputStreams<'a> {
InputKind::MouseMotion(mouse_motion_direction) => {
let mut total_mouse_movement = 0.0;

// FIXME: verify that this works and doesn't double count events
let mut event_reader = self.mouse_motion.get_reader();

for mouse_motion_event in event_reader.read(self.mouse_motion) {
for mouse_motion_event in &self.mouse_motion {
total_mouse_movement += match mouse_motion_direction {
MouseMotionDirection::Up | MouseMotionDirection::Down => {
mouse_motion_event.delta.y
Expand Down Expand Up @@ -300,15 +305,13 @@ impl<'a> InputStreams<'a> {
}
}
AxisType::MouseWheel(axis_type) => {
let Some(mouse_wheel) = self.mouse_wheel else {
let Some(mouse_wheel) = &self.mouse_wheel else {
return 0.0;
};

let mut total_mouse_wheel_movement = 0.0;
// FIXME: verify that this works and doesn't double count events
let mut event_reader = mouse_wheel.get_reader();

for mouse_wheel_event in event_reader.read(mouse_wheel) {
for mouse_wheel_event in mouse_wheel {
total_mouse_wheel_movement += match axis_type {
MouseWheelAxisType::X => mouse_wheel_event.x,
MouseWheelAxisType::Y => mouse_wheel_event.y,
Expand All @@ -319,10 +322,8 @@ impl<'a> InputStreams<'a> {
// CLEANUP: deduplicate code with MouseWheel
AxisType::MouseMotion(axis_type) => {
let mut total_mouse_motion_movement = 0.0;
// FIXME: verify that this works and doesn't double count events
let mut event_reader = self.mouse_motion.get_reader();

for mouse_wheel_event in event_reader.read(self.mouse_motion) {
for mouse_wheel_event in &self.mouse_motion {
total_mouse_motion_movement += match axis_type {
MouseMotionAxisType::X => mouse_wheel_event.delta.x,
MouseMotionAxisType::Y => mouse_wheel_event.delta.y,
Expand Down Expand Up @@ -496,9 +497,9 @@ pub struct MutableInputStreams<'a> {
/// Events used for mocking [`MouseButton`] inputs
pub mouse_button_events: &'a mut Events<MouseButtonInput>,
/// A [`MouseWheel`] event stream
pub mouse_wheel: &'a mut Events<MouseWheel>,
pub mouse_wheel: Vec<MouseWheel>,
/// A [`MouseMotion`] event stream
pub mouse_motion: &'a mut Events<MouseMotion>,
pub mouse_motion: Vec<MouseMotion>,

/// The [`Gamepad`] that this struct will detect inputs from
pub associated_gamepad: Option<Gamepad>,
Expand Down Expand Up @@ -537,6 +538,18 @@ impl<'a> MutableInputStreams<'a> {
mouse_motion,
) = input_system_state.get_mut(world);

let mouse_wheel: Vec<MouseWheel> = mouse_wheel
.get_reader()
.read(&mouse_wheel)
.cloned()
.collect();

let mouse_motion: Vec<MouseMotion> = mouse_motion
.get_reader()
.read(&mouse_motion)
.cloned()
.collect();

MutableInputStreams {
gamepad_buttons: gamepad_buttons.into_inner(),
gamepad_button_axes: gamepad_button_axes.into_inner(),
Expand All @@ -548,8 +561,8 @@ impl<'a> MutableInputStreams<'a> {
keyboard_events: keyboard_events.into_inner(),
mouse_buttons: mouse_buttons.into_inner(),
mouse_button_events: mouse_button_events.into_inner(),
mouse_wheel: mouse_wheel.into_inner(),
mouse_motion: mouse_motion.into_inner(),
mouse_wheel,
mouse_motion,
associated_gamepad: gamepad,
}
}
Expand Down Expand Up @@ -593,8 +606,8 @@ impl<'a> From<&'a MutableInputStreams<'a>> for InputStreams<'a> {
keycodes: Some(mutable_streams.keycodes),
scan_codes: Some(mutable_streams.scan_codes),
mouse_buttons: Some(mutable_streams.mouse_buttons),
mouse_wheel: Some(mutable_streams.mouse_wheel),
mouse_motion: mutable_streams.mouse_motion,
mouse_wheel: Some(mutable_streams.mouse_wheel.clone()),
mouse_motion: mutable_streams.mouse_motion.clone(),
associated_gamepad: mutable_streams.associated_gamepad,
}
}
Expand Down
15 changes: 8 additions & 7 deletions src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ pub fn update_action_state<A: Actionlike>(
keycodes: Option<Res<Input<KeyCode>>>,
scan_codes: Option<Res<Input<ScanCode>>>,
mouse_buttons: Option<Res<Input<MouseButton>>>,
mouse_wheel: Option<Res<Events<MouseWheel>>>,
mouse_motion: Res<Events<MouseMotion>>,
mut mouse_wheel: EventReader<MouseWheel>,
mut mouse_motion: EventReader<MouseMotion>,
clash_strategy: Res<ClashStrategy>,
#[cfg(all(feature = "ui", feature = "block_ui_interactions"))] interactions: Query<
&Interaction,
Expand All @@ -95,8 +95,9 @@ pub fn update_action_state<A: Actionlike>(
let keycodes = keycodes.map(|keycodes| keycodes.into_inner());
let scan_codes = scan_codes.map(|scan_codes| scan_codes.into_inner());
let mouse_buttons = mouse_buttons.map(|mouse_buttons| mouse_buttons.into_inner());
let mouse_wheel = mouse_wheel.map(|mouse_wheel| mouse_wheel.into_inner());
let mouse_motion = mouse_motion.into_inner();

let mouse_wheel: Vec<MouseWheel> = mouse_wheel.read().cloned().collect();
let mouse_motion: Vec<MouseMotion> = mouse_motion.read().cloned().collect();

// If use clicks on a button, do not apply them to the game state
#[cfg(all(feature = "ui", feature = "block_ui_interactions"))]
Expand All @@ -106,7 +107,7 @@ pub fn update_action_state<A: Actionlike>(
{
(None, None)
} else {
(mouse_buttons, mouse_wheel)
(mouse_buttons, Some(mouse_wheel))
};

#[cfg(feature = "egui")]
Expand Down Expand Up @@ -148,8 +149,8 @@ pub fn update_action_state<A: Actionlike>(
keycodes,
scan_codes,
mouse_buttons,
mouse_wheel,
mouse_motion,
mouse_wheel: mouse_wheel.clone(),
mouse_motion: mouse_motion.clone(),
associated_gamepad: input_map.gamepad(),
};

Expand Down
Loading