chargrid_graphical_gfx 0.1.0

chargrid context which renders with gfx
Documentation
use glutin::dpi::{LogicalPosition, LogicalSize};
use glutin::{
    ElementState, ModifiersState, MouseButton as GlutinMouseButton, MouseScrollDelta, VirtualKeyCode, WindowEvent,
};
use chargrid_input::{
    keys, Input, KeyboardInput, MouseButton as ChargridMouseButton, MouseButton, MouseInput, ScrollDirection,
};
use chargrid_render::Coord;

pub enum InputEvent {
    Input(Input),
    Resize(f32, f32),
    Quit,
}

macro_rules! convert_char_shift {
    ($lower:expr, $upper:expr, $shift:expr) => {
        KeyboardInput::Char(if $shift { $upper } else { $lower })
    };
}

#[allow(clippy::cognitive_complexity)]
fn convert_keycode_keyboard_input(code: VirtualKeyCode, shift: bool) -> Option<KeyboardInput> {
    let keyboard_input = match code {
        VirtualKeyCode::Space => KeyboardInput::Char(' '),
        VirtualKeyCode::A => convert_char_shift!('a', 'A', shift),
        VirtualKeyCode::B => convert_char_shift!('b', 'B', shift),
        VirtualKeyCode::C => convert_char_shift!('c', 'C', shift),
        VirtualKeyCode::D => convert_char_shift!('d', 'D', shift),
        VirtualKeyCode::E => convert_char_shift!('e', 'E', shift),
        VirtualKeyCode::F => convert_char_shift!('f', 'F', shift),
        VirtualKeyCode::G => convert_char_shift!('g', 'G', shift),
        VirtualKeyCode::H => convert_char_shift!('h', 'H', shift),
        VirtualKeyCode::I => convert_char_shift!('i', 'I', shift),
        VirtualKeyCode::J => convert_char_shift!('j', 'J', shift),
        VirtualKeyCode::K => convert_char_shift!('k', 'K', shift),
        VirtualKeyCode::L => convert_char_shift!('l', 'L', shift),
        VirtualKeyCode::M => convert_char_shift!('m', 'M', shift),
        VirtualKeyCode::N => convert_char_shift!('n', 'N', shift),
        VirtualKeyCode::O => convert_char_shift!('o', 'O', shift),
        VirtualKeyCode::P => convert_char_shift!('p', 'P', shift),
        VirtualKeyCode::Q => convert_char_shift!('q', 'Q', shift),
        VirtualKeyCode::R => convert_char_shift!('r', 'R', shift),
        VirtualKeyCode::S => convert_char_shift!('s', 'S', shift),
        VirtualKeyCode::T => convert_char_shift!('t', 'T', shift),
        VirtualKeyCode::U => convert_char_shift!('u', 'U', shift),
        VirtualKeyCode::V => convert_char_shift!('v', 'V', shift),
        VirtualKeyCode::W => convert_char_shift!('w', 'W', shift),
        VirtualKeyCode::X => convert_char_shift!('x', 'X', shift),
        VirtualKeyCode::Y => convert_char_shift!('y', 'Y', shift),
        VirtualKeyCode::Z => convert_char_shift!('z', 'Z', shift),
        VirtualKeyCode::Key1 => convert_char_shift!('1', '!', shift),
        VirtualKeyCode::Key2 => KeyboardInput::Char('2'),
        VirtualKeyCode::Key3 => convert_char_shift!('3', '#', shift),
        VirtualKeyCode::Key4 => convert_char_shift!('4', '$', shift),
        VirtualKeyCode::Key5 => convert_char_shift!('5', '%', shift),
        VirtualKeyCode::Key6 => convert_char_shift!('6', '^', shift),
        VirtualKeyCode::Key7 => convert_char_shift!('7', '&', shift),
        VirtualKeyCode::Key8 => convert_char_shift!('8', '*', shift),
        VirtualKeyCode::Key9 => convert_char_shift!('9', '(', shift),
        VirtualKeyCode::Key0 => convert_char_shift!('0', ')', shift),
        VirtualKeyCode::Numpad1 => KeyboardInput::Char('1'),
        VirtualKeyCode::Numpad2 => KeyboardInput::Char('2'),
        VirtualKeyCode::Numpad3 => KeyboardInput::Char('3'),
        VirtualKeyCode::Numpad4 => KeyboardInput::Char('4'),
        VirtualKeyCode::Numpad5 => KeyboardInput::Char('5'),
        VirtualKeyCode::Numpad6 => KeyboardInput::Char('6'),
        VirtualKeyCode::Numpad7 => KeyboardInput::Char('7'),
        VirtualKeyCode::Numpad8 => KeyboardInput::Char('8'),
        VirtualKeyCode::Numpad9 => KeyboardInput::Char('9'),
        VirtualKeyCode::Numpad0 => KeyboardInput::Char('0'),
        VirtualKeyCode::Period => convert_char_shift!('.', '>', shift),
        VirtualKeyCode::Comma => convert_char_shift!(',', '<', shift),
        VirtualKeyCode::Slash => convert_char_shift!('/', '?', shift),
        VirtualKeyCode::Left => KeyboardInput::Left,
        VirtualKeyCode::Right => KeyboardInput::Right,
        VirtualKeyCode::Up => KeyboardInput::Up,
        VirtualKeyCode::Down => KeyboardInput::Down,
        VirtualKeyCode::Escape => keys::ESCAPE,
        VirtualKeyCode::Return => keys::RETURN,
        VirtualKeyCode::At => KeyboardInput::Char('@'),
        VirtualKeyCode::Add => KeyboardInput::Char('+'),
        VirtualKeyCode::Subtract => KeyboardInput::Char('-'),
        VirtualKeyCode::Equals => convert_char_shift!('=', '+', shift),
        VirtualKeyCode::Backslash => convert_char_shift!('\\', '|', shift),
        VirtualKeyCode::Grave => convert_char_shift!('`', '~', shift),
        VirtualKeyCode::Apostrophe => convert_char_shift!('\'', '"', shift),
        VirtualKeyCode::LBracket => convert_char_shift!('[', '{', shift),
        VirtualKeyCode::RBracket => convert_char_shift!(']', '}', shift),
        VirtualKeyCode::PageUp => KeyboardInput::PageUp,
        VirtualKeyCode::PageDown => KeyboardInput::PageDown,
        VirtualKeyCode::Home => KeyboardInput::Home,
        VirtualKeyCode::End => KeyboardInput::End,
        VirtualKeyCode::F1 => KeyboardInput::Function(1),
        VirtualKeyCode::F2 => KeyboardInput::Function(2),
        VirtualKeyCode::F3 => KeyboardInput::Function(3),
        VirtualKeyCode::F4 => KeyboardInput::Function(4),
        VirtualKeyCode::F5 => KeyboardInput::Function(5),
        VirtualKeyCode::F6 => KeyboardInput::Function(6),
        VirtualKeyCode::F7 => KeyboardInput::Function(7),
        VirtualKeyCode::F8 => KeyboardInput::Function(8),
        VirtualKeyCode::F9 => KeyboardInput::Function(9),
        VirtualKeyCode::F10 => KeyboardInput::Function(10),
        VirtualKeyCode::F11 => KeyboardInput::Function(11),
        VirtualKeyCode::F12 => KeyboardInput::Function(12),
        VirtualKeyCode::F13 => KeyboardInput::Function(13),
        VirtualKeyCode::F14 => KeyboardInput::Function(14),
        VirtualKeyCode::F15 => KeyboardInput::Function(15),
        VirtualKeyCode::F16 => KeyboardInput::Function(16),
        VirtualKeyCode::F17 => KeyboardInput::Function(17),
        VirtualKeyCode::F18 => KeyboardInput::Function(18),
        VirtualKeyCode::F19 => KeyboardInput::Function(19),
        VirtualKeyCode::F20 => KeyboardInput::Function(20),
        VirtualKeyCode::F21 => KeyboardInput::Function(21),
        VirtualKeyCode::F22 => KeyboardInput::Function(22),
        VirtualKeyCode::F23 => KeyboardInput::Function(23),
        VirtualKeyCode::F24 => KeyboardInput::Function(24),
        _ => return None,
    };
    Some(keyboard_input)
}

fn convert_keycode(code: VirtualKeyCode, keymod: ModifiersState) -> Option<Input> {
    convert_keycode_keyboard_input(code, keymod.shift).map(Input::Keyboard)
}

pub fn convert_event(
    event: WindowEvent,
    (cell_width, cell_height): (f32, f32),
    last_mouse_coord: &mut Coord,
    last_mouse_button: &mut Option<MouseButton>,
) -> Option<InputEvent> {
    match event {
        WindowEvent::CloseRequested => Some(InputEvent::Quit),
        WindowEvent::Resized(LogicalSize { width, height }) => Some(InputEvent::Resize(width as f32, height as f32)),
        WindowEvent::KeyboardInput { input, .. } => {
            if let ElementState::Pressed = input.state {
                if let Some(virtual_keycode) = input.virtual_keycode {
                    if let Some(input) = convert_keycode(virtual_keycode, input.modifiers) {
                        return Some(InputEvent::Input(input));
                    }
                }
            }
            None
        }
        WindowEvent::CursorMoved {
            position: LogicalPosition { x, y },
            ..
        } => {
            let x = (x / (cell_width as f64)) as i32;
            let y = (y / (cell_height as f64)) as i32;
            let coord = Coord::new(x, y);
            *last_mouse_coord = coord;
            Some(InputEvent::Input(Input::Mouse(MouseInput::MouseMove {
                coord,
                button: *last_mouse_button,
            })))
        }
        WindowEvent::MouseInput { state, button, .. } => {
            let button = match button {
                GlutinMouseButton::Left => ChargridMouseButton::Left,
                GlutinMouseButton::Middle => ChargridMouseButton::Middle,
                GlutinMouseButton::Right => ChargridMouseButton::Right,
                GlutinMouseButton::Other(_) => return None,
            };
            let input = match state {
                ElementState::Pressed => {
                    *last_mouse_button = Some(button);
                    Input::Mouse(MouseInput::MousePress {
                        coord: *last_mouse_coord,
                        button,
                    })
                }
                ElementState::Released => {
                    *last_mouse_button = None;
                    Input::Mouse(MouseInput::MouseRelease {
                        coord: *last_mouse_coord,
                        button: Ok(button),
                    })
                }
            };
            Some(InputEvent::Input(input))
        }
        WindowEvent::MouseWheel { delta, .. } => {
            let (x, y) = match delta {
                MouseScrollDelta::LineDelta(x, y) => (x, y),
                MouseScrollDelta::PixelDelta(LogicalPosition { x, y }) => (x as f32, y as f32),
            };
            let direction = if y > 0. {
                ScrollDirection::Up
            } else if y < 0. {
                ScrollDirection::Down
            } else if x > 0. {
                ScrollDirection::Right
            } else if x < 0. {
                ScrollDirection::Left
            } else {
                return None;
            };
            Some(InputEvent::Input(Input::Mouse(MouseInput::MouseScroll {
                direction,
                coord: *last_mouse_coord,
            })))
        }
        _ => None,
    }
}