From b00a225dd034ca75479ad333b0f723a33393da2f Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Sun, 1 Dec 2024 16:34:08 +0000 Subject: [PATCH] refactor: removed repeated code for detecting game input, lowered cmake min version --- CMakeLists.txt | 2 +- include/engine/utilities/input_manager.h | 79 +++++--- src/engine/utilities/input_manager.cpp | 220 ++++++----------------- 3 files changed, 110 insertions(+), 191 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c17735b..b014989 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Define CMake Minimum. -cmake_minimum_required(VERSION 3.25) +cmake_minimum_required(VERSION 3.20) # Project project("Hexwave" VERSION 0.2 DESCRIPTION "An engine designed to make Interactive Films!") diff --git a/include/engine/utilities/input_manager.h b/include/engine/utilities/input_manager.h index 43c80b8..3df092b 100644 --- a/include/engine/utilities/input_manager.h +++ b/include/engine/utilities/input_manager.h @@ -6,28 +6,36 @@ namespace input { +/** + * @brief This is mapped to GLFW's GLFWgamepadstate buttons. + * + * @note This should match every controller. If not, check the gamecontrollerdb.txt in extras + */ enum controller_inputs { - INPUT_UP = 0, - INPUT_DOWN = 1, - INPUT_LEFT = 2, - INPUT_RIGHT = 3, - CONTROLLER_BUTTON_UP = 4, - CONTROLLER_BUTTON_DOWN = 5, - CONTROLLER_BUTTON_LEFT = 6, - CONTROLLER_BUTTON_RIGHT = 7, - CONTROLLER_BUTTON_OPTION = 8, - CONTROLLER_BUTTON_START = 9, - CONTROLLER_BUTTON_LEFT_JOYSTICK = 10, - CONTROLLER_BUTTON_RIGHT_JOYSTICK = 11, - CONTROLLER_BUTTON_LEFT_BUMPER = 12, - CONTROLLER_BUTTON_LB = 12, - CONTROLLER_BUTTON_RIGHT_BUMPER = 13, - CONTROLLER_BUTTON_RB = 13, - CONTROLLER_BUTTON_DPAD_UP = 14, - CONTROLLER_BUTTON_DPAD_DOWN = 15, - CONTROLLER_BUTTON_DPAD_LEFT = 16, - CONTROLLER_BUTTON_DPAD_RIGHT = 17, - CONTROLLER_BUTTON_SPECIAL = 18, // Xbox button, PS button, etc. + /* Button Inputs */ + + CONTROLLER_BUTTON_DOWN = 0, + CONTROLLER_BUTTON_RIGHT = 1, + CONTROLLER_BUTTON_LEFT = 2, + CONTROLLER_BUTTON_UP = 3, + CONTROLLER_BUTTON_LEFT_BUMPER = 4, + CONTROLLER_BUTTON_RIGHT_BUMPER = 5, + CONTROLLER_BUTTON_OPTION = 6, + CONTROLLER_BUTTON_START = 7, + CONTROLLER_BUTTON_SPECIAL = 8, // Xbox button, PS button, etc. + CONTROLLER_BUTTON_LEFT_JOYSTICK = 9, + CONTROLLER_BUTTON_RIGHT_JOYSTICK = 10, + CONTROLLER_BUTTON_DPAD_UP = 11, + CONTROLLER_BUTTON_DPAD_RIGHT = 12, + CONTROLLER_BUTTON_DPAD_DOWN = 13, + CONTROLLER_BUTTON_DPAD_LEFT = 14, + + /* Axis Inputs */ + + INPUT_UP = 15, + INPUT_DOWN = 16, + INPUT_LEFT = 17, + INPUT_RIGHT = 18, }; enum input_types { @@ -59,31 +67,48 @@ class input_manager { * @param key The key that was pressed (look at `GLFW_KEY_`). * */ - std::function on_keyboard_press{nullptr}; + std::function on_keyboard_press { nullptr }; /** * @brief Controller input event * * @param input The input of the controller as `controller_inputs`. */ - std::function on_controller_input{nullptr}; + std::function on_controller_input { nullptr }; /** * @brief Controller button press event * * @param key The controller button as `controller_inputs`. */ - std::function on_controller_button_press{nullptr}; + std::function on_controller_button_press { nullptr }; std::vector keys_held{}; - input_types current_input_type{input::KEYBOARDANDMOUSE}; - controller_types current_controller_type{input::XBOX}; + input_types current_input_type { input::KEYBOARDANDMOUSE }; + controller_types current_controller_type { input::XBOX }; private: + /** + * @brief Time of last input. + * + * @note This is to prevent spam of a button. + * @see time_required_between_input + */ std::chrono::time_point last_input; - float deadzone = 0.2; + + /** + * @brief Time (IN MS) required between last and current input. + */ + uint16_t time_required_between_input { 100 }; + + /** + * @brief a Dead-Zone for the axis inputs. + * + * @note This prevents the smallest of movements from triggering input. + */ + float dead_zone { 0.2 }; }; } diff --git a/src/engine/utilities/input_manager.cpp b/src/engine/utilities/input_manager.cpp index cb3786d..888c434 100644 --- a/src/engine/utilities/input_manager.cpp +++ b/src/engine/utilities/input_manager.cpp @@ -9,26 +9,28 @@ input::input_manager::input_manager(GLFWwindow* window) { std::cout << "Setting up input manager..." << "\n"; - static input_manager *mgr = this; + static input_manager *input_mgr = this; // Fire callback when keyboard input fires. glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods) { // Update input type to Keyboard/Mouse. - mgr->current_input_type = KEYBOARDANDMOUSE; + input_mgr->current_input_type = KEYBOARDANDMOUSE; if (action == GLFW_PRESS) { - mgr->keys_held.emplace_back(key); - mgr->on_keyboard_press(key); + input_mgr->keys_held.emplace_back(key); + input_mgr->on_keyboard_press(key); } if(action == GLFW_RELEASE) { - mgr->keys_held.erase(std::remove(mgr->keys_held.begin(), mgr->keys_held.end(), key), mgr->keys_held.end()); + input_mgr->keys_held.erase(std::remove(input_mgr->keys_held.begin(), + input_mgr->keys_held.end(), key), + input_mgr->keys_held.end()); } }); // Fire callback when mouse moves. glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos) { // Update input type to Keyboard/Mouse. - mgr->current_input_type = KEYBOARDANDMOUSE; + input_mgr->current_input_type = KEYBOARDANDMOUSE; }); std::ifstream game_controller_db("extras/gamecontrollerdb.txt"); @@ -56,191 +58,83 @@ input::input_manager::~input_manager() { } void input::input_manager::input_loop() { - if (glfwJoystickPresent(GLFW_JOYSTICK_1) == GLFW_TRUE) { - const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1); - - // Is the controller a Playstation Controller? - if (std::string(name).find("DualSense") == 0) { - current_controller_type = PLAYSTATION; - } else { - // Default to XBOX if we can't find "DualSense". - current_controller_type = XBOX; - } + if (glfwJoystickPresent(GLFW_JOYSTICK_1) != GLFW_TRUE) { + return; + } + + const char *name = glfwGetJoystickName(GLFW_JOYSTICK_1); + // Is the controller a Playstation Controller? + if (std::string(name).find("DualSense") == 0) { + current_controller_type = PLAYSTATION; + } else { + // Default to XBOX if we can't find "DualSense". + current_controller_type = XBOX; + } + + { int count; // Luckily, controller axis input on Playstation isn't any different to Xbox. - if (on_controller_input) { - const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count); + const float *axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count); - const float x_axis = axes[0]; - const float y_axis = axes[1]; + const float x_axis = axes[0]; + const float y_axis = axes[1]; - if (abs(x_axis) >= deadzone) { + if (abs(x_axis) >= dead_zone) { + if (on_controller_input) { if (x_axis < 0) { on_controller_input(INPUT_LEFT); } else { on_controller_input(INPUT_RIGHT); } - - current_input_type = CONTROLLER; } - if (abs(y_axis) >= deadzone) { + current_input_type = CONTROLLER; + } + + if (abs(y_axis) >= dead_zone) { + if (on_controller_input) { if (y_axis < 0) { on_controller_input(INPUT_UP); } else { on_controller_input(INPUT_DOWN); } - - current_input_type = CONTROLLER; } - } - GLFWgamepadstate state{}; - if (glfwGetGamepadState(GLFW_JOYSTICK_1, &state) == GLFW_FALSE) { - return; + current_input_type = CONTROLLER; } + } - const unsigned char* buttons = state.buttons; - - // Definitely a better way to do below code (mapping buttons to the actual index of the array?) but oh well. - if (on_controller_button_press) { - if (buttons[0] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_DOWN); - current_input_type = CONTROLLER; - last_input = std::chrono::high_resolution_clock::now(); - } - } - - if (buttons[1] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_RIGHT); - current_input_type = CONTROLLER; - } - } - - if (buttons[2] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_LEFT); - current_input_type = CONTROLLER; - } - } - - if (buttons[3] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_UP); - current_input_type = CONTROLLER; - } - } - - if (buttons[4] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_LEFT_BUMPER); - current_input_type = CONTROLLER; - } - } - - if (buttons[5] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_RIGHT_BUMPER); - current_input_type = CONTROLLER; - } - } - - if (buttons[6] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_OPTION); - current_input_type = CONTROLLER; - } - } - - if (buttons[7] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_START); - current_input_type = CONTROLLER; - } - } - - if (buttons[8] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_SPECIAL); - current_input_type = CONTROLLER; - } - } - - if (buttons[9] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_LEFT_JOYSTICK); - current_input_type = CONTROLLER; - } - } + GLFWgamepadstate state{}; + if (glfwGetGamepadState(GLFW_JOYSTICK_1, &state) == GLFW_FALSE) { + return; + } - if (buttons[10] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_RIGHT_JOYSTICK); - current_input_type = CONTROLLER; - } - } + const unsigned char* buttons = state.buttons; - if (buttons[11] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_DPAD_UP); - current_input_type = CONTROLLER; - } - } + int button_pressed_index{ -1 }; - if (buttons[12] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_DPAD_RIGHT); - current_input_type = CONTROLLER; - } - } + // state.buttons declares itself as "buttons[15]", so this is safe. + for (uint8_t i = 0; i < 15; i++) { + if (buttons[i] == GLFW_PRESS) { + button_pressed_index = i; + break; + } + } - if (buttons[13] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_DPAD_DOWN); - current_input_type = CONTROLLER; - } + if (button_pressed_index != -1) { + const auto now_time = std::chrono::high_resolution_clock::now(); + const auto result = std::chrono::duration_cast(now_time - last_input); + if (result.count() >= time_required_between_input) { + // Should always be true because we literally depend on this, + // but never hurts to be safe. + if (on_controller_button_press) { + on_controller_button_press(static_cast(button_pressed_index)); } - if (buttons[14] == GLFW_PRESS) { - const auto now_time = std::chrono::high_resolution_clock::now(); - const auto result = std::chrono::duration_cast(now_time - last_input); - if(result.count() >= 100) { - on_controller_button_press(CONTROLLER_BUTTON_DPAD_LEFT); - current_input_type = CONTROLLER; - } - } + current_input_type = CONTROLLER; + last_input = std::chrono::high_resolution_clock::now(); } } }