Skip to content

Commit

Permalink
Fix Leafwing-Studios#269: chords with a dual axis should properly rep…
Browse files Browse the repository at this point in the history
…ort it
  • Loading branch information
michalmoc committed Jun 6, 2023
1 parent 4cb89d2 commit a49d7f6
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 14 deletions.
42 changes: 28 additions & 14 deletions src/input_streams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::axislike::{
VirtualDPad,
};
use crate::buttonlike::{MouseMotionDirection, MouseWheelDirection};
use crate::prelude::DualAxis;
use crate::user_input::{InputKind, UserInput};

/// A collection of [`Input`] structs, which can be used to update an [`InputMap`](crate::input_map::InputMap).
Expand Down Expand Up @@ -343,29 +344,27 @@ impl<'a> InputStreams<'a> {

/// Get the axis pair associated to the user input.
///
/// If `input` is a chord, returns result of the first dual axis on the lis.
/// If `input` is not a [`DualAxis`](crate::axislike::DualAxis) or [`VirtualDPad`], returns [`None`].
///
/// See [`ActionState::action_axis_pair()`](crate::action_state::ActionState) for usage.
///
/// # Warning
///
/// If you need to ensure that this value is always in the range `[-1., 1.]`,
/// be sure to clamp the returned data.
pub fn input_axis_pair(&self, input: &UserInput) -> Option<DualAxisData> {
match input {
UserInput::Chord(inputs) => inputs
.iter()
.flat_map(|input_kind| {
if let InputKind::DualAxis(dual_axis) = input_kind {
Some(self.extract_dual_axis_data(dual_axis))
} else {
None
}
})
.next(),
UserInput::Single(InputKind::DualAxis(dual_axis)) => {
let x = self.input_value(&UserInput::Single(InputKind::SingleAxis(dual_axis.x)));
let y = self.input_value(&UserInput::Single(InputKind::SingleAxis(dual_axis.y)));

if x > dual_axis.x.positive_low
|| x < dual_axis.x.negative_low
|| y > dual_axis.y.positive_low
|| y < dual_axis.y.negative_low
{
Some(DualAxisData::new(x, y))
} else {
Some(DualAxisData::new(0.0, 0.0))
}
Some(self.extract_dual_axis_data(dual_axis))
}
UserInput::VirtualDPad(VirtualDPad {
up,
Expand All @@ -382,6 +381,21 @@ impl<'a> InputStreams<'a> {
_ => None,
}
}

fn extract_dual_axis_data(&self, dual_axis: &DualAxis) -> DualAxisData {
let x = self.input_value(&UserInput::Single(InputKind::SingleAxis(dual_axis.x)));
let y = self.input_value(&UserInput::Single(InputKind::SingleAxis(dual_axis.y)));

if x > dual_axis.x.positive_low
|| x < dual_axis.x.negative_low
|| y > dual_axis.y.positive_low
|| y < dual_axis.y.negative_low
{
DualAxisData::new(x, y)
} else {
DualAxisData::new(0.0, 0.0)
}
}
}

/// A mutable collection of [`Input`] structs, which can be used for mocking user inputs.
Expand Down
35 changes: 35 additions & 0 deletions tests/mouse_motion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use bevy::prelude::*;
use leafwing_input_manager::axislike::{AxisType, DualAxisData, MouseMotionAxisType};
use leafwing_input_manager::buttonlike::MouseMotionDirection;
use leafwing_input_manager::prelude::*;
use leafwing_input_manager::user_input::InputKind;

#[derive(Actionlike, Clone, Copy, Debug)]
enum ButtonlikeTestAction {
Expand Down Expand Up @@ -287,3 +288,37 @@ fn mouse_motion_virtualdpad() {
DualAxisData::new(0.0, -1.0)
);
}

#[test]
fn mouse_drag() {
let mut app = test_app();

let mut input_map = InputMap::default();

input_map.insert_chord(
[
InputKind::from(DualAxis::mouse_motion()),
InputKind::from(MouseButton::Right),
],
AxislikeTestAction::XY,
);

app.insert_resource(input_map);

app.send_input(DualAxis::from_value(
MouseMotionAxisType::X,
MouseMotionAxisType::Y,
5.0,
0.0,
));
app.send_input(MouseButton::Right);
app.update();

let action_state = app.world.resource::<ActionState<AxislikeTestAction>>();

assert!(action_state.pressed(AxislikeTestAction::XY));
assert_eq!(
action_state.axis_pair(AxislikeTestAction::XY),
Some(DualAxisData::new(5.0, 0.0))
);
}

0 comments on commit a49d7f6

Please sign in to comment.