#include "input.h" #include // Constructor Input::Input(string file, bool verbose) { // Fichero gamecontrollerdb.txt dbPath = file; // Inicializa las variables keyBindings_t kb; kb.scancode = 0; kb.active = false; keyBindings.clear(); keyBindings.resize(INPUT_TOTAL, kb); GameControllerBindings_t gcb; gcb.button = SDL_CONTROLLER_BUTTON_INVALID; gcb.active = false; gameControllerBindings.clear(); gameControllerBindings.resize(INPUT_TOTAL, gcb); this->verbose = verbose; enabled = true; setDefaultBindings(); discoverGameController(); } // Actualiza el estado del objeto void Input::update() { if (disabledUntil == d_keyPressed && !checkAnyInput()) { enable(); } } // Asigna inputs a teclas void Input::bindKey(Uint8 input, SDL_Scancode code) { keyBindings[input].scancode = code; } // Asigna inputs a botones del mando void Input::bindGameControllerButton(Uint8 input, SDL_GameControllerButton button) { gameControllerBindings[input].button = button; } // Comprueba si un input esta activo bool Input::checkInput(Uint8 input, bool repeat, int device, int index) { if (!enabled) { 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[input].button) != 0) { successGameController = true; } else { successGameController = false; } } else { if (!gameControllerBindings[input].active) { if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[input].button) != 0) { gameControllerBindings[input].active = true; successGameController = true; } else { successGameController = false; } } else { if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[input].button) == 0) { gameControllerBindings[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) { 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[i].button) != 0) { return true; } } } } return false; } // Busca si hay un mando conectado bool Input::discoverGameController() { bool found = false; if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) != 1) { SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); } if (SDL_GameControllerAddMappingsFromFile(dbPath.c_str()) < 0) { if (verbose) { cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << endl; } } const int nJoysticks = SDL_NumJoysticks(); numGamepads = 0; // Cuenta el numero de mandos for (int i = 0; i < nJoysticks; ++i) { if (SDL_IsGameController(i)) { numGamepads++; } } if (verbose) { if (nJoysticks > 0) { string stNumJoysticks = nJoysticks == 1 ? "joystick" : "joysticks"; string stNumGamePads = numGamepads == 1 ? "is a gamepad" : "are gamepads"; cout << "\n** Checking game controllers" << endl; cout << nJoysticks << " " << stNumJoysticks << " found (" << numGamepads << " " << stNumGamePads << ")\n"; } else { cout << "\n>> No game controllers found\n"; } } if (numGamepads > 0) { found = true; cout << "\n>> GAMEPAD LIST:" << endl; 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 string separator(" #"); string name = SDL_GameControllerNameForIndex(i); // name.resize(25); // name = name + separator + to_string(i); if (verbose) { // cout << " - " << name << endl; cout << "#" << i + 1 << ": " << name << endl; } controllerNames.push_back(name); } else { if (verbose) { cout << "SDL_GetError() = " << SDL_GetError() << endl; } } } cout << 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 string Input::getControllerName(int index) { if (numGamepads > 0) { return controllerNames[index]; } else { return ""; } } // Obten el numero 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; } // Establece unas teclas y botones del mando por defectp void Input::setDefaultBindings() { // Teclado bindKey(INPUT_UP, SDL_SCANCODE_UP); bindKey(INPUT_DOWN, SDL_SCANCODE_DOWN); bindKey(INPUT_LEFT, SDL_SCANCODE_LEFT); bindKey(INPUT_RIGHT, SDL_SCANCODE_RIGHT); bindKey(INPUT_BUTTON_1, SDL_SCANCODE_Z); bindKey(INPUT_BUTTON_2, SDL_SCANCODE_X); bindKey(INPUT_ACCEPT, SDL_SCANCODE_RETURN); bindKey(INPUT_CANCEL, SDL_SCANCODE_ESCAPE); bindKey(INPUT_PAUSE, SDL_SCANCODE_H); bindKey(INPUT_EXIT, SDL_SCANCODE_ESCAPE); // Mando bindGameControllerButton(INPUT_UP, SDL_CONTROLLER_BUTTON_DPAD_UP); bindGameControllerButton(INPUT_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN); bindGameControllerButton(INPUT_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT); bindGameControllerButton(INPUT_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); bindGameControllerButton(INPUT_BUTTON_1, SDL_CONTROLLER_BUTTON_A); bindGameControllerButton(INPUT_BUTTON_2, SDL_CONTROLLER_BUTTON_B); bindGameControllerButton(INPUT_BUTTON_3, SDL_CONTROLLER_BUTTON_X); bindGameControllerButton(INPUT_BUTTON_4, SDL_CONTROLLER_BUTTON_Y); bindGameControllerButton(INPUT_BUTTON_5, SDL_CONTROLLER_BUTTON_BACK); bindGameControllerButton(INPUT_BUTTON_6, SDL_CONTROLLER_BUTTON_START); bindGameControllerButton(INPUT_BUTTON_7, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); bindGameControllerButton(INPUT_BUTTON_8, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); bindGameControllerButton(INPUT_ACCEPT, SDL_CONTROLLER_BUTTON_A); bindGameControllerButton(INPUT_CANCEL, SDL_CONTROLLER_BUTTON_B); bindGameControllerButton(INPUT_PAUSE, SDL_CONTROLLER_BUTTON_START); bindGameControllerButton(INPUT_EXIT, SDL_CONTROLLER_BUTTON_BACK); } // Elimina todas las asociaciones de teclado y mando al objeto void Input::clearBindings() { // Inicializa las variables keyBindings_t kb; kb.scancode = 0; kb.active = false; keyBindings.clear(); keyBindings.resize(INPUT_TOTAL, kb); GameControllerBindings_t gcb; gcb.button = SDL_CONTROLLER_BUTTON_INVALID; gcb.active = false; gameControllerBindings.clear(); gameControllerBindings.resize(INPUT_TOTAL, gcb); }