From efcc6bab899b29718d039ee08dccde78a2654328 Mon Sep 17 00:00:00 2001 From: irate Date: Sat, 2 Dec 2023 17:10:04 +0100 Subject: [PATCH] Fix mouse input events being read multiple times (#418) * fix * Yeet accidental changes --- src/input_mocking.rs | 28 +++++++++---------- src/input_streams.rs | 65 ++++++++++++++++++++++++++------------------ src/systems.rs | 15 +++++----- 3 files changed, 61 insertions(+), 47 deletions(-) diff --git a/src/input_mocking.rs b/src/input_mocking.rs index 6da037a9..dcb494ad 100644 --- a/src/input_mocking.rs +++ b/src/input_mocking.rs @@ -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, @@ -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 }, }), } @@ -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, @@ -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, @@ -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")] diff --git a/src/input_streams.rs b/src/input_streams.rs index 637a7989..3f934318 100644 --- a/src/input_streams.rs +++ b/src/input_streams.rs @@ -38,9 +38,9 @@ pub struct InputStreams<'a> { /// A [`MouseButton`] [`Input`] stream pub mouse_buttons: Option<&'a Input>, /// A [`MouseWheel`] event stream - pub mouse_wheel: Option<&'a Events>, + pub mouse_wheel: Option>, /// A [`MouseMotion`] event stream - pub mouse_motion: &'a Events, + pub mouse_motion: Vec, /// The [`Gamepad`] that this struct will detect inputs from pub associated_gamepad: Option, } @@ -56,9 +56,20 @@ impl<'a> InputStreams<'a> { let keycodes = world.get_resource::>(); let scan_codes = world.get_resource::>(); let mouse_buttons = world.get_resource::>(); - let mouse_wheel = world.get_resource::>(); + let mouse_wheel = world.resource::>(); let mouse_motion = world.resource::>(); + let mouse_wheel: Vec = mouse_wheel + .get_reader() + .read(mouse_wheel) + .cloned() + .collect(); + let mouse_motion: Vec = mouse_motion + .get_reader() + .read(mouse_motion) + .cloned() + .collect(); + InputStreams { gamepad_buttons, gamepad_button_axes, @@ -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, } @@ -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 => { @@ -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 @@ -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, @@ -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, @@ -496,9 +497,9 @@ pub struct MutableInputStreams<'a> { /// Events used for mocking [`MouseButton`] inputs pub mouse_button_events: &'a mut Events, /// A [`MouseWheel`] event stream - pub mouse_wheel: &'a mut Events, + pub mouse_wheel: Vec, /// A [`MouseMotion`] event stream - pub mouse_motion: &'a mut Events, + pub mouse_motion: Vec, /// The [`Gamepad`] that this struct will detect inputs from pub associated_gamepad: Option, @@ -537,6 +538,18 @@ impl<'a> MutableInputStreams<'a> { mouse_motion, ) = input_system_state.get_mut(world); + let mouse_wheel: Vec = mouse_wheel + .get_reader() + .read(&mouse_wheel) + .cloned() + .collect(); + + let mouse_motion: Vec = mouse_motion + .get_reader() + .read(&mouse_motion) + .cloned() + .collect(); + MutableInputStreams { gamepad_buttons: gamepad_buttons.into_inner(), gamepad_button_axes: gamepad_button_axes.into_inner(), @@ -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, } } @@ -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, } } diff --git a/src/systems.rs b/src/systems.rs index 56f68ea3..d515b112 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -72,8 +72,8 @@ pub fn update_action_state( keycodes: Option>>, scan_codes: Option>>, mouse_buttons: Option>>, - mouse_wheel: Option>>, - mouse_motion: Res>, + mut mouse_wheel: EventReader, + mut mouse_motion: EventReader, clash_strategy: Res, #[cfg(all(feature = "ui", feature = "block_ui_interactions"))] interactions: Query< &Interaction, @@ -95,8 +95,9 @@ pub fn update_action_state( 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 = mouse_wheel.read().cloned().collect(); + let mouse_motion: Vec = 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"))] @@ -106,7 +107,7 @@ pub fn update_action_state( { (None, None) } else { - (mouse_buttons, mouse_wheel) + (mouse_buttons, Some(mouse_wheel)) }; #[cfg(feature = "egui")] @@ -148,8 +149,8 @@ pub fn update_action_state( keycodes, scan_codes, mouse_buttons, - mouse_wheel, - mouse_motion, + mouse_wheel: mouse_wheel.clone(), + mouse_motion: mouse_motion.clone(), associated_gamepad: input_map.gamepad(), };