shine-input 0.2.1

SHINE. Input handling for the shine engine.
Documentation
use crate::{ButtonId, ModifierFilterMask, ModifierId};
use std::collections::HashMap;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum InputMapping {
    ScanCodeKey(winit::ScanCode),
    VirtualKey(winit::VirtualKeyCode),
    MouseAxis(u32),
    MouseAxisWithDevice(winit::DeviceId, u32),
    Gamepad(gilrs::ev::Axis),
    GamepadWithDevice(gilrs::GamepadId, gilrs::ev::Axis),
}

pub struct Mapping {
    axis_mapping: HashMap<InputMapping, (ButtonId, ModifierFilterMask, f32)>,
    modifier_mapping: HashMap<InputMapping, ModifierId>,
}

impl Mapping {
    pub fn new() -> Mapping {
        Mapping {
            axis_mapping: HashMap::new(),
            modifier_mapping: HashMap::new(),
        }
    }

    pub fn add_modifier_mapping(&mut self, input_event: InputMapping, modifier_id: ModifierId) {
        if self.modifier_mapping.values().any(|m| *m == modifier_id) {
            log::warn!("Multiple mapping for {:?}", modifier_id);
        }
        self.modifier_mapping.insert(input_event, modifier_id);
    }

    pub fn add_button_mapping(
        &mut self,
        input_event: InputMapping,
        input_modifiers: Option<ModifierFilterMask>,
        button_id: ButtonId,
        sensitivity: f32,
    ) {
        if self.axis_mapping.values().any(|b| b.0 == button_id) {
            log::warn!("Multiple mapping for {:?}", button_id);
        }

        let mask = input_modifiers.unwrap_or_default();
        self.axis_mapping.insert(input_event, (button_id, mask, sensitivity));
    }

    pub fn map_winit_axis_to_modifier(&self, device_id: winit::DeviceId, axis: u32) -> Option<ModifierId> {
        let mapping = &self.modifier_mapping;

        if let Some(res) = mapping.get(&InputMapping::MouseAxisWithDevice(device_id.to_owned(), axis)) {
            return Some(res.to_owned());
        }

        if let Some(res) = mapping.get(&InputMapping::MouseAxis(axis)) {
            return Some(res.to_owned());
        }

        None
    }

    pub fn map_winit_key_to_modifier(&self, key_input: &winit::KeyboardInput) -> Option<ModifierId> {
        let mapping = &self.modifier_mapping;

        if let Some(res) = mapping.get(&InputMapping::ScanCodeKey(key_input.scancode)) {
            return Some(res.to_owned());
        }

        if let Some(vk) = key_input.virtual_keycode {
            if let Some(res) = mapping.get(&InputMapping::VirtualKey(vk)) {
                return Some(res.to_owned());
            }
        }

        None
    }

    pub fn map_winit_axis_to_button(&self, device_id: winit::DeviceId, axis: u32) -> Option<(ButtonId, ModifierFilterMask, f32)> {
        let mapping = &self.axis_mapping;

        if let Some(res) = mapping.get(&InputMapping::MouseAxisWithDevice(device_id.to_owned(), axis)) {
            return Some(res.to_owned());
        }

        if let Some(res) = mapping.get(&InputMapping::MouseAxis(axis)) {
            return Some(res.to_owned());
        }

        None
    }

    pub fn map_winit_key_to_button(&self, key_input: &winit::KeyboardInput) -> Option<(ButtonId, ModifierFilterMask, f32)> {
        let mapping = &self.axis_mapping;

        if let Some(res) = mapping.get(&InputMapping::ScanCodeKey(key_input.scancode)) {
            return Some(res.to_owned());
        }

        if let Some(vk) = key_input.virtual_keycode {
            if let Some(res) = mapping.get(&InputMapping::VirtualKey(vk)) {
                return Some(res.to_owned());
            }
        }

        None
    }

    pub fn map_gil_axis_to_modifier(&self, device_id: gilrs::GamepadId, axis: gilrs::ev::Axis) -> Option<ModifierId> {
        let mapping = &self.modifier_mapping;

        if let Some(res) = mapping.get(&InputMapping::GamepadWithDevice(device_id.to_owned(), axis.to_owned())) {
            return Some(res.to_owned());
        }

        if let Some(res) = mapping.get(&InputMapping::Gamepad(axis.to_owned())) {
            return Some(res.to_owned());
        }

        None
    }

    pub fn map_gil_axis_to_button(
        &self,
        device_id: gilrs::GamepadId,
        axis: gilrs::ev::Axis,
    ) -> Option<(ButtonId, ModifierFilterMask, f32)> {
        let mapping = &self.axis_mapping;

        if let Some(res) = mapping.get(&InputMapping::GamepadWithDevice(device_id.to_owned(), axis.to_owned())) {
            return Some(res.to_owned());
        }

        if let Some(res) = mapping.get(&InputMapping::Gamepad(axis.to_owned())) {
            return Some(res.to_owned());
        }

        None
    }
}