#pragma once #include <stdafx.h> #include "VulkanWindow.h" namespace fpr { enum class EKeyCode : int16_t { EKC_SPACE = GLFW_KEY_SPACE, EKC_APOSTROPHE = GLFW_KEY_APOSTROPHE, /* ' */ EKC_COMMA = GLFW_KEY_COMMA, /* , */ EKC_MINUS = GLFW_KEY_MINUS, /* - */ EKC_PERIOD = GLFW_KEY_PERIOD, /* . */ EKC_SLASH = GLFW_KEY_SLASH, /* / */ EKC_0 = GLFW_KEY_0, EKC_1 = GLFW_KEY_1, EKC_2 = GLFW_KEY_2, EKC_3 = GLFW_KEY_3, EKC_4 = GLFW_KEY_4, EKC_5 = GLFW_KEY_5, EKC_6 = GLFW_KEY_6, EKC_7 = GLFW_KEY_7, EKC_8 = GLFW_KEY_8, EKC_9 = GLFW_KEY_9, EKC_SEMICOLON = GLFW_KEY_SEMICOLON, /* ; */ EKC_EQUAL = GLFW_KEY_EQUAL, /* = */ EKC_A = GLFW_KEY_A, EKC_B = GLFW_KEY_B, EKC_C = GLFW_KEY_C, EKC_D = GLFW_KEY_D, EKC_E = GLFW_KEY_E, EKC_F = GLFW_KEY_F, EKC_G = GLFW_KEY_G, EKC_H = GLFW_KEY_H, EKC_I = GLFW_KEY_I, EKC_J = GLFW_KEY_J, EKC_K = GLFW_KEY_K, EKC_L = GLFW_KEY_L, EKC_M = GLFW_KEY_M, EKC_N = GLFW_KEY_N, EKC_O = GLFW_KEY_O, EKC_P = GLFW_KEY_P, EKC_Q = GLFW_KEY_Q, EKC_R = GLFW_KEY_R, EKC_S = GLFW_KEY_S, EKC_T = GLFW_KEY_T, EKC_U = GLFW_KEY_U, EKC_V = GLFW_KEY_V, EKC_W = GLFW_KEY_W, EKC_X = GLFW_KEY_X, EKC_Y = GLFW_KEY_Y, EKC_Z = GLFW_KEY_Z, EKC_LEFT_BRACKET = GLFW_KEY_LEFT_BRACKET, /* [ */ EKC_BACKSLASH = GLFW_KEY_BACKSLASH, /* \ */ EKC_RIGHT_BRACKET = GLFW_KEY_RIGHT_BRACKET, /* ] */ EKC_GRAVE_ACCENT = GLFW_KEY_GRAVE_ACCENT, /* ` */ EKC_WORLD_1 = GLFW_KEY_WORLD_1, /* non-US #1 */ EKC_WORLD_2 = GLFW_KEY_WORLD_2, /* non-US #2 */ EKC_ESCAPE = GLFW_KEY_ESCAPE, EKC_ENTER = GLFW_KEY_ENTER, EKC_TAB = GLFW_KEY_TAB, EKC_BACKSPACE = GLFW_KEY_BACKSPACE, EKC_INSERT = GLFW_KEY_INSERT, EKC_DELETE = GLFW_KEY_DELETE, EKC_RIGHT = GLFW_KEY_RIGHT, EKC_LEFT = GLFW_KEY_LEFT, EKC_DOWN = GLFW_KEY_DOWN, EKC_UP = GLFW_KEY_UP, EKC_PAGE_UP = GLFW_KEY_PAGE_UP, EKC_PAGE_DOWN = GLFW_KEY_PAGE_DOWN, EKC_HOME = GLFW_KEY_HOME, EKC_END = GLFW_KEY_END, EKC_CAPS_LOCK = GLFW_KEY_CAPS_LOCK, EKC_SCROLL_LOCK = GLFW_KEY_SCROLL_LOCK, EKC_NUM_LOCK = GLFW_KEY_NUM_LOCK, EKC_PRINT_SCREEN = GLFW_KEY_PRINT_SCREEN, EKC_PAUSE = GLFW_KEY_PAUSE, EKC_F1 = GLFW_KEY_F1, EKC_F2 = GLFW_KEY_F2, EKC_F3 = GLFW_KEY_F3, EKC_F4 = GLFW_KEY_F4, EKC_F5 = GLFW_KEY_F5, EKC_F6 = GLFW_KEY_F6, EKC_F7 = GLFW_KEY_F7, EKC_F8 = GLFW_KEY_F8, EKC_F9 = GLFW_KEY_F9, EKC_F10 = GLFW_KEY_F10, EKC_F11 = GLFW_KEY_F11, EKC_F12 = GLFW_KEY_F12, EKC_F13 = GLFW_KEY_F13, EKC_F14 = GLFW_KEY_F14, EKC_F15 = GLFW_KEY_F15, EKC_F16 = GLFW_KEY_F16, EKC_F17 = GLFW_KEY_F17, EKC_F18 = GLFW_KEY_F18, EKC_F19 = GLFW_KEY_F19, EKC_F20 = GLFW_KEY_F20, EKC_F21 = GLFW_KEY_F21, EKC_F22 = GLFW_KEY_F22, EKC_F23 = GLFW_KEY_F23, EKC_F24 = GLFW_KEY_F24, EKC_F25 = GLFW_KEY_F25, EKC_KP_0 = GLFW_KEY_KP_0, EKC_KP_1 = GLFW_KEY_KP_1, EKC_KP_2 = GLFW_KEY_KP_2, EKC_KP_3 = GLFW_KEY_KP_3, EKC_KP_4 = GLFW_KEY_KP_4, EKC_KP_5 = GLFW_KEY_KP_5, EKC_KP_6 = GLFW_KEY_KP_6, EKC_KP_7 = GLFW_KEY_KP_7, EKC_KP_8 = GLFW_KEY_KP_8, EKC_KP_9 = GLFW_KEY_KP_9, EKC_KP_DECIMAL = GLFW_KEY_KP_DECIMAL, EKC_KP_DIVIDE = GLFW_KEY_KP_DIVIDE, EKC_KP_MULTIPLY = GLFW_KEY_KP_MULTIPLY, EKC_KP_SUBTRACT = GLFW_KEY_KP_SUBTRACT, EKC_KP_ADD = GLFW_KEY_KP_ADD, EKC_KP_ENTER = GLFW_KEY_KP_ENTER, EKC_KP_EQUAL = GLFW_KEY_KP_EQUAL, EKC_LEFT_SHIFT = GLFW_KEY_LEFT_SHIFT, EKC_LEFT_CONTROL = GLFW_KEY_LEFT_CONTROL, EKC_LEFT_ALT = GLFW_KEY_LEFT_ALT, EKC_LEFT_SUPER = GLFW_KEY_LEFT_SUPER, EKC_RIGHT_SHIFT = GLFW_KEY_RIGHT_SHIFT, EKC_RIGHT_CONTROL = GLFW_KEY_RIGHT_CONTROL, EKC_RIGHT_ALT = GLFW_KEY_RIGHT_ALT, EKC_RIGHT_SUPER = GLFW_KEY_RIGHT_SUPER, EKC_MENU = GLFW_KEY_MENU, }; enum class EMouseButton : int16_t { EMB_1 = GLFW_MOUSE_BUTTON_1, EMB_2 = GLFW_MOUSE_BUTTON_2, EMB_3 = GLFW_MOUSE_BUTTON_3, EMB_4 = GLFW_MOUSE_BUTTON_4, EMB_5 = GLFW_MOUSE_BUTTON_5, EMB_6 = GLFW_MOUSE_BUTTON_6, EMB_7 = GLFW_MOUSE_BUTTON_7, EMB_8 = GLFW_MOUSE_BUTTON_8, EMB_LEFT = GLFW_MOUSE_BUTTON_LEFT, EMB_RIGHT = GLFW_MOUSE_BUTTON_RIGHT, EMB_MIDDLE = GLFW_MOUSE_BUTTON_MIDDLE, }; enum class EKeyState : int8_t { EKS_UNKNOWN = GLFW_KEY_UNKNOWN, EKS_RELEASED = GLFW_RELEASE, EKS_PRESSSED = GLFW_PRESS, EKS_REPEAT = GLFW_REPEAT, EKS_HOLD = 3 }; enum EAxis : int8_t { EA_NEGATIVE = -1, EA_POSITIVE = 1 }; enum class EMouseAxis : int8_t { EMA_X, EMA_Y }; class InputHandler { using axis_callback = std::function<void(double)>; using action_callback = std::function<void()>; using axis_callback_data = std::tuple<axis_callback, EKeyState, bool, EAxis>; using mouse_axis_callback = std::function<void(double)>; using action_callback_data = std::tuple<action_callback, EKeyState, bool>; using KeyActionCallbacks = std::map<EKeyCode, action_callback_data, std::less<>>; using KeyAxisCallbacks = std::map<EKeyCode, axis_callback_data, std::less<>>; using MouseCallbacks = std::map<EMouseButton, action_callback_data, std::less<>>; std::map<EMouseAxis, mouse_axis_callback> m_mouse_axis_bindings; GLFWwindow* m_window; KeyActionCallbacks m_tracked_key_actions; KeyAxisCallbacks m_tracked_key_axis; MouseCallbacks m_tracked_mouse_btns; static glm::highp_dvec2 old_cursor_pos; static glm::highp_dvec2 new_cursor_pos; static glm::highp_dvec2 dx_dy; //IMPORTANT: //An input handler is registered and held in this **STATIC** vector when constructed. This allows for multiple input handlers. //Therefore, I can bind different keys to different actions based on what they are resposible for. //For example, a camera input handler may bind the mouse for movoement. //However, I may also want to use the mouse for camera picking. //Having seperate input handlers allows for usage of same keys, and the user can pick between different input handlers based on the internal state of their program. static std::vector<InputHandler*> S_INPUT_HANDLERS; static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); static void MouseBtnCallback(GLFWwindow* window, int button, int action, int mods); static void MouseMovementCallback(GLFWwindow* window, double x, double y); bool m_enabled = true; static double delta_time; public: void Enable(bool is_enabled); InputHandler(GLFWwindow* window); void BindAction(EKeyCode key, action_callback callback, EKeyState key_state = EKeyState::EKS_PRESSSED); void BindAxis( EKeyCode key, axis_callback callback, EAxis axis = EAxis::EA_POSITIVE, EKeyState key_state = EKeyState::EKS_PRESSSED); void BindMouseAxis(EMouseAxis mouse_axis, mouse_axis_callback callback); void BindMouseButton(EMouseButton, action_callback callback, EKeyState = EKeyState::EKS_PRESSSED); const glm::highp_dvec2& GetCursorDelta(); static void Update(GLFWwindow* window); ~InputHandler(); static void SetDeltaTime(double delta); }; } // namespace fpr