Skip to content

Commit

Permalink
Fix mouse input events being read multiple times (#418)
Browse files Browse the repository at this point in the history
* fix

* Yeet accidental changes
  • Loading branch information
tim-blackbird authored Dec 2, 2023
1 parent 1e68d8b commit efcc6ba
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 47 deletions.
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()
.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

0 comments on commit efcc6ba

Please sign in to comment.