Newer
Older
ForwardPlusRenderer / include / InputHandler.h
#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