diff --git a/es-core/src/InputConfig.cpp b/es-core/src/InputConfig.cpp index e610528f8..960cb8544 100644 --- a/es-core/src/InputConfig.cpp +++ b/es-core/src/InputConfig.cpp @@ -96,6 +96,15 @@ bool InputConfig::getInputByName(const std::string& name, Input* result) return false; } +int InputConfig::getInputIDByName(const std::string& name) +{ + auto it = mNameMap.find(toLower(name)); + if (it != mNameMap.cend()) { + return it->second.id; + } + return -1; +} + bool InputConfig::isMappedTo(const std::string& name, Input input) { Input comp; diff --git a/es-core/src/InputConfig.h b/es-core/src/InputConfig.h index d38a37ff0..1a05bc49b 100644 --- a/es-core/src/InputConfig.h +++ b/es-core/src/InputConfig.h @@ -142,6 +142,7 @@ public: // Returns true if there is an Input mapped to this name, false otherwise. // Writes Input mapped to this name to result if true. bool getInputByName(const std::string& name, Input* result); + int getInputIDByName(const std::string& name); void loadFromXML(pugi::xml_node& root); void writeToXML(pugi::xml_node& parent); diff --git a/es-core/src/InputManager.cpp b/es-core/src/InputManager.cpp index 66ef837cc..765449617 100644 --- a/es-core/src/InputManager.cpp +++ b/es-core/src/InputManager.cpp @@ -142,7 +142,7 @@ void InputManager::removeJoystickByJoystickID(SDL_JoystickID joyId) mJoysticks.erase(joyIt); } else { - LOG(LogError) << "Could not find joystick to close (instance ID: " << joyId << ")"; + LOG(LogError) << "Error - Could not find joystick to close (instance ID: " << joyId << ")"; } } @@ -151,16 +151,16 @@ void InputManager::deinit() if (!initialized()) return; - for (auto iter = mJoysticks.cbegin(); iter != mJoysticks.cend(); iter++) - SDL_JoystickClose(iter->second); + for (auto it = mJoysticks.cbegin(); it != mJoysticks.cend(); it++) + SDL_JoystickClose(it->second); mJoysticks.clear(); - for (auto iter = mInputConfigs.cbegin(); iter != mInputConfigs.cend(); iter++) - delete iter->second; + for (auto it = mInputConfigs.cbegin(); it != mInputConfigs.cend(); it++) + delete it->second; mInputConfigs.clear(); - for (auto iter = mPrevAxisValues.cbegin(); iter != mPrevAxisValues.cend(); iter++) - delete[] iter->second; + for (auto it = mPrevAxisValues.cbegin(); it != mPrevAxisValues.cend(); it++) + delete[] it->second; mPrevAxisValues.clear(); if (mKeyboardInputConfig != nullptr) { @@ -191,11 +191,11 @@ int InputManager::getButtonCountByDevice(SDL_JoystickID id) if (id == DEVICE_KEYBOARD) return 120; // It's a lot, okay. else if (id == DEVICE_CEC) -#ifdef HAVE_CECLIB + #ifdef HAVE_CECLIB return CEC::CEC_USER_CONTROL_CODE_MAX; -#else // HAVE_LIBCEF + #else // HAVE_LIBCEF return 0; -#endif // HAVE_CECLIB + #endif // HAVE_CECLIB else return SDL_JoystickNumButtons(mJoysticks[id]); } @@ -213,26 +213,40 @@ InputConfig* InputManager::getInputConfigByDevice(int device) bool InputManager::parseEvent(const SDL_Event& ev, Window* window) { bool causedEvent = false; + int32_t axisValue; + switch (ev.type) { case SDL_JOYAXISMOTION: - // If it switched boundaries. - if ((abs(ev.jaxis.value) > DEADZONE) != + axisValue = ev.jaxis.value; + // For the analog trigger buttons, convert the negative<->positive axis values to only + // positive values in order to avoid registering double inputs. This is only a + // temporary solution until ES has been updated to use the SDL GameController API. + if (ev.jaxis.axis == mInputConfigs[ev.jaxis.which]->getInputIDByName("lefttrigger") || + ev.jaxis.axis == mInputConfigs[ev.jaxis.which]->getInputIDByName("righttrigger")) { + axisValue += 32768; + axisValue /= 2; + } + + // Check if the input value switched boundaries. + if ((abs(axisValue) > DEADZONE) != (abs(mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis]) > DEADZONE)) { int normValue; - if (abs(ev.jaxis.value) <= DEADZONE) + if (abs(axisValue) <= DEADZONE) { normValue = 0; - else - if (ev.jaxis.value > 0) + } + else { + if (axisValue > 0) normValue = 1; else normValue = -1; + } window->input(getInputConfigByDevice(ev.jaxis.which), Input(ev.jaxis.which, TYPE_AXIS, ev.jaxis.axis, normValue, false)); causedEvent = true; } - mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis] = ev.jaxis.value; + mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis] = axisValue; return causedEvent; case SDL_JOYBUTTONDOWN: diff --git a/es-core/src/guis/GuiInputConfig.cpp b/es-core/src/guis/GuiInputConfig.cpp index a859b1054..0a8729129 100755 --- a/es-core/src/guis/GuiInputConfig.cpp +++ b/es-core/src/guis/GuiInputConfig.cpp @@ -380,26 +380,35 @@ bool GuiInputConfig::filterTrigger(Input input, InputConfig* config, int inputId #if defined(__linux__) // On Linux, some gamepads return both an analog axis and a digital button for the trigger; // we want the analog axis only, so this function removes the button press event. - - if (( - // Match PlayStation joystick with 6 axes only. - strstr(config->getDeviceName().c_str(), "PLAYSTATION") != nullptr || - strstr(config->getDeviceName().c_str(), "PS3 Ga") != nullptr || - strstr(config->getDeviceName().c_str(), "PS(R) Ga") != nullptr || - // BigBen kid's PS3 gamepad 146b:0902, matched on SDL GUID because its name "Bigben - // Interactive Bigben Game Pad" may be too generic. - strcmp(config->getDeviceGUIDString().c_str(), "030000006b1400000209000011010000") == 0) - && InputManager::getInstance()->getAxisCountByDevice(config->getDeviceId()) == 6) { - // Digital triggers are unwanted. - if (input.type == TYPE_BUTTON && (input.id == 6 || input.id == 7)) { - mHoldingInput = false; - return true; + // This is relevant mostly for Sony Dual Shock controllers. + if (InputManager::getInstance()->getAxisCountByDevice(config->getDeviceId()) == 6) { + if (config->getDeviceName().find("PLAYSTATION") != std::string::npos || + config->getDeviceName().find("PS3 Ga") != std::string::npos || + config->getDeviceName().find("PS(R) Ga") != std::string::npos || + config->getDeviceName().find("PS4 Controller") != std::string::npos || + config->getDeviceName().find("Sony Interactive") != std::string::npos || + // BigBen kid's PS3 gamepad 146b:0902, matched on SDL GUID because its name + // "Bigben Interactive Bigben Game Pad" may be too generic. + config->getDeviceGUIDString().find("030000006b1400000209000011010000") + != std::string::npos ) { + // Remove digital trigger events. + if (input.type == TYPE_BUTTON && (input.id == 6 || input.id == 7)) { + mHoldingInput = false; + return true; + } } } + #endif - // Ignore negative pole for axes 2/5 only when triggers are being configured. - if (input.type == TYPE_AXIS && (input.id == 2 || input.id == 5)) { - if (strstr(GUI_INPUT_CONFIG_LIST[inputId].name, "Trigger") != nullptr) { + // Ignore negative poles when triggers are being configured. + // This is not a good solution as it's hardcoded to input 2 and 5 (Xbox controllers) and + // input 4 and 5 (Playstation Dual Shock controllers) instead of using a general detection + // for which type of axis input is used. This is also hardcoded to only work when configuring + // the trigger buttons, so it will not be possible to map trigger buttons to the shoulder + // button functions in ES for instance. It's probably necessary to update ES to use the SDL + // GameController API to fix this properly. + if (input.type == TYPE_AXIS && (input.id == 2 || input.id == 4 || input.id == 5)) { + if (std::string(GUI_INPUT_CONFIG_LIST[inputId].name).find("Trigger") != std::string::npos) { if (input.value == 1) mSkipAxis = true; else if (input.value == -1) @@ -410,11 +419,10 @@ bool GuiInputConfig::filterTrigger(Input input, InputConfig* config, int inputId return true; } } - #else - (void)input; - (void)config; - (void)inputId; - #endif + +// (void)input; +// (void)config; +// (void)inputId; return false; }