use crate::mapping::binding::InputBinding;
use crate::state::advanced::AdvancedInputState;
use crate::trigger::trigger::InputTrigger;
use crate::types::GamepadId;
pub trait Triggerable {
fn evaluate(
&self,
trigger: &InputTrigger,
input: &AdvancedInputState,
gamepad_id: Option<GamepadId>,
) -> bool;
}
impl Triggerable for InputBinding {
fn evaluate(
&self,
trigger: &InputTrigger,
input: &AdvancedInputState,
gamepad_id: Option<GamepadId>,
) -> bool {
match trigger {
InputTrigger::Down => is_down(self, input, gamepad_id),
InputTrigger::Pressed => is_just_pressed(self, input, gamepad_id),
InputTrigger::Released => is_just_released(self, input, gamepad_id),
InputTrigger::Held { min_duration } => is_held(self, input, gamepad_id, *min_duration),
InputTrigger::Chord(triggers) => {
triggers.iter().all(|t| self.evaluate(t, input, gamepad_id))
}
}
}
}
fn is_down(
binding: &InputBinding,
input: &AdvancedInputState,
gamepad_id: Option<GamepadId>,
) -> bool {
match binding {
InputBinding::Key(k) => input.is_key_down(*k),
InputBinding::MouseButton(b) => input.is_mouse_button_down(*b),
InputBinding::GamepadButton(b) => gamepad_id
.and_then(|id| input.gamepads.get(id))
.map(|gp| gp.is_button_down(*b))
.unwrap_or(false),
InputBinding::GamepadAxis(a) => gamepad_id
.and_then(|id| input.gamepads.get(id))
.map(|gp| gp.get_axis(*a).abs() > 0.1)
.unwrap_or(false),
}
}
fn is_just_pressed(
binding: &InputBinding,
input: &AdvancedInputState,
gamepad_id: Option<GamepadId>,
) -> bool {
match binding {
InputBinding::Key(k) => input.was_key_just_pressed(*k),
InputBinding::MouseButton(b) => input.mouse.was_button_just_pressed(*b),
InputBinding::GamepadButton(b) => gamepad_id
.and_then(|id| input.gamepads.get(id))
.map(|gp| {
gp.buttons
.get(b)
.map(|s| s.just_pressed_frame.is_some())
.unwrap_or(false)
})
.unwrap_or(false),
_ => false, }
}
fn is_just_released(
binding: &InputBinding,
input: &AdvancedInputState,
gamepad_id: Option<GamepadId>,
) -> bool {
match binding {
InputBinding::Key(k) => input.keyboard.was_just_released(*k),
InputBinding::MouseButton(b) => input.mouse.was_button_just_released(*b),
InputBinding::GamepadButton(b) => gamepad_id
.and_then(|id| input.gamepads.get(id))
.map(|gp| {
gp.buttons
.get(b)
.map(|s| s.just_released_frame.is_some())
.unwrap_or(false)
})
.unwrap_or(false),
_ => false,
}
}
fn is_held(
binding: &InputBinding,
input: &AdvancedInputState,
_gamepad_id: Option<GamepadId>,
min_duration_ms: f32,
) -> bool {
let (is_down, duration) = match binding {
InputBinding::Key(k) => (
input.keyboard.is_down(*k),
input.keyboard.get_held_duration(*k),
),
InputBinding::MouseButton(b) => input
.mouse
.buttons
.get(b)
.map(|s| (s.is_down, s.held_duration_ms))
.unwrap_or((false, 0.0)),
_ => (false, 0.0),
};
is_down && duration >= min_duration_ms
}