From a9b4edd10420fb35679ee9aac3caa9eb8f35e6dd Mon Sep 17 00:00:00 2001 From: ewewukek Date: Thu, 11 Jan 2024 12:53:19 +0300 Subject: Make D-Pad behave like regular buttons --- src/input/inputmanager.cpp | 56 ++++++++++++++++++++++++++++--- src/input/joystick.cpp | 83 ++++++++++++++++++++++++++++++++-------------- src/input/joystick.h | 15 ++++++++- 3 files changed, 125 insertions(+), 29 deletions(-) diff --git a/src/input/inputmanager.cpp b/src/input/inputmanager.cpp index a379e0e86..0a113bd76 100644 --- a/src/input/inputmanager.cpp +++ b/src/input/inputmanager.cpp @@ -416,8 +416,31 @@ std::string InputManager::getKeyStringLong(const InputActionT index) const } else if (key.type == InputType::JOYSTICK) { - // TRANSLATORS: long joystick button name. must be short. - str = strprintf(_("JButton%d"), key.value + 1); + if (key.value < Joystick::MAX_BUTTONS) + { + // TRANSLATORS: joystick button name. must be short. + str = strprintf(_("JButton%d"), key.value + 1); + } + else if (key.value == Joystick::KEY_UP) + { + // TRANSLATORS: joystick up button. must be short. + str = _("JUp"); + } + else if (key.value == Joystick::KEY_DOWN) + { + // TRANSLATORS: joystick down button. must be short. + str = _("JDown"); + } + else if (key.value == Joystick::KEY_LEFT) + { + // TRANSLATORS: joystick left button. must be short. + str = _("JLeft"); + } + else if (key.value == Joystick::KEY_RIGHT) + { + // TRANSLATORS: joystick right button. must be short. + str = _("JRight"); + } } if (!str.empty()) { @@ -459,8 +482,31 @@ void InputManager::updateKeyString(const InputFunction &ki, } else if (key.type == InputType::JOYSTICK) { - // TRANSLATORS: short joystick button name. muse be very short - str = strprintf(_("JB%d"), key.value + 1); + if (key.value < Joystick::MAX_BUTTONS) + { + // TRANSLATORS: joystick button name. must be very short + str = strprintf(_("JB%d"), key.value + 1); + } + else if (key.value == Joystick::KEY_UP) + { + // TRANSLATORS: joystick up button. must be very short + str = _("JUp"); + } + else if (key.value == Joystick::KEY_DOWN) + { + // TRANSLATORS: joystick down button. must be very short + str = _("JDn"); + } + else if (key.value == Joystick::KEY_LEFT) + { + // TRANSLATORS: joystick left button. must be very short + str = _("JLt"); + } + else if (key.value == Joystick::KEY_RIGHT) + { + // TRANSLATORS: joystick right button. must be very short + str = _("JRt"); + } } if (!str.empty()) { @@ -650,6 +696,7 @@ bool InputManager::handleEvent(const SDL_Event &restrict event) restrict2 break; } case SDL_JOYBUTTONDOWN: + case SDL_JOYHATMOTION: { updateConditionMask(true); // joystick.handleActicateButton(event); @@ -724,6 +771,7 @@ bool InputManager::handleEvent(const SDL_Event &restrict event) restrict2 // break; case SDL_JOYBUTTONDOWN: + case SDL_JOYHATMOTION: if ((joystick != nullptr) && joystick->validate()) { if (triggerAction(joystick->getActionVector(event))) diff --git a/src/input/joystick.cpp b/src/input/joystick.cpp index 0ab6102c5..59087c2c7 100644 --- a/src/input/joystick.cpp +++ b/src/input/joystick.cpp @@ -47,6 +47,7 @@ bool Joystick::mInitialized = false; Joystick::Joystick(const int no) : mDirection(0), + mHatPosition(0), mJoystick(nullptr), mTolerance(0), mNumber(no >= joystickCount ? joystickCount : no), @@ -264,18 +265,19 @@ void Joystick::logic() logger->log("axis 4 pos: %d", SDL_JoystickGetAxis(mJoystick, 4)); #endif // DEBUG_JOYSTICK - if ((mDirection == 0U) && mHaveHats) + if (mHaveHats) { // reading only hat 0 const uint8_t hat = SDL_JoystickGetHat(mJoystick, 0); + mHatPosition = 0; if ((hat & SDL_HAT_RIGHT) != 0) - mDirection |= RIGHT; + mHatPosition |= RIGHT; else if ((hat & SDL_HAT_LEFT) != 0) - mDirection |= LEFT; + mHatPosition |= LEFT; if ((hat & SDL_HAT_UP) != 0) - mDirection |= UP; + mHatPosition |= UP; else if ((hat & SDL_HAT_DOWN) != 0) - mDirection |= DOWN; + mHatPosition |= DOWN; } // Buttons @@ -293,15 +295,30 @@ void Joystick::logic() } else { + mHatPosition = 0; for (int i = 0; i < mButtonsNumber; i++) mActiveButtons[i] = false; } BLOCK_END("Joystick::logic") } -bool Joystick::buttonPressed(const unsigned char no) const +bool Joystick::buttonPressed(const int no) const { - return (mEnabled && no < MAX_BUTTONS) ? mActiveButtons[no] : false; + if (!mEnabled) + return false; + if (no < 0) + return false; + if (no < MAX_BUTTONS) + return mActiveButtons[no]; + if (no == KEY_UP) + return (mHatPosition & UP) != 0; + if (no == KEY_DOWN) + return (mHatPosition & DOWN) != 0; + if (no == KEY_LEFT) + return (mHatPosition & LEFT) != 0; + if (no == KEY_RIGHT) + return (mHatPosition & RIGHT) != 0; + return false; } void Joystick::getNames(STD_VECTOR &names) @@ -320,18 +337,12 @@ void Joystick::update() KeysVector *Joystick::getActionVector(const SDL_Event &event) { const int i = getButtonFromEvent(event); - - if (i < 0 || i >= mButtonsNumber) - return nullptr; -// logger->log("button triggerAction: %d", i); - if (mKeyToAction.find(i) != mKeyToAction.end()) - return &mKeyToAction[i]; - return nullptr; + return getActionVectorByKey(i); } KeysVector *Joystick::getActionVectorByKey(const int i) { - if (i < 0 || i >= mButtonsNumber) + if (i < 0 || (i >= mButtonsNumber && i < MAX_BUTTONS) || i > KEY_LAST) return nullptr; // logger->log("button triggerAction: %d", i); if (mKeyToAction.find(i) != mKeyToAction.end()) @@ -341,9 +352,30 @@ KeysVector *Joystick::getActionVectorByKey(const int i) int Joystick::getButtonFromEvent(const SDL_Event &event) const { - if (event.jbutton.which != mNumber) - return -1; - return event.jbutton.button; + if (event.type == SDL_JOYBUTTONDOWN) + { + if (event.jbutton.which != mNumber) + return -1; + return event.jbutton.button; + } + if (event.type == SDL_JOYHATMOTION) + { + // reading only hat 0 + if (event.jhat.which != mNumber || event.jhat.hat != 0) + return -1; + const int value = event.jhat.value; + // SDL reports new hat position, not when d-pad button is pressed. + // because of that we have to compare it to previously known state. + if ((mHatPosition & UP) == 0 && (value & SDL_HAT_UP) != 0) + return KEY_UP; + if ((mHatPosition & DOWN) == 0 && (value & SDL_HAT_DOWN) != 0) + return KEY_DOWN; + if ((mHatPosition & LEFT) == 0 && (value & SDL_HAT_LEFT) != 0) + return KEY_LEFT; + if ((mHatPosition & RIGHT) == 0 && (value & SDL_HAT_RIGHT) != 0) + return KEY_RIGHT; + } + return -1; } bool Joystick::isActionActive(const InputActionT index) const @@ -357,12 +389,7 @@ bool Joystick::isActionActive(const InputActionT index) const const InputItem &val = key.values[i]; if (val.type != InputType::JOYSTICK) continue; - const int value = val.value; - if (value >= 0 && value < mButtonsNumber) - { - if (mActiveButtons[value]) - return true; - } + return buttonPressed(val.value); } return false; } @@ -388,6 +415,14 @@ void Joystick::handleRepeat(const int time) if (mActiveButtons[key]) repeat = true; } + if (key == KEY_UP && (mHatPosition & UP) != 0) + repeat = true; + if (key == KEY_DOWN && (mHatPosition & DOWN) != 0) + repeat = true; + if (key == KEY_LEFT && (mHatPosition & LEFT) != 0) + repeat = true; + if (key == KEY_RIGHT && (mHatPosition & RIGHT) != 0) + repeat = true; if (repeat) { int &keyTime = (*it).second; diff --git a/src/input/joystick.h b/src/input/joystick.h index 32fdddf2e..bddf520a2 100644 --- a/src/input/joystick.h +++ b/src/input/joystick.h @@ -51,6 +51,18 @@ class Joystick final MAX_BUTTONS = 64 }; + /** + * Additional "buttons" for hat 0 (d-pad). + */ + enum + { + KEY_UP = MAX_BUTTONS, + KEY_DOWN, + KEY_LEFT, + KEY_RIGHT, + KEY_LAST = KEY_RIGHT + }; + /** * Directions, to be used as bitmask values. */ @@ -107,7 +119,7 @@ class Joystick final */ void logic(); - bool buttonPressed(const unsigned char no) const A_WARN_UNUSED; + bool buttonPressed(const int no) const A_WARN_UNUSED; bool isUp() const noexcept2 A_WARN_UNUSED { return mEnabled && ((mDirection & UP) != 0); } @@ -149,6 +161,7 @@ class Joystick final protected: unsigned char mDirection; + unsigned char mHatPosition; bool mActiveButtons[MAX_BUTTONS]; SDL_Joystick *mJoystick; -- cgit v1.2.3-60-g2f50