use super::binding::{ActivationMode, KeyCode, Modifiers, MouseButton, TriggerKind};
use std::collections::HashSet;
#[derive(Debug, Clone)]
pub struct FrameInput {
pub keys_pressed: HashSet<KeyCode>,
pub keys_held: HashSet<KeyCode>,
pub modifiers: Modifiers,
pub drag_started: HashSet<MouseButton>,
pub dragging: HashSet<MouseButton>,
pub drag_delta: glam::Vec2,
pub scroll_delta: f32,
pub clicked: HashSet<MouseButton>,
pub pointer_delta: glam::Vec2,
pub hovered: bool,
pub ctrl_scroll_orbit_delta: glam::Vec2,
pub shift_scroll_pan_delta: glam::Vec2,
}
impl Default for FrameInput {
fn default() -> Self {
Self {
keys_pressed: Default::default(),
keys_held: Default::default(),
modifiers: Default::default(),
drag_started: Default::default(),
dragging: Default::default(),
drag_delta: glam::Vec2::ZERO,
scroll_delta: 0.0,
clicked: Default::default(),
pointer_delta: glam::Vec2::ZERO,
hovered: false,
ctrl_scroll_orbit_delta: glam::Vec2::ZERO,
shift_scroll_pan_delta: glam::Vec2::ZERO,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ActionState {
Inactive,
Pressed,
Active {
delta: glam::Vec2,
},
}
impl ActionState {
pub fn pressed(self) -> bool {
matches!(self, ActionState::Pressed)
}
pub fn is_active(self) -> bool {
!matches!(self, ActionState::Inactive)
}
pub fn delta(self) -> glam::Vec2 {
match self {
ActionState::Active { delta } => delta,
_ => glam::Vec2::ZERO,
}
}
}
pub(crate) fn modifiers_match(required: &Modifiers, current: &Modifiers, ignore: bool) -> bool {
if ignore {
return true;
}
required == current
}
pub(crate) fn evaluate_trigger(
kind: &TriggerKind,
activation: &ActivationMode,
required_mods: &Modifiers,
ignore_mods: bool,
input: &FrameInput,
) -> ActionState {
if !modifiers_match(required_mods, &input.modifiers, ignore_mods) {
return ActionState::Inactive;
}
match (kind, activation) {
(TriggerKind::Key(key), ActivationMode::OnPress) => {
if input.keys_pressed.contains(key) {
ActionState::Pressed
} else {
ActionState::Inactive
}
}
(TriggerKind::Key(key), ActivationMode::WhileHeld) => {
if input.keys_held.contains(key) {
ActionState::Active {
delta: glam::Vec2::ZERO,
}
} else {
ActionState::Inactive
}
}
(TriggerKind::MouseButton(btn), ActivationMode::OnPress) => {
if input.clicked.contains(btn) {
ActionState::Pressed
} else {
ActionState::Inactive
}
}
(TriggerKind::MouseButton(btn), ActivationMode::OnDrag) => {
if input.dragging.contains(btn) {
ActionState::Active {
delta: input.drag_delta,
}
} else {
ActionState::Inactive
}
}
(TriggerKind::Scroll, ActivationMode::OnScroll) => {
if input.scroll_delta.abs() > 0.0 {
ActionState::Active {
delta: glam::Vec2::new(0.0, input.scroll_delta),
}
} else {
ActionState::Inactive
}
}
_ => ActionState::Inactive,
}
}