// SPDX-License-Identifier: MIT // // EmulationStation Desktop Edition // HelpComponent.cpp // // Help information in icon and text pairs. // #include "components/HelpComponent.h" #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" #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). #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 { { "up/down", ":/help/dpad_updown.svg" }, { "left/right", ":/help/dpad_leftright.svg" }, { "up/down/left/right", ":/help/dpad_all.svg" }, { "a", ":/help/button_a.svg" }, { "b", ":/help/button_b.svg" }, { "x", ":/help/button_x.svg" }, { "y", ":/help/button_y.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) { } void HelpComponent::clearPrompts() { mPrompts.clear(); updateGrid(); } void HelpComponent::setPrompts(const std::vector& prompts) { mPrompts = prompts; updateGrid(); } void HelpComponent::setStyle(const HelpStyle& style) { mStyle = style; updateGrid(); } void HelpComponent::updateGrid() { if (!Settings::getInstance()->getBool("ShowHelpPrompts") || mPrompts.empty()) { mGrid.reset(); return; } std::shared_ptr& font = mStyle.font; mGrid = std::make_shared(mWindow, Vector2i(static_cast(mPrompts.size()) * 4, 1)); // [icon] [spacer1] [text] [spacer2] std::vector< std::shared_ptr > icons; std::vector< std::shared_ptr > labels; float width = 0; const float height = std::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->setColorShift(mStyle.iconColor); icon->setResize(0, height); icons.push_back(icon); auto lbl = std::make_shared(mWindow, Utils::String::toUpper(it->second), font, mStyle.textColor); labels.push_back(lbl); width += icon->getSize().x() + lbl->getSize().x() + ICON_TEXT_SPACING + ENTRY_SPACING; } mGrid->setSize(width, height); for (unsigned int i = 0; i < icons.size(); i++) { const int col = i*4; mGrid->setColWidthPerc(col, icons.at(i)->getSize().x() / width); mGrid->setColWidthPerc(col + 1, ICON_TEXT_SPACING / width); mGrid->setColWidthPerc(col + 2, labels.at(i)->getSize().x() / width); mGrid->setEntry(icons.at(i), Vector2i(col, 0), false, false); mGrid->setEntry(labels.at(i), Vector2i(col + 2, 0), false, false); } mGrid->setPosition(Vector3f(mStyle.position.x(), mStyle.position.y(), 0.0f)); //mGrid->setPosition(OFFSET_X, Renderer::getScreenHeight() - mGrid->getSize().y() - OFFSET_Y); mGrid->setOrigin(mStyle.origin); } std::shared_ptr HelpComponent::getIconTexture(const char* name) { auto it = mIconCache.find(name); if (it != mIconCache.cend()) return it->second; auto pathLookup = ICON_PATH_MAP.find(name); if (pathLookup == ICON_PATH_MAP.cend()) { LOG(LogError) << "Unknown help icon \"" << name << "\"!"; return nullptr; } if (!ResourceManager::getInstance()->fileExists(pathLookup->second)) { LOG(LogError) << "Help icon \"" << name << "\" - corresponding image file \"" << pathLookup->second << "\" misisng!"; return nullptr; } std::shared_ptr tex = TextureResource::get(pathLookup->second); mIconCache[std::string(name)] = tex; return tex; } void HelpComponent::setOpacity(unsigned char opacity) { GuiComponent::setOpacity(opacity); for (unsigned int i = 0; i < mGrid->getChildCount(); i++) mGrid->getChild(i)->setOpacity(opacity); } void HelpComponent::render(const Transform4x4f& parentTrans) { Transform4x4f trans = parentTrans * getTransform(); if (mGrid) mGrid->render(trans); }