From 44aa6b8698f999d6b5e09ea9314f8df254db9ffa Mon Sep 17 00:00:00 2001 From: Richard Eklycke Date: Sun, 21 Aug 2022 15:42:55 +0200 Subject: [PATCH] HelpComponent: Display different help icons depending on controller Before this commit, all buttons shown in the help component would use the SNES layout, which wouldn't match when having plugged in an Xbox or Sony Playstation controller. If there are different kinds of controllers plugged in, the input mapping shown will be of the last used or inserted. The intention here is to help solving #442, or at least most of it. --- es-core/src/InputManager.cpp | 19 ++++++- es-core/src/InputManager.h | 2 + es-core/src/components/HelpComponent.cpp | 70 ++++++++++++++++++++---- es-core/src/components/HelpComponent.h | 6 +- 4 files changed, 84 insertions(+), 13 deletions(-) diff --git a/es-core/src/InputManager.cpp b/es-core/src/InputManager.cpp index 4ef5c4ac04..f72e19fe2e 100644 --- a/es-core/src/InputManager.cpp +++ b/es-core/src/InputManager.cpp @@ -31,7 +31,7 @@ int SDL_USER_CECBUTTONUP = -1; InputManager* InputManager::mInstance = NULL; -InputManager::InputManager() : mKeyboardInputConfig(NULL) +InputManager::InputManager() : mKeyboardInputConfig(NULL), mLastUsedKeyboardOrController(DEVICE_KEYBOARD) { } @@ -110,6 +110,8 @@ void InputManager::addJoystickByDeviceIndex(int id) int numAxes = SDL_JoystickNumAxes(joy); mPrevAxisValues[joyId] = new int[numAxes]; std::fill(mPrevAxisValues[joyId], mPrevAxisValues[joyId] + numAxes, 0); //initialize array to 0 + + mLastUsedKeyboardOrController = joyId; } void InputManager::removeJoystickByJoystickID(SDL_JoystickID joyId) @@ -201,6 +203,9 @@ int InputManager::getButtonCountByDevice(SDL_JoystickID id) InputConfig* InputManager::getInputConfigByDevice(int device) { + if (device != DEVICE_CEC) + mLastUsedKeyboardOrController = device; + if(device == DEVICE_KEYBOARD) return mKeyboardInputConfig; else if(device == DEVICE_CEC) @@ -209,6 +214,18 @@ InputConfig* InputManager::getInputConfigByDevice(int device) return mInputConfigs[device]; } +InputConfig* InputManager::getInputConfigForLastUsedDevice() const +{ + if(mLastUsedKeyboardOrController == DEVICE_KEYBOARD) + return mKeyboardInputConfig; + + const auto it = mInputConfigs.find(mLastUsedKeyboardOrController); + if(it != mInputConfigs.end()) + return it->second; + + return nullptr; // Could happen if last used controller was unplugged +} + bool InputManager::parseEvent(const SDL_Event& ev, Window* window) { bool causedEvent = false; diff --git a/es-core/src/InputManager.h b/es-core/src/InputManager.h index 388358d217..d7f85b50d4 100644 --- a/es-core/src/InputManager.h +++ b/es-core/src/InputManager.h @@ -26,6 +26,7 @@ class InputManager std::map mInputConfigs; InputConfig* mKeyboardInputConfig; InputConfig* mCECInputConfig; + int mLastUsedKeyboardOrController; std::map mPrevAxisValues; @@ -56,6 +57,7 @@ class InputManager std::string getDeviceGUIDString(int deviceId); InputConfig* getInputConfigByDevice(int deviceId); + InputConfig* getInputConfigForLastUsedDevice() const; bool parseEvent(const SDL_Event& ev, Window* window); }; diff --git a/es-core/src/components/HelpComponent.cpp b/es-core/src/components/HelpComponent.cpp index 1d7ef55291..8bbb746b37 100644 --- a/es-core/src/components/HelpComponent.cpp +++ b/es-core/src/components/HelpComponent.cpp @@ -3,10 +3,10 @@ #include "components/ComponentGrid.h" #include "components/ImageComponent.h" #include "components/TextComponent.h" -#include "resources/TextureResource.h" #include "utils/StringUtil.h" #include "Log.h" #include "Settings.h" +#include "InputManager.h" #define OFFSET_X 12 // move the entire thing right by this amount (px) #define OFFSET_Y 12 // move the entire thing up by this amount (px) @@ -14,7 +14,7 @@ #define ICON_TEXT_SPACING 8 // space between [icon] and [text] (px) #define ENTRY_SPACING 16 // space between [text] and next [icon] (px) -static const std::map ICON_PATH_MAP { +static const std::map DEFAULT_ICON_PATH_MAP { { "up/down", ":/help/dpad_updown.svg" }, { "left/right", ":/help/dpad_leftright.svg" }, { "up/down/left/right", ":/help/dpad_all.svg" }, @@ -29,6 +29,36 @@ static const std::map ICON_PATH_MAP { { "select", ":/help/button_select.svg" } }; +static const std::map XBOX_ICON_PATH_MAP { + { "up/down", ":/help/dpad_updown.svg" }, + { "left/right", ":/help/dpad_leftright.svg" }, + { "up/down/left/right", ":/help/dpad_all.svg" }, + { "a", ":/help/button_b.svg" }, + { "b", ":/help/button_a.svg" }, + { "x", ":/help/button_y.svg" }, + { "y", ":/help/button_x.svg" }, + { "l", ":/help/button_l.svg" }, + { "r", ":/help/button_r.svg" }, + { "lr", ":/help/button_lr.svg" }, + { "start", ":/help/button_start.svg" }, + { "select", ":/help/button_select.svg" } +}; + +static const std::map PLAYSTATION_ICON_PATH_MAP { + { "up/down", ":/help/dpad_updown.svg" }, + { "left/right", ":/help/dpad_leftright.svg" }, + { "up/down/left/right", ":/help/dpad_all.svg" }, + { "a", ":/help/button_circle.svg" }, + { "b", ":/help/button_x.svg" }, + { "x", ":/help/button_triangle.svg" }, + { "y", ":/help/button_square.svg" }, + { "l", ":/help/button_l.svg" }, + { "r", ":/help/button_r.svg" }, + { "lr", ":/help/button_lr.svg" }, + { "start", ":/help/button_start.svg" }, + { "select", ":/help/button_select.svg" } +}; + HelpComponent::HelpComponent(Window* window) : GuiComponent(window) { } @@ -67,12 +97,14 @@ void HelpComponent::updateGrid() std::vector< std::shared_ptr > icons; std::vector< std::shared_ptr > labels; + const auto& iconPathMap = getIconPathMap(InputManager::getInstance()->getInputConfigForLastUsedDevice()); + float width = 0; const float height = Math::round(font->getLetterHeight() * 1.25f); for(auto it = mPrompts.cbegin(); it != mPrompts.cend(); it++) { auto icon = std::make_shared(mWindow); - icon->setImage(getIconTexture(it->first.c_str())); + icon->setImage(getIconTexture(it->first.c_str(), iconPathMap)); icon->setColorShift(mStyle.iconColor); icon->setResize(0, height); icons.push_back(icon); @@ -100,26 +132,42 @@ void HelpComponent::updateGrid() mGrid->setOrigin(mStyle.origin); } -std::shared_ptr HelpComponent::getIconTexture(const char* name) +const std::map& HelpComponent::getIconPathMap(InputConfig* inputConfig) { - auto it = mIconCache.find(name); - if(it != mIconCache.cend()) - return it->second; + if(!inputConfig) + return DEFAULT_ICON_PATH_MAP; + + const auto& deviceName = inputConfig->getDeviceName(); + if(strcasestr(deviceName.c_str(), "xbox")) + return XBOX_ICON_PATH_MAP; - auto pathLookup = ICON_PATH_MAP.find(name); - if(pathLookup == ICON_PATH_MAP.cend()) + if(strcasestr(deviceName.c_str(), "sony") || strcasestr(deviceName.c_str(), "playstation")) + return PLAYSTATION_ICON_PATH_MAP; + + return DEFAULT_ICON_PATH_MAP; +} + +std::shared_ptr HelpComponent::getIconTexture(const char* name, const std::map& iconPathMap) +{ + auto pathLookup = iconPathMap.find(name); + if(pathLookup == iconPathMap.cend()) { LOG(LogError) << "Unknown help icon \"" << name << "\"!"; return nullptr; } + + auto it = mIconCache.find(pathLookup->second); + if(it != mIconCache.cend()) + return it->second; + if(!ResourceManager::getInstance()->fileExists(pathLookup->second)) { - LOG(LogError) << "Help icon \"" << name << "\" - corresponding image file \"" << pathLookup->second << "\" misisng!"; + LOG(LogError) << "Help icon \"" << name << "\" - corresponding image file \"" << pathLookup->second << "\" missing!"; return nullptr; } std::shared_ptr tex = TextureResource::get(pathLookup->second); - mIconCache[std::string(name)] = tex; + mIconCache[std::string(pathLookup->second)] = tex; return tex; } diff --git a/es-core/src/components/HelpComponent.h b/es-core/src/components/HelpComponent.h index e9c5d2e07d..aae0d5838f 100644 --- a/es-core/src/components/HelpComponent.h +++ b/es-core/src/components/HelpComponent.h @@ -4,6 +4,9 @@ #include "GuiComponent.h" #include "HelpStyle.h" +#include "resources/TextureResource.h" + +#include class ComponentGrid; class ImageComponent; @@ -23,7 +26,8 @@ class HelpComponent : public GuiComponent void setStyle(const HelpStyle& style); private: - std::shared_ptr getIconTexture(const char* name); + const std::map& getIconPathMap(InputConfig* inputConfig); + std::shared_ptr getIconTexture(const char* name, const std::map& iconPathMap); std::map< std::string, std::shared_ptr > mIconCache; std::shared_ptr mGrid;