#include "stdafx.h" #include "InputHandler.h" namespace fpr { std::vector<InputHandler*> InputHandler::S_INPUT_HANDLERS; glm::highp_dvec2 InputHandler::old_cursor_pos; glm::highp_dvec2 InputHandler::new_cursor_pos; glm::highp_dvec2 InputHandler::dx_dy; double InputHandler::delta_time; void fpr::InputHandler::BindAction(EKeyCode key, action_callback callback, EKeyState key_state) { m_tracked_key_actions.emplace(key, std::make_tuple(callback, key_state, false)); } void InputHandler::BindAxis(EKeyCode key, axis_callback callback, EAxis axis, EKeyState key_state) { m_tracked_key_axis.emplace(key, std::make_tuple(callback, key_state, false, axis)); } void InputHandler::BindMouseAxis(EMouseAxis mouse_axis, mouse_axis_callback callback) { m_mouse_axis_bindings.emplace(mouse_axis, callback); } void InputHandler::BindMouseButton(EMouseButton button, action_callback callback, EKeyState state) { m_tracked_mouse_btns.emplace(button, std::make_tuple(callback, state, false)); } const glm::highp_dvec2& InputHandler::GetCursorDelta() { return dx_dy; } void InputHandler::Update([[maybe_unused]] GLFWwindow* window) { for(InputHandler* instance : S_INPUT_HANDLERS) { for(auto& [button, callback_data] : instance->m_tracked_mouse_btns) { auto& [callback, state, is_pressed] = callback_data; if(state == fpr::EKeyState::EKS_HOLD && is_pressed) callback(); } for(auto& [button, callback_data] : instance->m_tracked_key_actions) { auto& [callback, state, is_pressed] = callback_data; if(state == fpr::EKeyState::EKS_HOLD && is_pressed) callback(); } for(auto& [button, callback_data] : instance->m_tracked_key_axis) { auto& [callback, state, is_pressed, axis] = callback_data; if(state == fpr::EKeyState::EKS_HOLD && is_pressed) callback((double)axis * delta_time); } } dx_dy = {}; } InputHandler::~InputHandler() {} void InputHandler::SetDeltaTime(double delta) { delta_time = delta; } void fpr::InputHandler::KeyCallback( [[maybe_unused]] GLFWwindow* window, int key, [[maybe_unused]] int scan_code, int action, [[maybe_unused]] int mods) { for(InputHandler* instance : S_INPUT_HANDLERS) { auto action_it = instance->m_tracked_key_actions.find(static_cast<EKeyCode>(key)); if(action_it != instance->m_tracked_key_actions.end()) { auto& [callback, state, is_pressed] = action_it->second; is_pressed = static_cast<EKeyState>(action) != EKeyState::EKS_RELEASED; if(static_cast<EKeyState>(action) == state) { callback(); } } auto axis_it = instance->m_tracked_key_axis.find(static_cast<EKeyCode>(key)); if(axis_it != instance->m_tracked_key_axis.end()) { auto& [callback, state, is_pressed, axis] = axis_it->second; is_pressed = static_cast<EKeyState>(action) != EKeyState::EKS_RELEASED; } } } void InputHandler::MouseBtnCallback( [[maybe_unused]] GLFWwindow* window, int button, int action, [[maybe_unused]] int mods) { for(InputHandler* instance : S_INPUT_HANDLERS) { if(!instance->m_enabled) continue; auto iter = instance->m_tracked_mouse_btns.find(static_cast<EMouseButton>(button)); if(iter == instance->m_tracked_mouse_btns.end()) continue; else { auto& [callback, state, is_pressed] = iter->second; is_pressed = static_cast<EKeyState>(action) != fpr::EKeyState::EKS_RELEASED; if(static_cast<EKeyState>(action) == state || is_pressed) { callback; } } } } void InputHandler::MouseMovementCallback([[maybe_unused]] GLFWwindow* window, double x, double y) { new_cursor_pos.x = x; new_cursor_pos.y = y; dx_dy = glm::normalize(old_cursor_pos - new_cursor_pos); old_cursor_pos = new_cursor_pos; for(InputHandler* instance : S_INPUT_HANDLERS) { if(!instance->m_enabled) continue; if(dx_dy.x != 0) { auto it = instance->m_mouse_axis_bindings.find(EMouseAxis::EMA_X); if(it != instance->m_mouse_axis_bindings.end()) { auto& callback = it->second; callback(dx_dy.x * delta_time); } } if(dx_dy.y != 0) { auto it = instance->m_mouse_axis_bindings.find(EMouseAxis::EMA_Y); if(it != instance->m_mouse_axis_bindings.end()) { auto& callback = it->second; callback(dx_dy.y * delta_time); } } } } void InputHandler::Enable(bool is_enabled) { m_enabled = is_enabled; }; fpr::InputHandler::InputHandler(GLFWwindow* window): m_window(window) { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); glfwSetKeyCallback(window, InputHandler::KeyCallback); glfwSetMouseButtonCallback(window, InputHandler::MouseBtnCallback); glfwSetCursorPosCallback(window, InputHandler::MouseMovementCallback); glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GLFW_TRUE); double mouse_x; double mouse_y; glfwGetCursorPos(window, &mouse_x, &mouse_y); S_INPUT_HANDLERS.push_back(this); } } // namespace fpr