2020-09-21 17:17:34 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-05-26 16:34:33 +00:00
|
|
|
//
|
2020-09-21 17:17:34 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2020-06-21 12:25:28 +00:00
|
|
|
// GuiGameScraper.cpp
|
2020-05-26 16:34:33 +00:00
|
|
|
//
|
2020-06-21 12:25:28 +00:00
|
|
|
// Single game scraping user interface.
|
|
|
|
// This interface is triggered from GuiMetaDataEd.
|
|
|
|
// GuiScraperSearch is called from here.
|
2020-05-26 16:34:33 +00:00
|
|
|
//
|
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "guis/GuiGameScraper.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
#include "FileData.h"
|
|
|
|
#include "MameNames.h"
|
|
|
|
#include "SystemData.h"
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "components/ButtonComponent.h"
|
|
|
|
#include "components/MenuComponent.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
#include "components/TextComponent.h"
|
2020-06-07 18:09:02 +00:00
|
|
|
#include "views/ViewController.h"
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
GuiGameScraper::GuiGameScraper(Window* window,
|
2021-12-02 16:34:30 +00:00
|
|
|
ScraperSearchParams& params,
|
|
|
|
std::function<void(const ScraperSearchResult&)> doneFunc,
|
|
|
|
bool& savedMediaAndAborted)
|
2021-07-07 18:03:42 +00:00
|
|
|
: GuiComponent(window)
|
2021-09-18 07:53:26 +00:00
|
|
|
, mClose(false)
|
2021-10-15 18:58:40 +00:00
|
|
|
, mGrid(window, glm::ivec2{2, 6})
|
2021-07-07 18:03:42 +00:00
|
|
|
, mBox(window, ":/graphics/frame.svg")
|
|
|
|
, mSearchParams(params)
|
2021-12-02 16:34:30 +00:00
|
|
|
, mSavedMediaAndAborted(savedMediaAndAborted)
|
2014-06-25 16:29:58 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
addChild(&mBox);
|
|
|
|
addChild(&mGrid);
|
|
|
|
|
2021-01-06 20:29:23 +00:00
|
|
|
std::string scrapeName;
|
|
|
|
|
|
|
|
if (Settings::getInstance()->getBool("ScraperSearchMetadataName")) {
|
|
|
|
scrapeName = mSearchParams.game->getName();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (params.game->isArcadeGame() &&
|
2021-07-07 18:03:42 +00:00
|
|
|
Settings::getInstance()->getString("Scraper") == "thegamesdb")
|
2021-11-17 20:32:40 +00:00
|
|
|
scrapeName = Utils::FileSystem::getFileName(mSearchParams.game->getPath()) + " (" +
|
|
|
|
MameNames::getInstance().getCleanName(mSearchParams.game->getCleanName()) +
|
|
|
|
")";
|
2021-01-06 20:29:23 +00:00
|
|
|
else
|
|
|
|
scrapeName = Utils::FileSystem::getFileName(mSearchParams.game->getPath());
|
|
|
|
}
|
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
mGameName = std::make_shared<TextComponent>(
|
|
|
|
mWindow,
|
|
|
|
scrapeName +
|
2020-12-25 14:28:19 +00:00
|
|
|
((mSearchParams.game->getType() == FOLDER) ? " " + ViewController::FOLDER_CHAR : ""),
|
2021-10-15 18:58:40 +00:00
|
|
|
Font::get(FONT_SIZE_LARGE), 0x777777FF, ALIGN_CENTER);
|
|
|
|
mGameName->setColor(0x555555FF);
|
|
|
|
mGrid.setEntry(mGameName, glm::ivec2{0, 0}, false, true, glm::ivec2{2, 2});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
mSystemName = std::make_shared<TextComponent>(
|
|
|
|
mWindow, Utils::String::toUpper(mSearchParams.system->getFullName()),
|
|
|
|
Font::get(FONT_SIZE_SMALL), 0x888888FF, ALIGN_CENTER);
|
2021-10-15 18:58:40 +00:00
|
|
|
mGrid.setEntry(mSystemName, glm::ivec2{0, 2}, false, true, glm::ivec2{2, 1});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-10-15 18:58:40 +00:00
|
|
|
// Row 3 is a spacer.
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// GuiScraperSearch.
|
2021-07-07 18:03:42 +00:00
|
|
|
mSearch = std::make_shared<GuiScraperSearch>(window, GuiScraperSearch::NEVER_AUTO_ACCEPT, 1);
|
2021-10-15 18:58:40 +00:00
|
|
|
mGrid.setEntry(mSearch, glm::ivec2{0, 4}, true, true, glm::ivec2{2, 1});
|
|
|
|
|
|
|
|
mResultList = mSearch->getResultList();
|
|
|
|
|
|
|
|
// Set up scroll indicators.
|
|
|
|
mScrollUp = std::make_shared<ImageComponent>(mWindow);
|
|
|
|
mScrollDown = std::make_shared<ImageComponent>(mWindow);
|
|
|
|
mScrollIndicator =
|
|
|
|
std::make_shared<ScrollIndicatorComponent>(mResultList, mScrollUp, mScrollDown);
|
|
|
|
|
|
|
|
mScrollUp->setResize(0.0f, mGameName->getFont()->getLetterHeight() / 2.0f);
|
|
|
|
mScrollUp->setOrigin(0.0f, -0.35f);
|
|
|
|
|
|
|
|
mScrollDown->setResize(0.0f, mGameName->getFont()->getLetterHeight() / 2.0f);
|
|
|
|
mScrollDown->setOrigin(0.0f, 0.35f);
|
|
|
|
|
|
|
|
mGrid.setEntry(mScrollUp, glm::ivec2{1, 0}, false, false, glm::ivec2{1, 1});
|
|
|
|
mGrid.setEntry(mScrollDown, glm::ivec2{1, 1}, false, false, glm::ivec2{1, 1});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
// Buttons
|
2021-03-27 09:26:13 +00:00
|
|
|
std::vector<std::shared_ptr<ButtonComponent>> buttons;
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-07-07 18:03:42 +00:00
|
|
|
buttons.push_back(
|
|
|
|
std::make_shared<ButtonComponent>(mWindow, "REFINE SEARCH", "refine search", [&] {
|
2021-07-11 20:26:53 +00:00
|
|
|
// Refine the search, unless the result has already been accepted.
|
|
|
|
if (!mSearch->getAcceptedResult()) {
|
2021-10-15 18:58:40 +00:00
|
|
|
// Copy any search refine that may have been previously entered by opening
|
|
|
|
// the input screen using the "Y" button shortcut.
|
|
|
|
mSearchParams.nameOverride = mSearch->getNameOverride();
|
2021-07-11 20:26:53 +00:00
|
|
|
mSearch->openInputScreen(mSearchParams);
|
|
|
|
mGrid.resetCursor();
|
|
|
|
}
|
2021-07-07 18:03:42 +00:00
|
|
|
}));
|
|
|
|
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "cancel", [&] {
|
|
|
|
if (mSearch->getSavedNewMedia()) {
|
|
|
|
// If the user aborted the scraping but there was still some media downloaded,
|
|
|
|
// then force an unload of the textures for the game image and marquee, and make
|
|
|
|
// an update of the game entry. Otherwise the images would not get updated until
|
|
|
|
// the user scrolls up and down the gamelist.
|
|
|
|
TextureResource::manualUnload(mSearchParams.game->getImagePath(), false);
|
|
|
|
TextureResource::manualUnload(mSearchParams.game->getMarqueePath(), false);
|
|
|
|
ViewController::get()->onFileChanged(mSearchParams.game, true);
|
|
|
|
}
|
|
|
|
delete this;
|
2020-06-21 12:25:28 +00:00
|
|
|
}));
|
|
|
|
mButtonGrid = makeButtonGrid(mWindow, buttons);
|
|
|
|
|
2021-10-15 18:58:40 +00:00
|
|
|
mGrid.setEntry(mButtonGrid, glm::ivec2{0, 5}, true, false, glm::ivec2{2, 1});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
mSearch->setAcceptCallback([this, doneFunc](const ScraperSearchResult& result) {
|
2021-07-07 18:03:42 +00:00
|
|
|
doneFunc(result);
|
|
|
|
close();
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
mSearch->setCancelCallback([&] { delete this; });
|
2021-10-15 18:58:40 +00:00
|
|
|
mSearch->setRefineCallback([&] {
|
|
|
|
mScrollUp->setOpacity(0);
|
|
|
|
mScrollDown->setOpacity(0);
|
|
|
|
mResultList->resetScrollIndicatorStatus();
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-07-02 15:51:07 +00:00
|
|
|
// Limit the width of the GUI on ultrawide monitors. The 1.778 aspect ratio value is
|
|
|
|
// the 16:9 reference.
|
|
|
|
float aspectValue = 1.778f / Renderer::getScreenAspectRatio();
|
2021-08-17 18:55:29 +00:00
|
|
|
float width = glm::clamp(0.95f * aspectValue, 0.70f, 0.95f) * Renderer::getScreenWidth();
|
2021-07-02 15:51:07 +00:00
|
|
|
|
2021-10-15 18:58:40 +00:00
|
|
|
float height = (mGameName->getFont()->getLetterHeight() +
|
|
|
|
static_cast<float>(Renderer::getScreenHeight()) * 0.0637f) +
|
|
|
|
mSystemName->getFont()->getLetterHeight() +
|
|
|
|
static_cast<float>(Renderer::getScreenHeight()) * 0.04f +
|
|
|
|
mButtonGrid->getSize().y + Font::get(FONT_SIZE_MEDIUM)->getHeight() * 8.0f;
|
|
|
|
|
|
|
|
setSize(width, height);
|
2021-08-16 16:25:01 +00:00
|
|
|
setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f,
|
|
|
|
(Renderer::getScreenHeight() - mSize.y) / 2.0f);
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
mGrid.resetCursor();
|
|
|
|
mSearch->search(params); // Start the search.
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GuiGameScraper::onSizeChanged()
|
|
|
|
{
|
2021-10-15 18:58:40 +00:00
|
|
|
mGrid.setRowHeightPerc(
|
|
|
|
0, (mGameName->getFont()->getLetterHeight() + Renderer::getScreenHeight() * 0.0637f) /
|
|
|
|
mSize.y / 2.0f);
|
|
|
|
mGrid.setRowHeightPerc(
|
|
|
|
1, (mGameName->getFont()->getLetterHeight() + Renderer::getScreenHeight() * 0.0637f) /
|
|
|
|
mSize.y / 2.0f);
|
|
|
|
mGrid.setRowHeightPerc(2, mSystemName->getFont()->getLetterHeight() / mSize.y, false);
|
|
|
|
mGrid.setRowHeightPerc(3, 0.04f, false);
|
2021-11-05 19:31:24 +00:00
|
|
|
mGrid.setRowHeightPerc(4, (Font::get(FONT_SIZE_MEDIUM)->getHeight() * 8.0f) / mSize.y, false);
|
2021-10-15 18:58:40 +00:00
|
|
|
|
|
|
|
mGrid.setColWidthPerc(1, 0.04f);
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-11-05 19:31:24 +00:00
|
|
|
mGrid.setSize(glm::round(mSize));
|
2021-10-15 18:58:40 +00:00
|
|
|
mBox.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f});
|
|
|
|
|
|
|
|
// Add some extra margins to the game name.
|
|
|
|
const float newSizeX = mSize.x * 0.96f;
|
|
|
|
mGameName->setSize(newSizeX, mGameName->getSize().y);
|
|
|
|
mGameName->setPosition((mSize.x - newSizeX) / 2.0f, 0.0f);
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GuiGameScraper::input(InputConfig* config, Input input)
|
|
|
|
{
|
2020-07-13 18:58:25 +00:00
|
|
|
if (config->isMappedTo("b", input) && input.value) {
|
2021-02-01 17:52:49 +00:00
|
|
|
if (mSearch->getSavedNewMedia()) {
|
|
|
|
// If the user aborted the scraping but there was still some media downloaded,
|
2021-12-02 16:34:30 +00:00
|
|
|
// then flag to GuiMetaDataEd that the image and marquee textures need to be
|
|
|
|
// manually unloaded and that the gamelist needs to be reloaded. Otherwise the
|
|
|
|
// images would not get updated until the user scrolls up and down the gamelist.
|
|
|
|
mSavedMediaAndAborted = true;
|
2021-02-01 17:52:49 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
delete this;
|
|
|
|
return true;
|
|
|
|
}
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
return GuiComponent::input(config, input);
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GuiGameScraper::update(int deltaTime)
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
GuiComponent::update(deltaTime);
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-07-13 18:58:25 +00:00
|
|
|
if (mClose)
|
2020-06-21 12:25:28 +00:00
|
|
|
delete this;
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<HelpPrompt> GuiGameScraper::getHelpPrompts()
|
|
|
|
{
|
2021-07-02 16:02:39 +00:00
|
|
|
std::vector<HelpPrompt> prompts = mGrid.getHelpPrompts();
|
|
|
|
prompts.push_back(HelpPrompt("b", "back (cancel)"));
|
|
|
|
|
|
|
|
return prompts;
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
2020-06-07 18:09:02 +00:00
|
|
|
HelpStyle GuiGameScraper::getHelpStyle()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
HelpStyle style = HelpStyle();
|
|
|
|
style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
|
|
|
|
return style;
|
2020-06-07 18:09:02 +00:00
|
|
|
}
|
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
void GuiGameScraper::close()
|
|
|
|
{
|
2021-07-07 18:03:42 +00:00
|
|
|
// This will cause update() to close the GUI.
|
2020-06-21 12:25:28 +00:00
|
|
|
mClose = true;
|
2017-08-11 17:03:12 +00:00
|
|
|
}
|