#include "input.h" #include // Constructor Input::Input(std::string file) { // Inicializa variables verbose = false; enabled = true; // Fichero gamecontrollerdb.txt dbPath = file; // Busca si hay mandos conectados discoverGameControllers(); // Inicializa las vectores keyBindings_t kb; kb.scancode = 0; kb.active = false; keyBindings.resize(input_number_of_inputs, kb); GameControllerBindings_t gcb; gcb.button = SDL_CONTROLLER_BUTTON_INVALID; gcb.active = false; gameControllerBindings.resize(numGamepads); for (int i = 0; i < numGamepads; ++i) { gameControllerBindings[i].resize(input_number_of_inputs, gcb); } // Listado de los inputs usados para jugar, excluyendo botones para la interfaz gameInputs.clear(); gameInputs.push_back(input_fire_left); gameInputs.push_back(input_fire_center); gameInputs.push_back(input_fire_right); gameInputs.push_back(input_up); gameInputs.push_back(input_down); gameInputs.push_back(input_left); gameInputs.push_back(input_right); // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas buttonInputs.clear(); buttonInputs.push_back(input_fire_left); buttonInputs.push_back(input_fire_center); buttonInputs.push_back(input_fire_right); buttonInputs.push_back(input_start); } // Actualiza el estado del objeto void Input::update() { if (disabledUntil == d_keyPressed && !checkAnyInput()) { enable(); } } // Asigna inputs a teclas void Input::bindKey(inputs_e input, SDL_Scancode code) { keyBindings[input].scancode = code; } // Asigna inputs a botones del mando void Input::bindGameControllerButton(int index, inputs_e input, SDL_GameControllerButton button) { if (index >= (int)connectedControllers.size()) { return; } gameControllerBindings[index][input].button = button; } // Comprueba si un input esta activo bool Input::checkInput(inputs_e input, bool repeat, int device, int index) { if (!enabled || index >= numGamepads) { return false; } bool successKeyboard = false; bool successGameController = false; if (device == INPUT_USE_ANY) { index = 0; } if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) { const Uint8 *keyStates = SDL_GetKeyboardState(nullptr); if (repeat) { if (keyStates[keyBindings[input].scancode] != 0) { successKeyboard = true; } else { successKeyboard = false; } } else { if (!keyBindings[input].active) { if (keyStates[keyBindings[input].scancode] != 0) { keyBindings[input].active = true; successKeyboard = true; } else { successKeyboard = false; } } else { if (keyStates[keyBindings[input].scancode] == 0) { keyBindings[input].active = false; successKeyboard = false; } else { successKeyboard = false; } } } } if (gameControllerFound()) if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) { if (repeat) { if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) { successGameController = true; } else { successGameController = false; } } else { if (!gameControllerBindings[index][input].active) { if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) { gameControllerBindings[index][input].active = true; successGameController = true; } else { successGameController = false; } } else { if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) == 0) { gameControllerBindings[index][input].active = false; successGameController = false; } else { successGameController = false; } } } } return (successKeyboard || successGameController); } // Comprueba si hay almenos un input activo bool Input::checkAnyInput(int device, int index) { if (device == INPUT_USE_ANY) { index = 0; } if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) { const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr); for (int i = 0; i < (int)keyBindings.size(); ++i) { if (mKeystates[keyBindings[i].scancode] != 0 && !keyBindings[i].active) { keyBindings[i].active = true; return true; } } } if (gameControllerFound()) { if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY) { for (int i = 0; i < (int)gameControllerBindings.size(); ++i) { if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][i].button) != 0 && !gameControllerBindings[index][i].active) { gameControllerBindings[index][i].active = true; return true; } } } } return false; } // Comprueba si hay algún botón pulsado. Devuelve 0 en caso de no encontrar nada o el indice del dispositivo + 1. Se hace así para poder gastar el valor devuelto como un valor "booleano" int Input::checkAnyButtonPressed(bool repeat) { // Solo comprueba los botones for (auto bi : buttonInputs) { // Comprueba el teclado if (checkInput(bi, repeat, INPUT_USE_KEYBOARD)) { return 1; } // Comprueba los mandos for (int i = 0; i < numGamepads; ++i) { if (checkInput(bi, repeat, INPUT_USE_GAMECONTROLLER, i)) { return i + 1; } } } return 0; } // Busca si hay mandos conectados bool Input::discoverGameControllers() { bool found = false; if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) != 1) { SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); } if (SDL_GameControllerAddMappingsFromFile(dbPath.c_str()) < 0) { if (verbose) { std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << std::endl; } } numJoysticks = SDL_NumJoysticks(); numGamepads = 0; // Cuenta el número de mandos joysticks.clear(); for (int i = 0; i < numJoysticks; ++i) { SDL_Joystick *joy = SDL_JoystickOpen(i); joysticks.push_back(joy); if (SDL_IsGameController(i)) { numGamepads++; } } if (verbose) { std::cout << "\nChecking for game controllers...\n"; std::cout << numJoysticks << " joysticks found, " << numGamepads << " are gamepads\n"; } if (numGamepads > 0) { found = true; for (int i = 0; i < numGamepads; i++) { // Abre el mando y lo añade a la lista SDL_GameController *pad = SDL_GameControllerOpen(i); if (SDL_GameControllerGetAttached(pad) == 1) { connectedControllers.push_back(pad); const std::string separator(" #"); std::string name = SDL_GameControllerNameForIndex(i); // name.resize(25); // name = name + separator + std::to_string(i); if (verbose) { std::cout << name << std::endl; } controllerNames.push_back(name); } else { if (verbose) { std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl; } } } SDL_GameControllerEventState(SDL_ENABLE); } return found; } // Comprueba si hay algun mando conectado bool Input::gameControllerFound() { if (numGamepads > 0) { return true; } else { return false; } } // Obten el nombre de un mando de juego std::string Input::getControllerName(int index) { if (numGamepads > 0) { return controllerNames[index]; } else { return ""; } } // Obten el número de mandos conectados int Input::getNumControllers() { return numGamepads; } // Establece si ha de mostrar mensajes void Input::setVerbose(bool value) { verbose = value; } // Deshabilita las entradas durante un periodo de tiempo void Input::disableUntil(i_disable_e value) { disabledUntil = value; enabled = false; } // Hablita las entradas void Input::enable() { enabled = true; disabledUntil = d_notDisabled; } // Obtiene el indice del controlador a partir de un event.id int Input::getJoyIndex(int id) { for (int i = 0; i < numJoysticks; ++i) { if (SDL_JoystickInstanceID(joysticks[i]) == id) { return i; } } return -1; } // Muestra por consola los controles asignados void Input::printBindings(int device, int index) { if (device == INPUT_USE_ANY) { return; } if (device == INPUT_USE_KEYBOARD) { return; } if (device == INPUT_USE_GAMECONTROLLER) { if (index >= numGamepads) { return; } // Muestra el nombre del mando std::cout << "\n" << controllerNames[index] << std::endl; // Muestra los botones asignados for (auto bi : buttonInputs) { std::cout << to_String(bi) << " : " << gameControllerBindings[index][bi].button << std::endl; } } } // Convierte un inputs_e a std::string std::string Input::to_String(inputs_e input) { if (input == input_fire_left) { return "input_fire_left"; } if (input == input_fire_center) { return "input_fire_center"; } if (input == input_fire_right) { return "input_fire_right"; } if (input == input_start) { return "input_start"; } return ""; }