use ev::{Axis, AxisOrBtn, Button, Code, Event, EventType};
use gamepad::{Gamepad, Gilrs};
use utils;
use std::time::{Duration, SystemTime};
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Jitter {
pub threshold: f32,
}
impl Jitter {
pub fn new() -> Self {
Jitter { threshold: 0.01 }
}
}
impl FilterFn for Jitter {
fn filter(&self, ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
match ev {
Some(Event {
event: EventType::AxisChanged(_, val, axis),
id,
..
}) => match gilrs[id].state().axis_data(axis) {
Some(data) if val != 0.0 && (val - data.value()).abs() < self.threshold => {
Some(Event::dropped())
}
_ => ev,
},
_ => ev,
}
}
}
fn apply_deadzone(x: f32, y: f32, threshold: f32) -> (f32, f32) {
let magnitude = utils::clamp((x * x + y * y).sqrt(), 0.0, 1.0);
if magnitude <= threshold {
(0.0, 0.0)
} else {
let norm = ((magnitude - threshold) / (1.0 - threshold)) / magnitude;
(x * norm, y * norm)
}
}
pub fn deadzone(ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
match ev {
Some(Event {
event: EventType::AxisChanged(axis, val, nec),
id,
time,
}) => {
let threshold = match gilrs[id].deadzone(nec) {
Some(t) => t,
None => return ev,
};
if let Some((other, other_code)) = axis.second_axis()
.and_then(|axis| gilrs[id].axis_code(axis).map(|code| (axis, code)))
{
let other_val = gilrs[id].state().value(other_code);
let val = apply_deadzone(val, other_val, threshold);
Some(if gilrs[id].state().value(nec) == val.0 {
Event::dropped()
} else {
Event {
id,
time,
event: EventType::AxisChanged(axis, val.0, nec),
}
})
} else {
let val = apply_deadzone(val, 0.0, threshold).0;
Some(if gilrs[id].state().value(nec) == val {
Event::dropped()
} else {
Event {
id,
time,
event: EventType::AxisChanged(axis, val, nec),
}
})
}
}
Some(Event {
event: EventType::ButtonChanged(btn, val, nec),
id,
time,
}) => {
let gp = &gilrs[id];
let threshold = match gp.deadzone(nec) {
Some(t) => t,
None => return ev,
};
let val = apply_deadzone(val, 0.0, threshold).0;
Some(if gp.state().value(nec) == val {
Event::dropped()
} else {
Event {
id,
time,
event: EventType::ButtonChanged(btn, val, nec),
}
})
}
_ => ev,
}
}
pub fn axis_dpad_to_button(ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
use platform::native_ev_codes as necs;
fn can_map(gp: &Gamepad) -> bool {
let hats_mapped = gp.mapping().hats_mapped();
if hats_mapped == 0b0000_1111 {
true
} else if hats_mapped == 0 {
gp.axis_or_btn_name(Code(necs::BTN_DPAD_RIGHT)).is_none()
&& gp.axis_or_btn_name(Code(necs::BTN_DPAD_LEFT)).is_none()
&& gp.axis_or_btn_name(Code(necs::BTN_DPAD_DOWN)).is_none()
&& gp.axis_or_btn_name(Code(necs::BTN_DPAD_UP)).is_none()
&& gp.button_code(Button::DPadRight).is_none()
} else {
false
}
}
match ev {
Some(Event {
event: EventType::AxisChanged(Axis::DPadX, val, _),
id,
time,
}) if can_map(&gilrs[id]) =>
{
Some(if val == 1.0 {
Event {
id,
time,
event: EventType::ButtonPressed(Button::DPadRight, Code(necs::BTN_DPAD_RIGHT)),
}
} else if val == -1.0 {
Event {
id,
time,
event: EventType::ButtonPressed(Button::DPadLeft, Code(necs::BTN_DPAD_LEFT)),
}
} else if gilrs[id].state().is_pressed(Code(necs::BTN_DPAD_RIGHT)) {
Event {
id,
time,
event: EventType::ButtonReleased(Button::DPadRight, Code(necs::BTN_DPAD_RIGHT)),
}
} else {
Event {
id,
time,
event: EventType::ButtonReleased(Button::DPadLeft, Code(necs::BTN_DPAD_LEFT)),
}
})
}
Some(Event {
event: EventType::AxisChanged(Axis::DPadY, val, _),
id,
time,
}) if can_map(&gilrs[id]) =>
{
Some(if val == 1.0 {
Event {
id,
time,
event: EventType::ButtonPressed(Button::DPadUp, Code(necs::BTN_DPAD_UP)),
}
} else if val == -1.0 {
Event {
id,
time,
event: EventType::ButtonPressed(Button::DPadDown, Code(necs::BTN_DPAD_DOWN)),
}
} else if gilrs[id].state().is_pressed(Code(necs::BTN_DPAD_UP)) {
Event {
id,
time,
event: EventType::ButtonReleased(Button::DPadUp, Code(necs::BTN_DPAD_UP)),
}
} else {
Event {
id,
time,
event: EventType::ButtonReleased(Button::DPadDown, Code(necs::BTN_DPAD_DOWN)),
}
})
}
_ => ev,
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Repeat {
pub after: Duration,
pub every: Duration,
}
impl Repeat {
pub fn new() -> Self {
Repeat {
after: Duration::from_millis(500),
every: Duration::from_millis(30),
}
}
}
impl FilterFn for Repeat {
fn filter(&self, ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
match ev {
Some(ev) => Some(ev),
None => {
let now = SystemTime::now();
for (id, gamepad) in gilrs.gamepads() {
for (nec, btn_data) in gamepad.state().buttons() {
match (
btn_data.is_pressed(),
btn_data.is_repeating(),
now.duration_since(btn_data.timestamp()),
) {
(true, false, Ok(dur)) if dur >= self.after => {
let btn_name = match gamepad.axis_or_btn_name(nec) {
Some(AxisOrBtn::Btn(b)) => b,
_ => Button::Unknown,
};
return Some(Event {
id,
event: EventType::ButtonRepeated(btn_name, nec),
time: btn_data.timestamp() + self.after,
});
}
(true, true, Ok(dur)) if dur >= self.every => {
let btn_name = match gamepad.axis_or_btn_name(nec) {
Some(AxisOrBtn::Btn(b)) => b,
_ => Button::Unknown,
};
return Some(Event {
id,
event: EventType::ButtonRepeated(btn_name, nec),
time: btn_data.timestamp() + self.every,
});
}
_ => (),
}
}
}
None
}
}
}
}
pub trait Filter {
fn filter_ev<F: FilterFn>(&self, filter: &F, gilrs: &mut Gilrs) -> Option<Event>;
}
pub trait FilterFn {
fn filter(&self, ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event>;
}
impl<F> FilterFn for F
where
F: Fn(Option<Event>, &mut Gilrs) -> Option<Event>,
{
fn filter(&self, ev: Option<Event>, gilrs: &mut Gilrs) -> Option<Event> {
self(ev, gilrs)
}
}
impl Filter for Option<Event> {
fn filter_ev<F: FilterFn>(&self, filter: &F, gilrs: &mut Gilrs) -> Option<Event> {
let e = filter.filter(*self, gilrs);
debug_assert!(
!(self.is_some() && e.is_none()),
"Filter changed Some(event) into None. See ev::filter documentation for more info."
);
e
}
}
impl Filter for Event {
fn filter_ev<F: FilterFn>(&self, filter: &F, gilrs: &mut Gilrs) -> Option<Event> {
let e = filter.filter(Some(*self), gilrs);
debug_assert!(
!e.is_none(),
"Filter changed Some(event) into None. See ev::filter documentation for more info."
);
e
}
}