11//! Handle user specified rumble request events.
2- use bevy_ecs:: {
3- prelude:: { EventReader , Res } ,
4- system:: NonSendMut ,
5- } ;
2+ use bevy_ecs:: prelude:: { EventReader , Res } ;
3+ use bevy_ecs:: system:: { ResMut , Resource } ;
64use bevy_input:: gamepad:: { GamepadRumbleIntensity , GamepadRumbleRequest } ;
75use bevy_log:: { debug, warn} ;
86use bevy_time:: Time ;
9- use bevy_utils:: { Duration , HashMap } ;
7+ use bevy_utils:: { synccell :: SyncCell , Duration , HashMap } ;
108use gilrs:: {
119 ff:: { self , BaseEffect , BaseEffectType , Repeat , Replay } ,
12- GamepadId , Gilrs ,
10+ GamepadId ,
1311} ;
1412use thiserror:: Error ;
1513
16- use crate :: converter:: convert_gamepad_id;
14+ use crate :: { converter:: convert_gamepad_id, Gilrs } ;
1715
1816/// A rumble effect that is currently in effect.
1917struct RunningRumble {
20- /// Duration from app startup when this effect will be finished
18+ /// The time (since app startup) when this effect will be finished.
2119 deadline : Duration ,
22- /// A ref-counted handle to the specific force-feedback effect
20+ /// A ref-counted handle to the specific force-feedback effect.
2321 ///
24- /// Dropping it will cause the effect to stop
22+ /// Dropping it will end the effect.
2523 #[ allow( dead_code) ]
26- effect : ff:: Effect ,
24+ effect : SyncCell < ff:: Effect > ,
2725}
2826
2927#[ derive( Error , Debug ) ]
@@ -35,7 +33,7 @@ enum RumbleError {
3533}
3634
3735/// Contains the gilrs rumble effects that are currently running for each gamepad
38- #[ derive( Default ) ]
36+ #[ derive( Resource , Default ) ]
3937pub ( crate ) struct RunningRumbleEffects {
4038 /// If multiple rumbles are running at the same time, their resulting rumble
4139 /// will be the saturated sum of their strengths up until [`u16::MAX`]
@@ -79,8 +77,8 @@ fn get_base_effects(
7977}
8078
8179fn handle_rumble_request (
80+ gilrs : & mut gilrs:: Gilrs ,
8281 running_rumbles : & mut RunningRumbleEffects ,
83- gilrs : & mut Gilrs ,
8482 rumble : GamepadRumbleRequest ,
8583 current_time : Duration ,
8684) -> Result < ( ) , RumbleError > {
@@ -113,17 +111,20 @@ fn handle_rumble_request(
113111
114112 let gamepad_rumbles = running_rumbles. rumbles . entry ( gamepad_id) . or_default ( ) ;
115113 let deadline = current_time + duration;
116- gamepad_rumbles. push ( RunningRumble { deadline, effect } ) ;
114+ gamepad_rumbles. push ( RunningRumble {
115+ deadline,
116+ effect : SyncCell :: new ( effect) ,
117+ } ) ;
117118 }
118119 }
119120
120121 Ok ( ( ) )
121122}
122123pub ( crate ) fn play_gilrs_rumble (
123124 time : Res < Time > ,
124- mut gilrs : NonSendMut < Gilrs > ,
125125 mut requests : EventReader < GamepadRumbleRequest > ,
126- mut running_rumbles : NonSendMut < RunningRumbleEffects > ,
126+ mut gilrs : ResMut < Gilrs > ,
127+ mut running_rumbles : ResMut < RunningRumbleEffects > ,
127128) {
128129 let current_time = time. raw_elapsed ( ) ;
129130 // Remove outdated rumble effects.
@@ -138,7 +139,7 @@ pub(crate) fn play_gilrs_rumble(
138139 // Add new effects.
139140 for rumble in requests. read ( ) . cloned ( ) {
140141 let gamepad = rumble. gamepad ( ) ;
141- match handle_rumble_request ( & mut running_rumbles , & mut gilrs , rumble, current_time) {
142+ match handle_rumble_request ( gilrs . get ( ) , & mut running_rumbles , rumble, current_time) {
142143 Ok ( ( ) ) => { }
143144 Err ( RumbleError :: GilrsError ( err) ) => {
144145 if let ff:: Error :: FfNotSupported ( _) = err {
0 commit comments