Skip to content

Commit

Permalink
yoten
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-blackbird committed Dec 2, 2023
1 parent 1e68d8b commit 6006907
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 153 deletions.
80 changes: 15 additions & 65 deletions src/input_mocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,14 @@ use bevy::ecs::world::World;
#[cfg(feature = "ui")]
use bevy::ecs::{component::Component, query::With, system::Query};
use bevy::input::gamepad::{GamepadAxisChangedEvent, GamepadButtonChangedEvent};
use bevy::input::mouse::MouseScrollUnit;
use bevy::input::ButtonState;
use bevy::input::{
gamepad::{Gamepad, GamepadButton, GamepadEvent},
keyboard::{KeyCode, KeyboardInput},
mouse::{MouseButton, MouseButtonInput, MouseMotion, MouseWheel},
mouse::{MouseButton, MouseButtonInput, MouseWheel},
touch::{TouchInput, Touches},
Input,
};
use bevy::math::Vec2;
use bevy::prelude::Entity;
#[cfg(feature = "ui")]
use bevy::ui::Interaction;
Expand Down Expand Up @@ -175,48 +173,20 @@ 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 {
unit: MouseScrollUnit::Pixel,
x: -1.0,
y: 0.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelDirection::Right => self.mouse_wheel.send(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: 1.0,
y: 0.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelDirection::Up => self.mouse_wheel.send(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: 0.0,
y: 1.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelDirection::Down => self.mouse_wheel.send(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: 0.0,
y: -1.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelDirection::Left => self.mouse_wheel.x -= 1.,
MouseWheelDirection::Right => self.mouse_wheel.x += 1.,
MouseWheelDirection::Up => self.mouse_wheel.y += 1.,
MouseWheelDirection::Down => self.mouse_wheel.y -= 1.,
}
}

// Discrete mouse motion event
for mouse_motion_direction in raw_inputs.mouse_motion {
match mouse_motion_direction {
MouseMotionDirection::Up => self.mouse_motion.send(MouseMotion {
delta: Vec2 { x: 0.0, y: 1.0 },
}),
MouseMotionDirection::Down => self.mouse_motion.send(MouseMotion {
delta: Vec2 { x: 0.0, y: -1.0 },
}),
MouseMotionDirection::Right => self.mouse_motion.send(MouseMotion {
delta: Vec2 { x: 1.0, y: 0.0 },
}),
MouseMotionDirection::Left => self.mouse_motion.send(MouseMotion {
delta: Vec2 { x: -1.0, y: 0.0 },
}),
MouseMotionDirection::Left => self.mouse_motion.x -= 1.,
MouseMotionDirection::Right => self.mouse_motion.x += 1.,
MouseMotionDirection::Up => self.mouse_motion.y += 1.,
MouseMotionDirection::Down => self.mouse_motion.y -= 1.,
}
}

Expand Down Expand Up @@ -249,33 +219,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 {
unit: MouseScrollUnit::Pixel,
x: position_data,
y: 0.0,
window: Entity::PLACEHOLDER,
}),
MouseWheelAxisType::Y => self.mouse_wheel.send(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: 0.0,
y: position_data,
window: Entity::PLACEHOLDER,
}),
MouseWheelAxisType::X => self.mouse_wheel.x += position_data,
MouseWheelAxisType::Y => self.mouse_wheel.y += position_data,
}
}
AxisType::MouseMotion(axis_type) => match axis_type {
MouseMotionAxisType::X => self.mouse_motion.send(MouseMotion {
delta: Vec2 {
x: position_data,
y: 0.0,
},
}),
MouseMotionAxisType::Y => self.mouse_motion.send(MouseMotion {
delta: Vec2 {
x: 0.0,
y: position_data,
},
}),
MouseMotionAxisType::X => self.mouse_motion.x += position_data,
MouseMotionAxisType::Y => self.mouse_motion.y += position_data,
},
}
}
Expand Down Expand Up @@ -341,8 +291,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
145 changes: 63 additions & 82 deletions src/input_streams.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Unified input streams for working with [`bevy::input`] data.

use bevy::ecs::prelude::{Events, ResMut, World};
use bevy::ecs::system::SystemState;
use bevy::input::{
gamepad::{Gamepad, GamepadAxis, GamepadButton, GamepadEvent, Gamepads},
Expand All @@ -9,6 +8,10 @@ use bevy::input::{
Axis, Input,
};
use bevy::utils::HashSet;
use bevy::{
ecs::prelude::{Events, ResMut, World},
math::Vec2,
};

use crate::axislike::{
AxisType, DualAxisData, MouseMotionAxisType, MouseWheelAxisType, SingleAxis, VirtualAxis,
Expand Down Expand Up @@ -37,10 +40,10 @@ pub struct InputStreams<'a> {
pub scan_codes: Option<&'a Input<ScanCode>>,
/// A [`MouseButton`] [`Input`] stream
pub mouse_buttons: Option<&'a Input<MouseButton>>,
/// A [`MouseWheel`] event stream
pub mouse_wheel: Option<&'a Events<MouseWheel>>,
/// A [`MouseMotion`] event stream
pub mouse_motion: &'a Events<MouseMotion>,
/// A [`MouseWheel`] delta
pub mouse_wheel: Option<Vec2>,
/// A [`MouseMotion`] delta
pub mouse_motion: Vec2,
/// The [`Gamepad`] that this struct will detect inputs from
pub associated_gamepad: Option<Gamepad>,
}
Expand All @@ -59,6 +62,20 @@ impl<'a> InputStreams<'a> {
let mouse_wheel = world.get_resource::<Events<MouseWheel>>();
let mouse_motion = world.resource::<Events<MouseMotion>>();

let mouse_wheel: Option<Vec2> = mouse_wheel.map(|events| {
events
.get_reader()
.read(events)
.map(|event| Vec2::new(event.x, event.y))
.sum()
});

let mouse_motion: Vec2 = mouse_motion
.get_reader()
.read(mouse_motion)
.map(|event| event.delta)
.sum();

InputStreams {
gamepad_buttons,
gamepad_button_axes,
Expand Down Expand Up @@ -168,60 +185,20 @@ impl<'a> InputStreams<'a> {
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) {
total_mouse_wheel_movement += match mouse_wheel_direction {
MouseWheelDirection::Up | MouseWheelDirection::Down => mouse_wheel_event.y,
MouseWheelDirection::Left | MouseWheelDirection::Right => {
mouse_wheel_event.x
}
}
}

match mouse_wheel_direction {
MouseWheelDirection::Up | MouseWheelDirection::Right => {
total_mouse_wheel_movement > 0.0
}
MouseWheelDirection::Down | MouseWheelDirection::Left => {
total_mouse_wheel_movement < 0.0
}
MouseWheelDirection::Up => mouse_wheel.y > 0.0,
MouseWheelDirection::Right => mouse_wheel.x > 0.0,
MouseWheelDirection::Down => mouse_wheel.y < 0.0,
MouseWheelDirection::Left => mouse_wheel.x < 0.0,
}
}
// CLEANUP: refactor to share code with MouseWheel
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) {
total_mouse_movement += match mouse_motion_direction {
MouseMotionDirection::Up | MouseMotionDirection::Down => {
mouse_motion_event.delta.y
}
MouseMotionDirection::Left | MouseMotionDirection::Right => {
mouse_motion_event.delta.x
}
}
}

match mouse_motion_direction {
MouseMotionDirection::Up | MouseMotionDirection::Right => {
total_mouse_movement > 0.0
}
MouseMotionDirection::Down | MouseMotionDirection::Left => {
total_mouse_movement < 0.0
}
}
}
InputKind::MouseMotion(mouse_motion_direction) => match mouse_motion_direction {
MouseMotionDirection::Up => self.mouse_motion.y > 0.0,
MouseMotionDirection::Right => self.mouse_motion.x > 0.0,
MouseMotionDirection::Down => self.mouse_motion.y < 0.0,
MouseMotionDirection::Left => self.mouse_motion.x < 0.0,
},
}
}

Expand Down Expand Up @@ -304,32 +281,24 @@ impl<'a> InputStreams<'a> {
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) {
total_mouse_wheel_movement += match axis_type {
MouseWheelAxisType::X => mouse_wheel_event.x,
MouseWheelAxisType::Y => mouse_wheel_event.y,
match axis_type {
MouseWheelAxisType::X => {
value_in_axis_range(single_axis, mouse_wheel.x)
}
MouseWheelAxisType::Y => {
value_in_axis_range(single_axis, mouse_wheel.y)
}
}
value_in_axis_range(single_axis, total_mouse_wheel_movement)
}
// 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) {
total_mouse_motion_movement += match axis_type {
MouseMotionAxisType::X => mouse_wheel_event.delta.x,
MouseMotionAxisType::Y => mouse_wheel_event.delta.y,
}
AxisType::MouseMotion(axis_type) => match axis_type {
MouseMotionAxisType::X => {
value_in_axis_range(single_axis, self.mouse_motion.x)
}
value_in_axis_range(single_axis, total_mouse_motion_movement)
}
MouseMotionAxisType::Y => {
value_in_axis_range(single_axis, self.mouse_motion.y)
}
},
}
}
UserInput::VirtualAxis(VirtualAxis { negative, positive }) => {
Expand Down Expand Up @@ -495,10 +464,10 @@ pub struct MutableInputStreams<'a> {
pub mouse_buttons: &'a mut Input<MouseButton>,
/// 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>,
/// A [`MouseMotion`] event stream
pub mouse_motion: &'a mut Events<MouseMotion>,
/// A [`MouseWheel`] delta
pub mouse_wheel: Vec2,
/// A [`MouseMotion`] delta
pub mouse_motion: Vec2,

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

let mouse_wheel: Vec2 = mouse_wheel
.get_reader()
.read(&mouse_wheel)
.map(|event| Vec2::new(event.x, event.y))
.sum();

let mouse_motion: Vec2 = mouse_motion
.get_reader()
.read(&mouse_motion)
.map(|event| event.delta)
.sum();

MutableInputStreams {
gamepad_buttons: gamepad_buttons.into_inner(),
gamepad_button_axes: gamepad_button_axes.into_inner(),
Expand All @@ -548,8 +529,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
17 changes: 11 additions & 6 deletions src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use crate::{
};

use bevy::time::Time;
use bevy::utils::Instant;
use bevy::{ecs::prelude::*, prelude::ScanCode};
use bevy::{
input::{
Expand All @@ -24,6 +23,7 @@ use bevy::{
},
time::Real,
};
use bevy::{math::Vec2, utils::Instant};

#[cfg(feature = "ui")]
use bevy::ui::Interaction;
Expand Down 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,13 @@ 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: Vec2 = mouse_wheel
.read()
.map(|event| Vec2::new(event.x, event.y))
.sum();

let mouse_motion: Vec2 = mouse_motion.read().map(|event| event.delta).sum();

// 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 +111,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

0 comments on commit 6006907

Please sign in to comment.