Skip to content

Commit

Permalink
Add Inversion to SingleAxis, DualAxis, and VirtualDPad (#362)
Browse files Browse the repository at this point in the history
* feat: add axis inversion

* feat: VirtualDPad::inverted()

* fix(inversion): clear clippy lints

* docs(inversion): clarify DualAxis inversion

Co-authored-by: Alice Cecile <[email protected]>

* docs(inversion): add changelog entry

---------

Co-authored-by: Alice Cecile <[email protected]>
  • Loading branch information
SignalWalker and alice-i-cecile authored Jul 2, 2023
1 parent 58429ff commit 76076be
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- Changed `entity` field of `ActionStateDriver` to `targets: ActionStateDriverTarget` with variants for 0, 1, or multiple targets, to allow for one driver
to update multiple entities if needed.
- Added builder-style functions to `SingleAxis`, `DualAxis`, and `VirtualDPad` that invert their output values, allowing, for example, binding inverted camera controls.

### Docs

Expand Down
65 changes: 65 additions & 0 deletions src/axislike.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub struct SingleAxis {
pub positive_low: f32,
/// Any axis value lower than this will trigger the input.
pub negative_low: f32,
/// Whether to invert output values from this axis.
pub inverted: bool,
/// The target value for this input, used for input mocking.
///
/// WARNING: this field is ignored for the sake of [`Eq`] and [`Hash`](std::hash::Hash)
Expand All @@ -42,6 +44,7 @@ impl SingleAxis {
axis_type: axis_type.into(),
positive_low: threshold,
negative_low: -threshold,
inverted: false,
value: None,
}
}
Expand All @@ -56,6 +59,7 @@ impl SingleAxis {
axis_type: axis_type.into(),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
value: Some(value),
}
}
Expand All @@ -67,6 +71,7 @@ impl SingleAxis {
axis_type: AxisType::MouseWheel(MouseWheelAxisType::X),
positive_low: 0.,
negative_low: 0.,
inverted: false,
value: None,
}
}
Expand All @@ -78,6 +83,7 @@ impl SingleAxis {
axis_type: AxisType::MouseWheel(MouseWheelAxisType::Y),
positive_low: 0.,
negative_low: 0.,
inverted: false,
value: None,
}
}
Expand All @@ -89,6 +95,7 @@ impl SingleAxis {
axis_type: AxisType::MouseMotion(MouseMotionAxisType::X),
positive_low: 0.,
negative_low: 0.,
inverted: false,
value: None,
}
}
Expand All @@ -100,6 +107,7 @@ impl SingleAxis {
axis_type: AxisType::MouseMotion(MouseMotionAxisType::Y),
positive_low: 0.,
negative_low: 0.,
inverted: false,
value: None,
}
}
Expand All @@ -112,6 +120,7 @@ impl SingleAxis {
axis_type: axis_type.into(),
negative_low: threshold,
positive_low: f32::MAX,
inverted: false,
value: None,
}
}
Expand All @@ -124,6 +133,7 @@ impl SingleAxis {
axis_type: axis_type.into(),
negative_low: f32::MIN,
positive_low: threshold,
inverted: false,
value: None,
}
}
Expand All @@ -135,6 +145,13 @@ impl SingleAxis {
self.positive_low = deadzone;
self
}

/// Returns this [`SingleAxis`] inverted.
#[must_use]
pub fn inverted(mut self) -> Self {
self.inverted = !self.inverted;
self
}
}

impl PartialEq for SingleAxis {
Expand Down Expand Up @@ -250,6 +267,28 @@ impl DualAxis {
self.y = self.y.with_deadzone(deadzone);
self
}

/// Returns this [`DualAxis`] with an inverted X-axis.
#[must_use]
pub fn inverted_x(mut self) -> DualAxis {
self.x = self.x.inverted();
self
}

/// Returns this [`DualAxis`] with an inverted Y-axis.
#[must_use]
pub fn inverted_y(mut self) -> DualAxis {
self.y = self.y.inverted();
self
}

/// Returns this [`DualAxis`] with both axes inverted.
#[must_use]
pub fn inverted(mut self) -> DualAxis {
self.x = self.x.inverted();
self.y = self.y.inverted();
self
}
}

#[allow(clippy::doc_markdown)] // False alarm because it thinks DPad is an un-quoted item
Expand Down Expand Up @@ -339,6 +378,25 @@ impl VirtualDPad {
right: InputKind::MouseMotion(MouseMotionDirection::Right),
}
}

/// Returns this [`VirtualDPad`] but with `up` and `down` swapped.
pub fn inverted_y(mut self) -> Self {
std::mem::swap(&mut self.up, &mut self.down);
self
}

/// Returns this [`VirtualDPad`] but with `left` and `right` swapped.
pub fn inverted_x(mut self) -> Self {
std::mem::swap(&mut self.left, &mut self.right);
self
}

/// Returns this [`VirtualDPad`] but with inverted inputs.
pub fn inverted(mut self) -> Self {
std::mem::swap(&mut self.up, &mut self.down);
std::mem::swap(&mut self.left, &mut self.right);
self
}
}

/// A virtual Axis that you can get a value between -1 and 1 from.
Expand Down Expand Up @@ -405,6 +463,13 @@ impl VirtualAxis {
positive: InputKind::GamepadButton(GamepadButtonType::DPadUp),
}
}

/// Returns this [`VirtualAxis`] but with flipped positive/negative inputs.
#[must_use]
pub fn inverted(mut self) -> Self {
std::mem::swap(&mut self.positive, &mut self.negative);
self
}
}

/// The type of axis used by a [`UserInput`](crate::user_input::UserInput).
Expand Down
2 changes: 2 additions & 0 deletions src/input_streams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ impl<'a> InputStreams<'a> {
let value_in_axis_range = |axis: &SingleAxis, value: f32| -> f32 {
if value >= axis.negative_low && value <= axis.positive_low {
0.0
} else if axis.inverted {
-value
} else {
value
}
Expand Down
9 changes: 9 additions & 0 deletions tests/gamepad_axis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ fn game_pad_single_axis_mocking() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};

app.send_input(input);
Expand All @@ -98,12 +99,14 @@ fn game_pad_dual_axis_mocking() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
},
y: SingleAxis {
axis_type: AxisType::Gamepad(GamepadAxisType::LeftStickY),
value: Some(0.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
},
};
app.send_input(input);
Expand Down Expand Up @@ -132,6 +135,7 @@ fn game_pad_single_axis() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -144,6 +148,7 @@ fn game_pad_single_axis() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -156,6 +161,7 @@ fn game_pad_single_axis() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -168,6 +174,7 @@ fn game_pad_single_axis() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -181,6 +188,7 @@ fn game_pad_single_axis() {
// Usually a small deadzone threshold will be set
positive_low: 0.1,
negative_low: 0.1,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -193,6 +201,7 @@ fn game_pad_single_axis() {
value: None,
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand Down
9 changes: 9 additions & 0 deletions tests/mouse_motion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ fn mouse_motion_single_axis_mocking() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};

app.send_input(input);
Expand All @@ -93,12 +94,14 @@ fn mouse_motion_dual_axis_mocking() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
},
y: SingleAxis {
axis_type: AxisType::MouseMotion(MouseMotionAxisType::Y),
value: Some(0.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
},
};
app.send_input(input);
Expand Down Expand Up @@ -166,6 +169,7 @@ fn mouse_motion_single_axis() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -178,6 +182,7 @@ fn mouse_motion_single_axis() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -190,6 +195,7 @@ fn mouse_motion_single_axis() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -202,6 +208,7 @@ fn mouse_motion_single_axis() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -215,6 +222,7 @@ fn mouse_motion_single_axis() {
// Usually a small deadzone threshold will be set
positive_low: 0.1,
negative_low: 0.1,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -227,6 +235,7 @@ fn mouse_motion_single_axis() {
value: None,
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand Down
9 changes: 9 additions & 0 deletions tests/mouse_wheel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ fn mouse_wheel_single_axis_mocking() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};

app.send_input(input);
Expand All @@ -93,12 +94,14 @@ fn mouse_wheel_dual_axis_mocking() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
},
y: SingleAxis {
axis_type: AxisType::MouseWheel(MouseWheelAxisType::Y),
value: Some(0.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
},
};
app.send_input(input);
Expand Down Expand Up @@ -166,6 +169,7 @@ fn mouse_wheel_single_axis() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -178,6 +182,7 @@ fn mouse_wheel_single_axis() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -190,6 +195,7 @@ fn mouse_wheel_single_axis() {
value: Some(1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -202,6 +208,7 @@ fn mouse_wheel_single_axis() {
value: Some(-1.),
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -215,6 +222,7 @@ fn mouse_wheel_single_axis() {
// Usually a small deadzone threshold will be set
positive_low: 0.1,
negative_low: 0.1,
inverted: false,
};
app.send_input(input);
app.update();
Expand All @@ -227,6 +235,7 @@ fn mouse_wheel_single_axis() {
value: None,
positive_low: 0.0,
negative_low: 0.0,
inverted: false,
};
app.send_input(input);
app.update();
Expand Down

0 comments on commit 76076be

Please sign in to comment.