-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add rumble support to bevy_gilrs #3868
Conversation
Medium => ff::BaseEffectType::Strong { magnitude: 40_000 }, | ||
Weak => ff::BaseEffectType::Weak { magnitude: 40_000 }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This magnitudes shouldn't be the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the gilrs example They use the same magnitude with a different BaseEffectType
(you'll notice here we use Strong
for Medium
and Weak
for Weak
) to demonstrate a periodic change in force feedback intensity. Testing it myself with two different controllers, I find all different RumbleIntensity
to be distinct enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't notice the different Types here. Then everything is fine here
This adds the `RumbleRequest` event and a system to read them and rumble controllers accordingly. It gives users two ways of controlling controller rumble: 1. A very primitive API with `RumbleIntensity` that is easy to understand and use. 2. A direct access to the girls `ff::Effect` system for complete fine-grained control over how the gamepad rumbles.
Notes: Re-export of
|
There is still an open question: how do we want this to play out with mobile rumble? (and by extension, web) It might or might not be wishable to have a unified interface to interact with mobile rumble. Having a unified API means the |
@@ -20,10 +23,13 @@ impl Plugin for GilrsPlugin { | |||
{ | |||
Ok(gilrs) => { | |||
app.insert_non_send_resource(gilrs) | |||
.add_event::<RumbleRequest>() | |||
.init_non_send_resource::<rumble::RumblesManager>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.init_non_send_resource::<rumble::RumblesManager>() | |
.init_non_send_resource::<RumblesManager>() |
This should just be imported.
.add_startup_system_to_stage( | ||
StartupStage::PreStartup, | ||
gilrs_event_startup_system, | ||
) | ||
.add_system_to_stage(CoreStage::PostUpdate, rumble::gilrs_rumble_system) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.add_system_to_stage(CoreStage::PostUpdate, rumble::gilrs_rumble_system) | |
.add_system_to_stage(CoreStage::PostUpdate, gilrs_rumble_system) |
use gilrs::GilrsBuilder; | ||
use gilrs_system::{gilrs_event_startup_system, gilrs_event_system}; | ||
pub use rumble::{RumbleIntensity, RumbleRequest}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub use rumble::{RumbleIntensity, RumbleRequest}; | |
pub use rumble::{gilrs_rumble_system, RumbleIntensity, RumblesManager, RumbleRequest}; |
fn effect_type(&self) -> ff::BaseEffectType { | ||
use RumbleIntensity::*; | ||
match self { | ||
Strong => ff::BaseEffectType::Strong { magnitude: 63_000 }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These values seem super arbitrary and hard-coded.
} | ||
} | ||
|
||
/// Request `pad` rumble in `gilrs_effect` pattern for `duration_seconds` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The phrasing here is a little unclear.
/// # Notes | ||
/// | ||
/// * Does nothing if `pad` does not support rumble | ||
/// * If a new `RumbleRequest` is sent while another one is still executing, it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is always the correct behavior. Could we have an overwriting field perhaps?
} | ||
} | ||
|
||
struct RunningRumble { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs docs; I'm not immediately sure what it does.
.insert(pad_id, RunningRumble { deadline, effect }); | ||
Ok(()) | ||
} | ||
pub(crate) fn gilrs_rumble_system( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub(crate) fn gilrs_rumble_system( | |
pub(crate) fn play_gilrs_rumble( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really want this functionality and this API is a great start.
However, I feel pretty strongly that we should be wrapping this. I want this to work across platforms: vibration is a critical feature for web / console / mobile / VR, and gilrs isn't going to cover those.
.insert(pad_id, RunningRumble { deadline, effect }); | ||
Ok(()) | ||
} | ||
pub(crate) fn gilrs_rumble_system( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this should be pub?
log::debug!("Tried to rumble {pad:?} but an error occurred: {err}") | ||
} | ||
Err(RumbleError::GamepadNotFound) => { | ||
log::error!("Tried to rumble {pad:?} but it doesn't exist!") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
log::error!("Tried to rumble {pad:?} but it doesn't exist!") | |
log::warn!("Tried to rumble {pad:?} but it doesn't exist!") |
@@ -194,6 +194,7 @@ Example | File | Description | |||
`char_input_events` | [`input/char_input_events.rs`](./input/char_input_events.rs) | Prints out all chars as they are inputted. | |||
`gamepad_input` | [`input/gamepad_input.rs`](./input/gamepad_input.rs) | Shows handling of gamepad input, connections, and disconnections | |||
`gamepad_input_events` | [`input/gamepad_input_events.rs`](./input/gamepad_input_events.rs) | Iterates and prints gamepad input and connection events | |||
`gamepad_rumble` | [`input/gamepad_rumble.rs`](./input/gamepad_rumble.rs) | Make a controller rumble |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`gamepad_rumble` | [`input/gamepad_rumble.rs`](./input/gamepad_rumble.rs) | Make a controller rumble | |
`gamepad_rumble` | [`input/gamepad_rumble.rs`](./input/gamepad_rumble.rs) | Makes a controller vibrate for force-feedback purposes |
Keyword stuffing!
@@ -0,0 +1,70 @@ | |||
use bevy::{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a module-style doc comment explaining what the example does.
Hey, I'm considering picking this one up. Anything I should know about @nicopap @alice-i-cecile ? |
@johanhelsing nope. I think everything relevant should be in the diff and comments of this PR. |
I merged main into this branch and got it working again. My branch is here https://github.com/bevyengine/bevy/compare/main...johanhelsing:bevy:rumble?expand=1 I'll create a PR when/if I have something I want feedback on, but that branch is probably a good starting point if I end up abandoning it and someone else wants to pick this up :) |
# Objective Provide the ability to trigger controller rumbling (force-feedback) with a cross-platform API. ## Solution This adds the `GamepadRumbleRequest` event to `bevy_input` and adds a system in `bevy_gilrs` to read them and rumble controllers accordingly. It's a relatively primitive API with a `duration` in seconds and `GamepadRumbleIntensity` with values for the weak and strong gamepad motors. It's is an almost 1-to-1 mapping to platform APIs. Some platforms refer to these motors as left and right, and low frequency and high frequency, but by convention, they're usually the same. I used #3868 as a starting point, updated to main, removed the low-level gilrs effect API, and moved the requests to `bevy_input` and exposed the strong and weak intensities. I intend this to hopefully be a non-controversial cross-platform starting point we can build upon to eventually support more fine-grained control (closer to the gilrs effect API) --- ## Changelog ### Added - Gamepads can now be rumbled by sending the `GamepadRumbleRequest` event. --------- Co-authored-by: Nicola Papale <nico@nicopap.ch> Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com> Co-authored-by: Bruce Reif (Buswolley) <bruce.reif@dynata.com>
This adds the
RumbleRequest
event and a system to read them and rumblecontrollers accordingly.
It gives users two ways of controlling controller rumble:
RumbleIntensity
that is easy tounderstand and use.
ff::Effect
system for completefine-grained control over how the gamepad rumbles.