(&mut self, index: usize, low_frequency: f32, high_frequency: f32)
| 150 | } |
| 151 | |
| 152 | fn consume_output_requests<S: GamepadSink>(&mut self, app: &mut S) { |
| 153 | for req in app.take_gamepad_rumble_requests() { |
| 154 | self.apply_rumble( |
| 155 | req.index, |
| 156 | req.rumble.low_frequency, |
| 157 | req.rumble.high_frequency, |
| 158 | ); |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | fn apply_rumble(&mut self, index: usize, low_frequency: f32, high_frequency: f32) { |
| 163 | let low = low_frequency.clamp(0.0, 1.0); |
| 164 | let high = high_frequency.clamp(0.0, 1.0); |
| 165 | |
| 166 | if low <= f32::EPSILON && high <= f32::EPSILON { |
| 167 | self.stop_rumble(index); |
| 168 | return; |
| 169 | } |
| 170 | |
| 171 | let Some(id) = self.find_gamepad_id_by_index(index) else { |
| 172 | return; |
| 173 | }; |
| 174 | self.stop_rumble(index); |
| 175 | |
| 176 | let Some(gilrs) = self.gilrs.as_mut() else { |
| 177 | return; |
| 178 | }; |
| 179 | let gp = gilrs.gamepad(id); |
| 180 | if !gp.is_connected() || !gp.is_ff_supported() { |
| 181 | return; |
| 182 | } |
| 183 | |
| 184 | let duration = Ticks::from_ms(RUMBLE_PLAY_FOR_MS); |
| 185 | let weak = magnitude_from_unit(low); |
| 186 | let strong = magnitude_from_unit(high); |
| 187 | let mut builder = EffectBuilder::new(); |
| 188 | if strong > 0 { |
| 189 | builder.add_effect(BaseEffect { |
| 190 | kind: BaseEffectType::Strong { magnitude: strong }, |
| 191 | scheduling: Replay { |
| 192 | play_for: duration, |
| 193 | ..Default::default() |
| 194 | }, |
| 195 | ..Default::default() |
| 196 | }); |
| 197 | } |
| 198 | if weak > 0 { |
| 199 | builder.add_effect(BaseEffect { |
| 200 | kind: BaseEffectType::Weak { magnitude: weak }, |
| 201 | scheduling: Replay { |
| 202 | play_for: duration, |
| 203 | ..Default::default() |
| 204 | }, |
| 205 | ..Default::default() |
| 206 | }); |
no test coverage detected