bevy/crates/bevy_gilrs/src/lib.rs
Johan Klokkhammer Helsing a1e442cd2a
Add gamepad rumble support to bevy_input (#8398)
# 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>
2023-04-24 15:28:53 +00:00

40 lines
1.2 KiB
Rust

#![allow(clippy::type_complexity)]
mod converter;
mod gilrs_system;
mod rumble;
use bevy_app::{App, Plugin, PostUpdate, PreStartup, PreUpdate};
use bevy_ecs::prelude::*;
use bevy_input::InputSystem;
use bevy_utils::tracing::error;
use gilrs::GilrsBuilder;
use gilrs_system::{gilrs_event_startup_system, gilrs_event_system};
use rumble::{play_gilrs_rumble, RunningRumbleEffects};
#[derive(Default)]
pub struct GilrsPlugin;
/// Updates the running gamepad rumble effects.
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)]
pub struct RumbleSystem;
impl Plugin for GilrsPlugin {
fn build(&self, app: &mut App) {
match GilrsBuilder::new()
.with_default_filters(false)
.set_update_state(false)
.build()
{
Ok(gilrs) => {
app.insert_non_send_resource(gilrs)
.init_non_send_resource::<RunningRumbleEffects>()
.add_systems(PreStartup, gilrs_event_startup_system)
.add_systems(PreUpdate, gilrs_event_system.before(InputSystem))
.add_systems(PostUpdate, play_gilrs_rumble.in_set(RumbleSystem));
}
Err(err) => error!("Failed to start Gilrs. {}", err),
}
}
}