mirror of
https://github.com/bevyengine/bevy
synced 2024-11-24 21:53:07 +00:00
Gamepad improvements (#16222)
# Objective Closes #16221. ## Solution - Make `Gamepad` fields public and remove delegates / getters. - Move `impl Into` to `Axis` methods (delegates for `Axis` used `impl Into` to allow passing both `GamepadAxis` and `GamepadButton`). - Improve docs. ## Testing - I run tests. Not sure if the migration guide is needed, since it's a feature from RC, but I wrote it just in case. --- ## Migration Guide - `Gamepad` fields are now public. - Instead of using `Gamepad` delegates like `Gamepad::just_pressed`, call these methods directly on the fields. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
8d24efe60c
commit
b0058dc54b
5 changed files with 69 additions and 237 deletions
|
@ -45,16 +45,16 @@ where
|
||||||
/// If the `input_device`:
|
/// If the `input_device`:
|
||||||
/// - was present before, the position data is updated, and the old value is returned.
|
/// - was present before, the position data is updated, and the old value is returned.
|
||||||
/// - wasn't present before, `None` is returned.
|
/// - wasn't present before, `None` is returned.
|
||||||
pub fn set(&mut self, input_device: T, position_data: f32) -> Option<f32> {
|
pub fn set(&mut self, input_device: impl Into<T>, position_data: f32) -> Option<f32> {
|
||||||
self.axis_data.insert(input_device, position_data)
|
self.axis_data.insert(input_device.into(), position_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the position data of the provided `input_device`.
|
/// Returns the position data of the provided `input_device`.
|
||||||
///
|
///
|
||||||
/// This will be clamped between [`Axis::MIN`] and [`Axis::MAX`] inclusive.
|
/// This will be clamped between [`Axis::MIN`] and [`Axis::MAX`] inclusive.
|
||||||
pub fn get(&self, input_device: T) -> Option<f32> {
|
pub fn get(&self, input_device: impl Into<T>) -> Option<f32> {
|
||||||
self.axis_data
|
self.axis_data
|
||||||
.get(&input_device)
|
.get(&input_device.into())
|
||||||
.copied()
|
.copied()
|
||||||
.map(|value| value.clamp(Self::MIN, Self::MAX))
|
.map(|value| value.clamp(Self::MIN, Self::MAX))
|
||||||
}
|
}
|
||||||
|
@ -66,13 +66,13 @@ where
|
||||||
/// Use for things like camera zoom, where you want devices like mouse wheels to be able to
|
/// Use for things like camera zoom, where you want devices like mouse wheels to be able to
|
||||||
/// exceed the normal range. If being able to move faster on one input device
|
/// exceed the normal range. If being able to move faster on one input device
|
||||||
/// than another would give an unfair advantage, you should likely use [`Axis::get`] instead.
|
/// than another would give an unfair advantage, you should likely use [`Axis::get`] instead.
|
||||||
pub fn get_unclamped(&self, input_device: T) -> Option<f32> {
|
pub fn get_unclamped(&self, input_device: impl Into<T>) -> Option<f32> {
|
||||||
self.axis_data.get(&input_device).copied()
|
self.axis_data.get(&input_device.into()).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the position data of the `input_device`, returning the position data if the input device was previously set.
|
/// Removes the position data of the `input_device`, returning the position data if the input device was previously set.
|
||||||
pub fn remove(&mut self, input_device: T) -> Option<f32> {
|
pub fn remove(&mut self, input_device: impl Into<T>) -> Option<f32> {
|
||||||
self.axis_data.remove(&input_device)
|
self.axis_data.remove(&input_device.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over all axes.
|
/// Returns an iterator over all axes.
|
||||||
|
|
|
@ -306,13 +306,12 @@ pub enum ButtonSettingsError {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The [`Gamepad`] [`component`](Component) stores a connected gamepad's metadata such as the `name` and its [`GamepadButton`] and [`GamepadAxis`].
|
/// Stores a connected gamepad's state and any metadata such as the device name.
|
||||||
///
|
///
|
||||||
/// The [`entity`](Entity) representing a gamepad and its [`minimal components`](GamepadSettings) are automatically managed.
|
/// An entity with this component is spawned automatically after [`GamepadConnectionEvent`]
|
||||||
|
/// and updated by [`gamepad_event_processing_system`].
|
||||||
///
|
///
|
||||||
/// # Usage
|
/// See also [`GamepadSettings`] for configuration.
|
||||||
///
|
|
||||||
/// The only way to obtain a [`Gamepad`] is by [`query`](Query).
|
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -321,14 +320,15 @@ pub enum ButtonSettingsError {
|
||||||
/// # use bevy_ecs::system::Query;
|
/// # use bevy_ecs::system::Query;
|
||||||
/// #
|
/// #
|
||||||
/// fn gamepad_usage_system(gamepads: Query<&Gamepad>) {
|
/// fn gamepad_usage_system(gamepads: Query<&Gamepad>) {
|
||||||
/// for gamepad in gamepads.iter() {
|
/// for gamepad in &gamepads {
|
||||||
/// println!("{}", gamepad.name());
|
/// let name = &gamepad.info.name;
|
||||||
|
/// println!("{name}");
|
||||||
///
|
///
|
||||||
/// if gamepad.just_pressed(GamepadButton::North) {
|
/// if gamepad.digital.just_pressed(GamepadButton::North) {
|
||||||
/// println!("{} just pressed North", gamepad.name())
|
/// println!("{name} just pressed North")
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// if let Some(left_stick_x) = gamepad.get(GamepadAxis::LeftStickX) {
|
/// if let Some(left_stick_x) = gamepad.analog.get(GamepadAxis::LeftStickX) {
|
||||||
/// println!("left stick X: {}", left_stick_x)
|
/// println!("left stick X: {}", left_stick_x)
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
@ -338,22 +338,23 @@ pub enum ButtonSettingsError {
|
||||||
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))]
|
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))]
|
||||||
#[require(GamepadSettings)]
|
#[require(GamepadSettings)]
|
||||||
pub struct Gamepad {
|
pub struct Gamepad {
|
||||||
info: GamepadInfo,
|
/// Metadata.
|
||||||
|
pub info: GamepadInfo,
|
||||||
/// [`ButtonInput`] of [`GamepadButton`] representing their digital state
|
/// [`ButtonInput`] of [`GamepadButton`] representing their digital state
|
||||||
pub(crate) digital: ButtonInput<GamepadButton>,
|
pub digital: ButtonInput<GamepadButton>,
|
||||||
/// [`Axis`] of [`GamepadButton`] representing their analog state.
|
/// [`Axis`] of [`GamepadButton`] representing their analog state.
|
||||||
pub(crate) analog: Axis<GamepadInput>,
|
pub analog: Axis<GamepadInput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gamepad {
|
impl Gamepad {
|
||||||
/// Creates a gamepad with the given metadata.
|
/// Creates a gamepad with the given metadata.
|
||||||
fn new(info: GamepadInfo) -> Self {
|
pub fn new(info: GamepadInfo) -> Self {
|
||||||
let mut analog = Axis::default();
|
let mut analog = Axis::default();
|
||||||
for button in GamepadButton::all().iter().copied() {
|
for button in GamepadButton::all().iter().copied() {
|
||||||
analog.set(button.into(), 0.0);
|
analog.set(button, 0.0);
|
||||||
}
|
}
|
||||||
for axis_type in GamepadAxis::all().iter().copied() {
|
for axis_type in GamepadAxis::all().iter().copied() {
|
||||||
analog.set(axis_type.into(), 0.0);
|
analog.set(axis_type, 0.0);
|
||||||
}
|
}
|
||||||
Self {
|
Self {
|
||||||
info,
|
info,
|
||||||
|
@ -362,168 +363,38 @@ impl Gamepad {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The name of the gamepad.
|
|
||||||
///
|
|
||||||
/// This name is generally defined by the OS.
|
|
||||||
///
|
|
||||||
/// For example on Windows the name may be "HID-compliant game controller".
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
self.info.name.as_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the USB vendor ID as assigned by the USB-IF, if available.
|
|
||||||
pub fn vendor_id(&self) -> Option<u16> {
|
|
||||||
self.info.vendor_id
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the USB product ID as assigned by the [vendor], if available.
|
|
||||||
///
|
|
||||||
/// [vendor]: Self::vendor_id
|
|
||||||
pub fn product_id(&self) -> Option<u16> {
|
|
||||||
self.info.product_id
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the analog data of the provided [`GamepadAxis`] or [`GamepadButton`].
|
|
||||||
///
|
|
||||||
/// This will be clamped between [[`Axis::MIN`],[`Axis::MAX`]].
|
|
||||||
pub fn get(&self, input: impl Into<GamepadInput>) -> Option<f32> {
|
|
||||||
self.analog.get(input.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the unclamped analog data of the provided [`GamepadAxis`] or [`GamepadButton`].
|
|
||||||
///
|
|
||||||
/// This value may be outside the [`Axis::MIN`] and [`Axis::MAX`] range.
|
|
||||||
pub fn get_unclamped(&self, input: impl Into<GamepadInput>) -> Option<f32> {
|
|
||||||
self.analog.get_unclamped(input.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the left stick as a [`Vec2`]
|
/// Returns the left stick as a [`Vec2`]
|
||||||
pub fn left_stick(&self) -> Vec2 {
|
pub fn left_stick(&self) -> Vec2 {
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: self.get(GamepadAxis::LeftStickX).unwrap_or(0.0),
|
x: self.analog.get(GamepadAxis::LeftStickX).unwrap_or(0.0),
|
||||||
y: self.get(GamepadAxis::LeftStickY).unwrap_or(0.0),
|
y: self.analog.get(GamepadAxis::LeftStickY).unwrap_or(0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the right stick as a [`Vec2`]
|
/// Returns the right stick as a [`Vec2`]
|
||||||
pub fn right_stick(&self) -> Vec2 {
|
pub fn right_stick(&self) -> Vec2 {
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: self.get(GamepadAxis::RightStickX).unwrap_or(0.0),
|
x: self.analog.get(GamepadAxis::RightStickX).unwrap_or(0.0),
|
||||||
y: self.get(GamepadAxis::RightStickY).unwrap_or(0.0),
|
y: self.analog.get(GamepadAxis::RightStickY).unwrap_or(0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the directional pad as a [`Vec2`]
|
/// Returns the directional pad as a [`Vec2`]
|
||||||
pub fn dpad(&self) -> Vec2 {
|
pub fn dpad(&self) -> Vec2 {
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: self.get(GamepadButton::DPadRight).unwrap_or(0.0)
|
x: self.analog.get(GamepadButton::DPadRight).unwrap_or(0.0)
|
||||||
- self.get(GamepadButton::DPadLeft).unwrap_or(0.0),
|
- self.analog.get(GamepadButton::DPadLeft).unwrap_or(0.0),
|
||||||
y: self.get(GamepadButton::DPadUp).unwrap_or(0.0)
|
y: self.analog.get(GamepadButton::DPadUp).unwrap_or(0.0)
|
||||||
- self.get(GamepadButton::DPadDown).unwrap_or(0.0),
|
- self.analog.get(GamepadButton::DPadDown).unwrap_or(0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the [`GamepadButton`] has been pressed.
|
|
||||||
pub fn pressed(&self, button_type: GamepadButton) -> bool {
|
|
||||||
self.digital.pressed(button_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if any item in [`GamepadButton`] has been pressed.
|
|
||||||
pub fn any_pressed(&self, button_inputs: impl IntoIterator<Item = GamepadButton>) -> bool {
|
|
||||||
button_inputs
|
|
||||||
.into_iter()
|
|
||||||
.any(|button_type| self.pressed(button_type))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if all items in [`GamepadButton`] have been pressed.
|
|
||||||
pub fn all_pressed(&self, button_inputs: impl IntoIterator<Item = GamepadButton>) -> bool {
|
|
||||||
button_inputs
|
|
||||||
.into_iter()
|
|
||||||
.all(|button_type| self.pressed(button_type))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the [`GamepadButton`] has been pressed during the current frame.
|
|
||||||
///
|
|
||||||
/// Note: This function does not imply information regarding the current state of [`ButtonInput::pressed`] or [`ButtonInput::just_released`].
|
|
||||||
pub fn just_pressed(&self, button_type: GamepadButton) -> bool {
|
|
||||||
self.digital.just_pressed(button_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if any item in [`GamepadButton`] has been pressed during the current frame.
|
|
||||||
pub fn any_just_pressed(&self, button_inputs: impl IntoIterator<Item = GamepadButton>) -> bool {
|
|
||||||
button_inputs
|
|
||||||
.into_iter()
|
|
||||||
.any(|button_type| self.just_pressed(button_type))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if all items in [`GamepadButton`] have been just pressed.
|
|
||||||
pub fn all_just_pressed(&self, button_inputs: impl IntoIterator<Item = GamepadButton>) -> bool {
|
|
||||||
button_inputs
|
|
||||||
.into_iter()
|
|
||||||
.all(|button_type| self.just_pressed(button_type))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the [`GamepadButton`] has been released during the current frame.
|
|
||||||
///
|
|
||||||
/// Note: This function does not imply information regarding the current state of [`ButtonInput::pressed`] or [`ButtonInput::just_pressed`].
|
|
||||||
pub fn just_released(&self, button_type: GamepadButton) -> bool {
|
|
||||||
self.digital.just_released(button_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if any item in [`GamepadButton`] has just been released.
|
|
||||||
pub fn any_just_released(
|
|
||||||
&self,
|
|
||||||
button_inputs: impl IntoIterator<Item = GamepadButton>,
|
|
||||||
) -> bool {
|
|
||||||
button_inputs
|
|
||||||
.into_iter()
|
|
||||||
.any(|button_type| self.just_released(button_type))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if all items in [`GamepadButton`] have just been released.
|
|
||||||
pub fn all_just_released(
|
|
||||||
&self,
|
|
||||||
button_inputs: impl IntoIterator<Item = GamepadButton>,
|
|
||||||
) -> bool {
|
|
||||||
button_inputs
|
|
||||||
.into_iter()
|
|
||||||
.all(|button_type| self.just_released(button_type))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator over all digital [button]s that are pressed.
|
|
||||||
///
|
|
||||||
/// [button]: GamepadButton
|
|
||||||
pub fn get_pressed(&self) -> impl Iterator<Item = &GamepadButton> {
|
|
||||||
self.digital.get_pressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator over all digital [button]s that were just pressed.
|
|
||||||
///
|
|
||||||
/// [button]: GamepadButton
|
|
||||||
pub fn get_just_pressed(&self) -> impl Iterator<Item = &GamepadButton> {
|
|
||||||
self.digital.get_just_pressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator over all digital [button]s that were just released.
|
|
||||||
///
|
|
||||||
/// [button]: GamepadButton
|
|
||||||
pub fn get_just_released(&self) -> impl Iterator<Item = &GamepadButton> {
|
|
||||||
self.digital.get_just_released()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an iterator over all analog [axes].
|
|
||||||
///
|
|
||||||
/// [axes]: GamepadInput
|
|
||||||
pub fn get_analog_axes(&self) -> impl Iterator<Item = &GamepadInput> {
|
|
||||||
self.analog.all_axes()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that we don't expose `gilrs::Gamepad::uuid` due to
|
// Note that we don't expose `gilrs::Gamepad::uuid` due to
|
||||||
// https://gitlab.com/gilrs-project/gilrs/-/issues/153.
|
// https://gitlab.com/gilrs-project/gilrs/-/issues/153.
|
||||||
//
|
//
|
||||||
/// Metadata associated with a [`Gamepad`].
|
/// Metadata associated with a [`Gamepad`].
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
|
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
|
@ -1426,12 +1297,12 @@ pub fn gamepad_event_processing_system(
|
||||||
};
|
};
|
||||||
let Some(filtered_value) = gamepad_settings
|
let Some(filtered_value) = gamepad_settings
|
||||||
.get_axis_settings(axis)
|
.get_axis_settings(axis)
|
||||||
.filter(value, gamepad_axis.get(axis))
|
.filter(value, gamepad_axis.analog.get(axis))
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
gamepad_axis.analog.set(axis.into(), filtered_value);
|
gamepad_axis.analog.set(axis, filtered_value);
|
||||||
let send_event = GamepadAxisChangedEvent::new(gamepad, axis, filtered_value);
|
let send_event = GamepadAxisChangedEvent::new(gamepad, axis, filtered_value);
|
||||||
processed_axis_events.send(send_event);
|
processed_axis_events.send(send_event);
|
||||||
processed_events.send(GamepadEvent::from(send_event));
|
processed_events.send(GamepadEvent::from(send_event));
|
||||||
|
@ -1447,16 +1318,16 @@ pub fn gamepad_event_processing_system(
|
||||||
};
|
};
|
||||||
let Some(filtered_value) = settings
|
let Some(filtered_value) = settings
|
||||||
.get_button_axis_settings(button)
|
.get_button_axis_settings(button)
|
||||||
.filter(value, gamepad_buttons.get(button))
|
.filter(value, gamepad_buttons.analog.get(button))
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let button_settings = settings.get_button_settings(button);
|
let button_settings = settings.get_button_settings(button);
|
||||||
gamepad_buttons.analog.set(button.into(), filtered_value);
|
gamepad_buttons.analog.set(button, filtered_value);
|
||||||
|
|
||||||
if button_settings.is_released(filtered_value) {
|
if button_settings.is_released(filtered_value) {
|
||||||
// Check if button was previously pressed
|
// Check if button was previously pressed
|
||||||
if gamepad_buttons.pressed(button) {
|
if gamepad_buttons.digital.pressed(button) {
|
||||||
processed_digital_events.send(GamepadButtonStateChangedEvent::new(
|
processed_digital_events.send(GamepadButtonStateChangedEvent::new(
|
||||||
gamepad,
|
gamepad,
|
||||||
button,
|
button,
|
||||||
|
@ -1468,7 +1339,7 @@ pub fn gamepad_event_processing_system(
|
||||||
gamepad_buttons.digital.release(button);
|
gamepad_buttons.digital.release(button);
|
||||||
} else if button_settings.is_pressed(filtered_value) {
|
} else if button_settings.is_pressed(filtered_value) {
|
||||||
// Check if button was previously not pressed
|
// Check if button was previously not pressed
|
||||||
if !gamepad_buttons.pressed(button) {
|
if !gamepad_buttons.digital.pressed(button) {
|
||||||
processed_digital_events.send(GamepadButtonStateChangedEvent::new(
|
processed_digital_events.send(GamepadButtonStateChangedEvent::new(
|
||||||
gamepad,
|
gamepad,
|
||||||
button,
|
button,
|
||||||
|
@ -2000,11 +1871,7 @@ mod tests {
|
||||||
.resource_mut::<Events<GamepadConnectionEvent>>()
|
.resource_mut::<Events<GamepadConnectionEvent>>()
|
||||||
.send(GamepadConnectionEvent::new(
|
.send(GamepadConnectionEvent::new(
|
||||||
gamepad,
|
gamepad,
|
||||||
Connected(GamepadInfo {
|
Connected(GamepadInfo::default()),
|
||||||
name: String::from("Gamepad test"),
|
|
||||||
vendor_id: None,
|
|
||||||
product_id: None,
|
|
||||||
}),
|
|
||||||
));
|
));
|
||||||
gamepad
|
gamepad
|
||||||
}
|
}
|
||||||
|
@ -2522,13 +2389,8 @@ mod tests {
|
||||||
assert_eq!(event.button, GamepadButton::DPadDown);
|
assert_eq!(event.button, GamepadButton::DPadDown);
|
||||||
assert_eq!(event.state, ButtonState::Pressed);
|
assert_eq!(event.state, ButtonState::Pressed);
|
||||||
}
|
}
|
||||||
assert!(ctx
|
let gamepad = ctx.app.world_mut().get::<Gamepad>(entity).unwrap();
|
||||||
.app
|
assert!(gamepad.digital.pressed(GamepadButton::DPadDown));
|
||||||
.world_mut()
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.get(ctx.app.world(), entity)
|
|
||||||
.unwrap()
|
|
||||||
.pressed(GamepadButton::DPadDown));
|
|
||||||
|
|
||||||
ctx.app
|
ctx.app
|
||||||
.world_mut()
|
.world_mut()
|
||||||
|
@ -2543,13 +2405,8 @@ mod tests {
|
||||||
.len(),
|
.len(),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
assert!(ctx
|
let gamepad = ctx.app.world_mut().get::<Gamepad>(entity).unwrap();
|
||||||
.app
|
assert!(gamepad.digital.pressed(GamepadButton::DPadDown));
|
||||||
.world_mut()
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.get(ctx.app.world(), entity)
|
|
||||||
.unwrap()
|
|
||||||
.pressed(GamepadButton::DPadDown));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2568,23 +2425,13 @@ mod tests {
|
||||||
ctx.update();
|
ctx.update();
|
||||||
|
|
||||||
// Check it is flagged for this frame
|
// Check it is flagged for this frame
|
||||||
assert!(ctx
|
let gamepad = ctx.app.world_mut().get::<Gamepad>(entity).unwrap();
|
||||||
.app
|
assert!(gamepad.digital.just_pressed(GamepadButton::DPadDown));
|
||||||
.world_mut()
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.get(ctx.app.world(), entity)
|
|
||||||
.unwrap()
|
|
||||||
.just_pressed(GamepadButton::DPadDown));
|
|
||||||
ctx.update();
|
ctx.update();
|
||||||
|
|
||||||
//Check it clears next frame
|
//Check it clears next frame
|
||||||
assert!(!ctx
|
let gamepad = ctx.app.world_mut().get::<Gamepad>(entity).unwrap();
|
||||||
.app
|
assert!(!gamepad.digital.just_pressed(GamepadButton::DPadDown));
|
||||||
.world_mut()
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.get(ctx.app.world(), entity)
|
|
||||||
.unwrap()
|
|
||||||
.just_pressed(GamepadButton::DPadDown));
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn gamepad_buttons_released() {
|
fn gamepad_buttons_released() {
|
||||||
|
@ -2627,13 +2474,8 @@ mod tests {
|
||||||
assert_eq!(event.button, GamepadButton::DPadDown);
|
assert_eq!(event.button, GamepadButton::DPadDown);
|
||||||
assert_eq!(event.state, ButtonState::Released);
|
assert_eq!(event.state, ButtonState::Released);
|
||||||
}
|
}
|
||||||
assert!(!ctx
|
let gamepad = ctx.app.world_mut().get::<Gamepad>(entity).unwrap();
|
||||||
.app
|
assert!(!gamepad.digital.pressed(GamepadButton::DPadDown));
|
||||||
.world_mut()
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.get(ctx.app.world(), entity)
|
|
||||||
.unwrap()
|
|
||||||
.pressed(GamepadButton::DPadDown));
|
|
||||||
ctx.app
|
ctx.app
|
||||||
.world_mut()
|
.world_mut()
|
||||||
.resource_mut::<Events<GamepadButtonStateChangedEvent>>()
|
.resource_mut::<Events<GamepadButtonStateChangedEvent>>()
|
||||||
|
@ -2672,23 +2514,13 @@ mod tests {
|
||||||
ctx.update();
|
ctx.update();
|
||||||
|
|
||||||
// Check it is flagged for this frame
|
// Check it is flagged for this frame
|
||||||
assert!(ctx
|
let gamepad = ctx.app.world_mut().get::<Gamepad>(entity).unwrap();
|
||||||
.app
|
assert!(gamepad.digital.just_released(GamepadButton::DPadDown));
|
||||||
.world_mut()
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.get(ctx.app.world(), entity)
|
|
||||||
.unwrap()
|
|
||||||
.just_released(GamepadButton::DPadDown));
|
|
||||||
ctx.update();
|
ctx.update();
|
||||||
|
|
||||||
//Check it clears next frame
|
// Check it clears next frame
|
||||||
assert!(!ctx
|
let gamepad = ctx.app.world_mut().get::<Gamepad>(entity).unwrap();
|
||||||
.app
|
assert!(!gamepad.digital.just_released(GamepadButton::DPadDown));
|
||||||
.world_mut()
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.get(ctx.app.world(), entity)
|
|
||||||
.unwrap()
|
|
||||||
.just_released(GamepadButton::DPadDown));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -11,18 +11,18 @@ fn main() {
|
||||||
|
|
||||||
fn gamepad_system(gamepads: Query<(Entity, &Gamepad)>) {
|
fn gamepad_system(gamepads: Query<(Entity, &Gamepad)>) {
|
||||||
for (entity, gamepad) in &gamepads {
|
for (entity, gamepad) in &gamepads {
|
||||||
if gamepad.just_pressed(GamepadButton::South) {
|
if gamepad.digital.just_pressed(GamepadButton::South) {
|
||||||
info!("{:?} just pressed South", entity);
|
info!("{:?} just pressed South", entity);
|
||||||
} else if gamepad.just_released(GamepadButton::South) {
|
} else if gamepad.digital.just_released(GamepadButton::South) {
|
||||||
info!("{:?} just released South", entity);
|
info!("{:?} just released South", entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
let right_trigger = gamepad.get(GamepadButton::RightTrigger2).unwrap();
|
let right_trigger = gamepad.analog.get(GamepadButton::RightTrigger2).unwrap();
|
||||||
if right_trigger.abs() > 0.01 {
|
if right_trigger.abs() > 0.01 {
|
||||||
info!("{:?} RightTrigger2 value is {}", entity, right_trigger);
|
info!("{:?} RightTrigger2 value is {}", entity, right_trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
let left_stick_x = gamepad.get(GamepadAxis::LeftStickX).unwrap();
|
let left_stick_x = gamepad.analog.get(GamepadAxis::LeftStickX).unwrap();
|
||||||
if left_stick_x.abs() > 0.01 {
|
if left_stick_x.abs() > 0.01 {
|
||||||
info!("{:?} LeftStickX value is {}", entity, left_stick_x);
|
info!("{:?} LeftStickX value is {}", entity, left_stick_x);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ fn gamepad_system(
|
||||||
mut rumble_requests: EventWriter<GamepadRumbleRequest>,
|
mut rumble_requests: EventWriter<GamepadRumbleRequest>,
|
||||||
) {
|
) {
|
||||||
for (entity, gamepad) in &gamepads {
|
for (entity, gamepad) in &gamepads {
|
||||||
if gamepad.just_pressed(GamepadButton::North) {
|
if gamepad.digital.just_pressed(GamepadButton::North) {
|
||||||
info!(
|
info!(
|
||||||
"North face button: strong (low-frequency) with low intensity for rumble for 5 seconds. Press multiple times to increase intensity."
|
"North face button: strong (low-frequency) with low intensity for rumble for 5 seconds. Press multiple times to increase intensity."
|
||||||
);
|
);
|
||||||
|
@ -30,7 +30,7 @@ fn gamepad_system(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if gamepad.just_pressed(GamepadButton::East) {
|
if gamepad.digital.just_pressed(GamepadButton::East) {
|
||||||
info!("East face button: maximum rumble on both motors for 5 seconds");
|
info!("East face button: maximum rumble on both motors for 5 seconds");
|
||||||
rumble_requests.send(GamepadRumbleRequest::Add {
|
rumble_requests.send(GamepadRumbleRequest::Add {
|
||||||
gamepad: entity,
|
gamepad: entity,
|
||||||
|
@ -39,7 +39,7 @@ fn gamepad_system(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if gamepad.just_pressed(GamepadButton::South) {
|
if gamepad.digital.just_pressed(GamepadButton::South) {
|
||||||
info!("South face button: low-intensity rumble on the weak motor for 0.5 seconds");
|
info!("South face button: low-intensity rumble on the weak motor for 0.5 seconds");
|
||||||
rumble_requests.send(GamepadRumbleRequest::Add {
|
rumble_requests.send(GamepadRumbleRequest::Add {
|
||||||
gamepad: entity,
|
gamepad: entity,
|
||||||
|
@ -48,7 +48,7 @@ fn gamepad_system(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if gamepad.just_pressed(GamepadButton::West) {
|
if gamepad.digital.just_pressed(GamepadButton::West) {
|
||||||
info!("West face button: custom rumble intensity for 5 second");
|
info!("West face button: custom rumble intensity for 5 second");
|
||||||
rumble_requests.send(GamepadRumbleRequest::Add {
|
rumble_requests.send(GamepadRumbleRequest::Add {
|
||||||
gamepad: entity,
|
gamepad: entity,
|
||||||
|
@ -62,7 +62,7 @@ fn gamepad_system(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if gamepad.just_pressed(GamepadButton::Start) {
|
if gamepad.digital.just_pressed(GamepadButton::Start) {
|
||||||
info!("Start button: Interrupt the current rumble");
|
info!("Start button: Interrupt the current rumble");
|
||||||
rumble_requests.send(GamepadRumbleRequest::Stop { gamepad: entity });
|
rumble_requests.send(GamepadRumbleRequest::Stop { gamepad: entity });
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,12 +393,12 @@ fn update_buttons(
|
||||||
materials: Res<ButtonMaterials>,
|
materials: Res<ButtonMaterials>,
|
||||||
mut query: Query<(&mut MeshMaterial2d<ColorMaterial>, &ReactTo)>,
|
mut query: Query<(&mut MeshMaterial2d<ColorMaterial>, &ReactTo)>,
|
||||||
) {
|
) {
|
||||||
for buttons in &gamepads {
|
for gamepad in &gamepads {
|
||||||
for (mut handle, react_to) in query.iter_mut() {
|
for (mut handle, react_to) in query.iter_mut() {
|
||||||
if buttons.just_pressed(**react_to) {
|
if gamepad.digital.just_pressed(**react_to) {
|
||||||
*handle = materials.active.clone();
|
*handle = materials.active.clone();
|
||||||
}
|
}
|
||||||
if buttons.just_released(**react_to) {
|
if gamepad.digital.just_released(**react_to) {
|
||||||
*handle = materials.normal.clone();
|
*handle = materials.normal.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ fn update_connected(
|
||||||
|
|
||||||
let formatted = gamepads
|
let formatted = gamepads
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(entity, gamepad)| format!("{} - {}", entity, gamepad.name()))
|
.map(|(entity, gamepad)| format!("{} - {}", entity, gamepad.info.name))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue