Skip to content

Commit

Permalink
refactor: removed repeated code for detecting game input, lowered cma…
Browse files Browse the repository at this point in the history
…ke min version
  • Loading branch information
Jaskowicz1 committed Dec 1, 2024
1 parent da0bc64 commit b00a225
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 191 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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!")

Expand Down
79 changes: 52 additions & 27 deletions include/engine/utilities/input_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -59,31 +67,48 @@ class input_manager {
* @param key The key that was pressed (look at `GLFW_KEY_`).
*
*/
std::function<void(int key)> on_keyboard_press{nullptr};
std::function<void(int key)> on_keyboard_press { nullptr };

/**
* @brief Controller input event
*
* @param input The input of the controller as `controller_inputs`.
*/
std::function<void(controller_inputs input)> on_controller_input{nullptr};
std::function<void(controller_inputs input)> on_controller_input { nullptr };

/**
* @brief Controller button press event
*
* @param key The controller button as `controller_inputs`.
*/
std::function<void(controller_inputs key)> on_controller_button_press{nullptr};
std::function<void(controller_inputs key)> on_controller_button_press { nullptr };

std::vector<int> 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<std::chrono::high_resolution_clock> 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 };
};

}
220 changes: 57 additions & 163 deletions src/engine/utilities/input_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<controller_inputs>(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<std::chrono::milliseconds>(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();
}
}
}

0 comments on commit b00a225

Please sign in to comment.