1use crate::ev::{Axis, AxisOrBtn, Button, Code, Event, EventType};
77use crate::gamepad::{Gamepad, Gilrs};
78use crate::utils;
79
80use std::time::Duration;
81
82#[derive(Copy, Clone, PartialEq, Debug)]
84pub struct Jitter {
85 pub threshold: f32,
86}
87
88impl Jitter {
89 pub fn new() -> Self {
91 Jitter { threshold: 0.01 }
92 }
93}
94
95impl Default for Jitter {
96 fn default() -> Self {
97 Self::new()
98 }
99}
100
101impl FilterFn for Jitter {
102 fn filter(&self, ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
103 match ev {
104 Some(Event {
105 event: EventType::AxisChanged(_, val, axis),
106 id,
107 ..
108 }) => match gilrs.gamepad(id).state().axis_data(axis) {
109 Some(data) if val != 0.0 && (val - data.value()).abs() < self.threshold => {
110 Some(Event::new(id, EventType::Dropped))
111 }
112 _ => ev,
113 },
114 _ => ev,
115 }
116 }
117}
118
119fn apply_deadzone(x: f32, y: f32, threshold: f32) -> (f32, f32) {
120 let magnitude = utils::clamp((x * x + y * y).sqrt(), 0.0, 1.0);
121 if magnitude <= threshold {
122 (0.0, 0.0)
123 } else {
124 let norm = ((magnitude - threshold) / (1.0 - threshold)) / magnitude;
125 (x * norm, y * norm)
126 }
127}
128
129fn deadzone_nonzero_axis_idx(axis: Axis) -> Option<usize> {
130 Some(match axis {
131 Axis::DPadX => 0,
132 Axis::DPadY => 1,
133 Axis::LeftStickX => 2,
134 Axis::LeftStickY => 3,
135 Axis::RightStickX => 4,
136 Axis::RightStickY => 5,
137 _ => {
138 return None;
139 }
140 })
141}
142
143pub fn deadzone(ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
145 match ev {
146 Some(Event {
147 event: EventType::AxisChanged(axis, val, nec),
148 id,
149 time,
150 }) => {
151 let threshold = match gilrs.gamepad(id).deadzone(nec) {
152 Some(t) => t,
153 None => return ev,
154 };
155
156 if let Some((other_axis, other_code)) = axis
157 .second_axis()
158 .and_then(|axis| gilrs.gamepad(id).axis_code(axis).map(|code| (axis, code)))
159 {
160 let other_val = gilrs.gamepad(id).state().value(other_code);
161 let val = apply_deadzone(val, other_val, threshold);
162
163 let other_axis_idx = deadzone_nonzero_axis_idx(other_axis).unwrap();
165
166 if val.0 == 0.
167 && val.1 == 0.
168 && gilrs.gamepads_data[id.0].have_sent_nonzero_for_axis[other_axis_idx]
169 && gilrs.gamepad(id).state().value(other_code) != 0.
170 {
171 gilrs.insert_event(Event {
173 id,
174 time,
175 event: EventType::AxisChanged(other_axis, 0., other_code),
176 });
177 gilrs.gamepads_data[id.0].have_sent_nonzero_for_axis[other_axis_idx] = false;
178 }
179
180 Some(if gilrs.gamepad(id).state().value(nec) == val.0 {
181 Event::new(id, EventType::Dropped)
182 } else {
183 if let Some(axis_idx) = deadzone_nonzero_axis_idx(axis) {
184 gilrs.gamepads_data[id.0].have_sent_nonzero_for_axis[axis_idx] =
185 val.0 != 0.;
186 }
187 Event {
188 id,
189 time,
190 event: EventType::AxisChanged(axis, val.0, nec),
191 }
192 })
193 } else {
194 let val = apply_deadzone(val, 0.0, threshold).0;
195
196 Some(if gilrs.gamepad(id).state().value(nec) == val {
197 Event::new(id, EventType::Dropped)
198 } else {
199 if let Some(axis_idx) = deadzone_nonzero_axis_idx(axis) {
200 gilrs.gamepads_data[id.0].have_sent_nonzero_for_axis[axis_idx] = val != 0.;
201 }
202 Event {
203 id,
204 time,
205 event: EventType::AxisChanged(axis, val, nec),
206 }
207 })
208 }
209 }
210 Some(Event {
211 event: EventType::ButtonChanged(btn, val, nec),
212 id,
213 time,
214 }) => {
215 let gp = &gilrs.gamepad(id);
216 let threshold = match gp.deadzone(nec) {
217 Some(t) => t,
218 None => return ev,
219 };
220 let val = apply_deadzone(val, 0.0, threshold).0;
221
222 Some(if gp.state().value(nec) == val {
223 Event::new(id, EventType::Dropped)
224 } else {
225 Event {
226 id,
227 time,
228 event: EventType::ButtonChanged(btn, val, nec),
229 }
230 })
231 }
232 _ => ev,
233 }
234}
235
236pub fn axis_dpad_to_button(ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
242 use gilrs_core::native_ev_codes as necs;
243
244 fn can_map(gp: &Gamepad<'_>) -> bool {
245 let hats_mapped = gp.mapping().hats_mapped();
246 if hats_mapped == 0b0000_1111 {
247 true
248 } else if hats_mapped == 0 {
249 gp.axis_or_btn_name(Code(necs::BTN_DPAD_RIGHT)).is_none()
250 && gp.axis_or_btn_name(Code(necs::BTN_DPAD_LEFT)).is_none()
251 && gp.axis_or_btn_name(Code(necs::BTN_DPAD_DOWN)).is_none()
252 && gp.axis_or_btn_name(Code(necs::BTN_DPAD_UP)).is_none()
253 && gp.button_code(Button::DPadRight).is_none()
254 } else {
255 false
257 }
258 }
259
260 let ev = ev?;
261 let gamepad = gilrs.gamepad(ev.id);
262
263 if !can_map(&gamepad) {
264 return Some(ev);
265 }
266
267 let mut out_event = ev.drop();
268
269 match ev.event {
270 EventType::AxisChanged(Axis::DPadX, val, _) => {
271 let mut release_left = false;
272 let mut release_right = false;
273
274 if val == 1.0 {
275 release_left = gamepad.state().is_pressed(Code(necs::BTN_DPAD_LEFT));
278
279 gilrs.insert_event(Event {
280 event: EventType::ButtonChanged(
281 Button::DPadRight,
282 1.0,
283 Code(necs::BTN_DPAD_RIGHT),
284 ),
285 ..ev
286 });
287 out_event = Event {
288 event: EventType::ButtonPressed(Button::DPadRight, Code(necs::BTN_DPAD_RIGHT)),
289 ..ev
290 };
291 } else if val == -1.0 {
292 release_right = gamepad.state().is_pressed(Code(necs::BTN_DPAD_RIGHT));
295
296 gilrs.insert_event(Event {
297 event: EventType::ButtonChanged(
298 Button::DPadLeft,
299 1.0,
300 Code(necs::BTN_DPAD_LEFT),
301 ),
302 ..ev
303 });
304 out_event = Event {
305 event: EventType::ButtonPressed(Button::DPadLeft, Code(necs::BTN_DPAD_LEFT)),
306 ..ev
307 };
308 } else {
309 release_left = gamepad.state().is_pressed(Code(necs::BTN_DPAD_LEFT));
310 release_right = gamepad.state().is_pressed(Code(necs::BTN_DPAD_RIGHT));
311 }
312
313 if release_right {
314 if !out_event.is_dropped() {
315 gilrs.insert_event(out_event);
316 }
317
318 gilrs.insert_event(Event {
319 event: EventType::ButtonChanged(
320 Button::DPadRight,
321 0.0,
322 Code(necs::BTN_DPAD_RIGHT),
323 ),
324 ..ev
325 });
326 out_event = Event {
327 event: EventType::ButtonReleased(Button::DPadRight, Code(necs::BTN_DPAD_RIGHT)),
328 ..ev
329 };
330 }
331
332 if release_left {
333 if !out_event.is_dropped() {
334 gilrs.insert_event(out_event);
335 }
336
337 gilrs.insert_event(Event {
338 event: EventType::ButtonChanged(
339 Button::DPadLeft,
340 0.0,
341 Code(necs::BTN_DPAD_LEFT),
342 ),
343 ..ev
344 });
345 out_event = Event {
346 event: EventType::ButtonReleased(Button::DPadLeft, Code(necs::BTN_DPAD_LEFT)),
347 ..ev
348 };
349 }
350
351 Some(out_event)
352 }
353 EventType::AxisChanged(Axis::DPadY, val, _) => {
354 let mut release_up = false;
355 let mut release_down = false;
356
357 if val == 1.0 {
358 release_down = gamepad.state().is_pressed(Code(necs::BTN_DPAD_DOWN));
361
362 gilrs.insert_event(Event {
363 event: EventType::ButtonChanged(Button::DPadUp, 1.0, Code(necs::BTN_DPAD_UP)),
364 ..ev
365 });
366 out_event = Event {
367 event: EventType::ButtonPressed(Button::DPadUp, Code(necs::BTN_DPAD_UP)),
368 ..ev
369 };
370 } else if val == -1.0 {
371 release_up = gamepad.state().is_pressed(Code(necs::BTN_DPAD_UP));
374
375 gilrs.insert_event(Event {
376 event: EventType::ButtonChanged(
377 Button::DPadDown,
378 1.0,
379 Code(necs::BTN_DPAD_DOWN),
380 ),
381 ..ev
382 });
383 out_event = Event {
384 event: EventType::ButtonPressed(Button::DPadDown, Code(necs::BTN_DPAD_DOWN)),
385 ..ev
386 };
387 } else {
388 release_up = gamepad.state().is_pressed(Code(necs::BTN_DPAD_UP));
389 release_down = gamepad.state().is_pressed(Code(necs::BTN_DPAD_DOWN));
390 }
391
392 if release_up {
393 if !out_event.is_dropped() {
394 gilrs.insert_event(out_event);
395 }
396
397 gilrs.insert_event(Event {
398 event: EventType::ButtonChanged(Button::DPadUp, 0.0, Code(necs::BTN_DPAD_UP)),
399 ..ev
400 });
401 out_event = Event {
402 event: EventType::ButtonReleased(Button::DPadUp, Code(necs::BTN_DPAD_UP)),
403 ..ev
404 };
405 }
406
407 if release_down {
408 if !out_event.is_dropped() {
409 gilrs.insert_event(out_event);
410 }
411
412 gilrs.insert_event(Event {
413 event: EventType::ButtonChanged(
414 Button::DPadDown,
415 0.0,
416 Code(necs::BTN_DPAD_DOWN),
417 ),
418 ..ev
419 });
420 out_event = Event {
421 event: EventType::ButtonReleased(Button::DPadDown, Code(necs::BTN_DPAD_DOWN)),
422 ..ev
423 };
424 }
425
426 Some(out_event)
427 }
428 _ => Some(ev),
429 }
430}
431
432#[derive(Copy, Clone, PartialEq, Eq, Debug)]
434pub struct Repeat {
435 pub after: Duration,
436 pub every: Duration,
437}
438
439impl Repeat {
440 pub fn new() -> Self {
442 Repeat {
443 after: Duration::from_millis(500),
444 every: Duration::from_millis(30),
445 }
446 }
447}
448
449impl Default for Repeat {
450 fn default() -> Self {
451 Self::new()
452 }
453}
454
455impl FilterFn for Repeat {
456 fn filter(&self, ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
457 match ev {
458 Some(ev) => Some(ev),
459 None => {
460 let now = utils::time_now();
461 for (id, gamepad) in gilrs.gamepads() {
462 for (nec, btn_data) in gamepad.state().buttons() {
463 match (
464 btn_data.is_pressed(),
465 btn_data.is_repeating(),
466 now.duration_since(btn_data.timestamp()),
467 ) {
468 (true, false, Ok(dur)) if dur >= self.after => {
469 let btn_name = match gamepad.axis_or_btn_name(nec) {
470 Some(AxisOrBtn::Btn(b)) => b,
471 _ => Button::Unknown,
472 };
473
474 return Some(Event {
475 id,
476 event: EventType::ButtonRepeated(btn_name, nec),
477 time: btn_data.timestamp() + self.after,
478 });
479 }
480 (true, true, Ok(dur)) if dur >= self.every => {
481 let btn_name = match gamepad.axis_or_btn_name(nec) {
482 Some(AxisOrBtn::Btn(b)) => b,
483 _ => Button::Unknown,
484 };
485
486 return Some(Event {
487 id,
488 event: EventType::ButtonRepeated(btn_name, nec),
489 time: btn_data.timestamp() + self.every,
490 });
491 }
492 _ => (),
493 }
494 }
495 }
496 None
497 }
498 }
499 }
500}
501
502pub trait Filter {
506 fn filter_ev<F: FilterFn>(&self, filter: &F, gilrs: &mut Gilrs) -> Option<Event>;
507}
508
509pub trait FilterFn {
513 fn filter(&self, ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event>;
514}
515
516impl<F> FilterFn for F
517where
518 F: Fn(Option<Event>, &mut Gilrs) -> Option<Event>,
519{
520 fn filter(&self, ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
521 self(ev, gilrs)
522 }
523}
524
525impl Filter for Option<Event> {
526 fn filter_ev<F: FilterFn>(&self, filter: &F, gilrs: &mut Gilrs) -> Option<Event> {
527 let e = filter.filter(*self, gilrs);
528 debug_assert!(
529 !(self.is_some() && e.is_none()),
530 "Filter changed Some(event) into None. See ev::filter documentation for more info."
531 );
532
533 e
534 }
535}
536
537impl Filter for Event {
538 fn filter_ev<F: FilterFn>(&self, filter: &F, gilrs: &mut Gilrs) -> Option<Event> {
539 let e = filter.filter(Some(*self), gilrs);
540 debug_assert!(
541 e.is_some(),
542 "Filter changed Some(event) into None. See ev::filter documentation for more info."
543 );
544
545 e
546 }
547}