Skip to content

Make Gilrs a normal resource on non-Wasm targets #12092

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

Merged
merged 9 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions crates/bevy_gilrs/src/gilrs_system.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
use crate::converter::{convert_axis, convert_button, convert_gamepad_id};
use crate::{
converter::{convert_axis, convert_button, convert_gamepad_id},
Gilrs,
};
use bevy_ecs::event::EventWriter;
use bevy_ecs::system::{NonSend, NonSendMut, Res, ResMut};
#[cfg(target_arch = "wasm32")]
use bevy_ecs::system::NonSendMut;
use bevy_ecs::system::{Res, ResMut};
use bevy_input::gamepad::{
GamepadAxisChangedEvent, GamepadButtonChangedEvent, GamepadConnection, GamepadConnectionEvent,
GamepadSettings,
};
use bevy_input::gamepad::{GamepadEvent, GamepadInfo};
use bevy_input::prelude::{GamepadAxis, GamepadButton};
use bevy_input::Axis;
use gilrs::{ev::filter::axis_dpad_to_button, EventType, Filter, Gilrs};
use gilrs::{ev::filter::axis_dpad_to_button, EventType, Filter};

pub fn gilrs_event_startup_system(
gilrs: NonSend<Gilrs>,
#[cfg(target_arch = "wasm32")] mut gilrs: NonSendMut<Gilrs>,
#[cfg(not(target_arch = "wasm32"))] mut gilrs: ResMut<Gilrs>,
mut connection_events: EventWriter<GamepadConnectionEvent>,
) {
for (id, gamepad) in gilrs.gamepads() {
for (id, gamepad) in gilrs.0.get().gamepads() {
let info = GamepadInfo {
name: gamepad.name().into(),
};
Expand All @@ -27,16 +33,15 @@ pub fn gilrs_event_startup_system(
}

pub fn gilrs_event_system(
mut gilrs: NonSendMut<Gilrs>,
#[cfg(target_arch = "wasm32")] mut gilrs: NonSendMut<Gilrs>,
#[cfg(not(target_arch = "wasm32"))] mut gilrs: ResMut<Gilrs>,
mut events: EventWriter<GamepadEvent>,
mut gamepad_buttons: ResMut<Axis<GamepadButton>>,
gamepad_axis: Res<Axis<GamepadAxis>>,
gamepad_settings: Res<GamepadSettings>,
) {
while let Some(gilrs_event) = gilrs
.next_event()
.filter_ev(&axis_dpad_to_button, &mut gilrs)
{
let gilrs = gilrs.0.get();
while let Some(gilrs_event) = gilrs.next_event().filter_ev(&axis_dpad_to_button, gilrs) {
gilrs.update(&gilrs_event);

let gamepad = convert_gamepad_id(gilrs_event.id);
Expand Down
13 changes: 10 additions & 3 deletions crates/bevy_gilrs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ mod rumble;
use bevy_app::{App, Plugin, PostUpdate, PreStartup, PreUpdate};
use bevy_ecs::prelude::*;
use bevy_input::InputSystem;
use bevy_utils::tracing::error;
use bevy_utils::{synccell::SyncCell, tracing::error};
use gilrs::GilrsBuilder;
use gilrs_system::{gilrs_event_startup_system, gilrs_event_system};
use rumble::{play_gilrs_rumble, RunningRumbleEffects};

#[cfg_attr(not(target_arch = "wasm32"), derive(Resource))]
pub(crate) struct Gilrs(pub SyncCell<gilrs::Gilrs>);

/// Plugin that provides gamepad handling to an [`App`].
#[derive(Default)]
pub struct GilrsPlugin;
Expand All @@ -31,8 +34,12 @@ impl Plugin for GilrsPlugin {
.build()
{
Ok(gilrs) => {
app.insert_non_send_resource(gilrs)
.init_non_send_resource::<RunningRumbleEffects>()
#[cfg(target_arch = "wasm32")]
app.insert_non_send_resource(Gilrs(SyncCell::new(gilrs)));
#[cfg(not(target_arch = "wasm32"))]
app.insert_resource(Gilrs(SyncCell::new(gilrs)));

app.init_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));
Expand Down
31 changes: 18 additions & 13 deletions crates/bevy_gilrs/src/rumble.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
//! Handle user specified rumble request events.
use bevy_ecs::{
prelude::{EventReader, Res},
system::NonSendMut,
};
use crate::Gilrs;
use bevy_ecs::prelude::{EventReader, Res, ResMut, Resource};
#[cfg(target_arch = "wasm32")]
use bevy_ecs::system::NonSendMut;
use bevy_input::gamepad::{GamepadRumbleIntensity, GamepadRumbleRequest};
use bevy_log::{debug, warn};
use bevy_time::{Real, Time};
use bevy_utils::{Duration, HashMap};
use bevy_utils::{synccell::SyncCell, Duration, HashMap};
use gilrs::{
ff::{self, BaseEffect, BaseEffectType, Repeat, Replay},
GamepadId, Gilrs,
GamepadId,
};
use thiserror::Error;

Expand All @@ -23,7 +23,7 @@ struct RunningRumble {
///
/// Dropping it will cause the effect to stop
#[allow(dead_code)]
effect: ff::Effect,
effect: SyncCell<ff::Effect>,
}

#[derive(Error, Debug)]
Expand All @@ -35,7 +35,7 @@ enum RumbleError {
}

/// Contains the gilrs rumble effects that are currently running for each gamepad
#[derive(Default)]
#[derive(Default, Resource)]
pub(crate) struct RunningRumbleEffects {
/// If multiple rumbles are running at the same time, their resulting rumble
/// will be the saturated sum of their strengths up until [`u16::MAX`]
Expand Down Expand Up @@ -80,7 +80,7 @@ fn get_base_effects(

fn handle_rumble_request(
running_rumbles: &mut RunningRumbleEffects,
gilrs: &mut Gilrs,
gilrs: &mut gilrs::Gilrs,
rumble: GamepadRumbleRequest,
current_time: Duration,
) -> Result<(), RumbleError> {
Expand Down Expand Up @@ -113,18 +113,23 @@ fn handle_rumble_request(

let gamepad_rumbles = running_rumbles.rumbles.entry(gamepad_id).or_default();
let deadline = current_time + duration;
gamepad_rumbles.push(RunningRumble { deadline, effect });
gamepad_rumbles.push(RunningRumble {
deadline,
effect: SyncCell::new(effect),
});
}
}

Ok(())
}
pub(crate) fn play_gilrs_rumble(
time: Res<Time<Real>>,
mut gilrs: NonSendMut<Gilrs>,
#[cfg(target_arch = "wasm32")] mut gilrs: NonSendMut<Gilrs>,
#[cfg(not(target_arch = "wasm32"))] mut gilrs: ResMut<Gilrs>,
mut requests: EventReader<GamepadRumbleRequest>,
mut running_rumbles: NonSendMut<RunningRumbleEffects>,
mut running_rumbles: ResMut<RunningRumbleEffects>,
) {
let gilrs = gilrs.0.get();
let current_time = time.elapsed();
// Remove outdated rumble effects.
for rumbles in running_rumbles.rumbles.values_mut() {
Expand All @@ -138,7 +143,7 @@ pub(crate) fn play_gilrs_rumble(
// Add new effects.
for rumble in requests.read().cloned() {
let gamepad = rumble.gamepad();
match handle_rumble_request(&mut running_rumbles, &mut gilrs, rumble, current_time) {
match handle_rumble_request(&mut running_rumbles, gilrs, rumble, current_time) {
Ok(()) => {}
Err(RumbleError::GilrsError(err)) => {
if let ff::Error::FfNotSupported(_) = err {
Expand Down