Expanded the help system to (hopefully) the whole application, removed the completely broken command line scraper and fixed some bugs related to the game collections.

This commit is contained in:
Leon Styhre 2020-06-09 20:03:31 +02:00
parent c5e70385dd
commit 4a38271f6a
31 changed files with 205 additions and 457 deletions

View file

@ -6,7 +6,6 @@ set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/FileSorts.h ${CMAKE_CURRENT_SOURCE_DIR}/src/FileSorts.h
${CMAKE_CURRENT_SOURCE_DIR}/src/MetaData.h ${CMAKE_CURRENT_SOURCE_DIR}/src/MetaData.h
${CMAKE_CURRENT_SOURCE_DIR}/src/PlatformId.h ${CMAKE_CURRENT_SOURCE_DIR}/src/PlatformId.h
${CMAKE_CURRENT_SOURCE_DIR}/src/ScraperCmdLine.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemData.h ${CMAKE_CURRENT_SOURCE_DIR}/src/SystemData.h
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.h ${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.h
@ -60,7 +59,6 @@ set(ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/MetaData.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/MetaData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/PlatformId.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/PlatformId.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ScraperCmdLine.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemData.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/SystemData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.cpp

View file

@ -354,12 +354,18 @@ void CollectionSystemManager::updateCollectionSystem(FileData* file, CollectionS
} }
else { else {
ViewController::get()->onFileChanged(rootFolder, FILE_SORTED); ViewController::get()->onFileChanged(rootFolder, FILE_SORTED);
// If it's a custom collection and the collections // If it's a custom collection and the setting to group the collections is
// are grouped, update the parent instead. // enabled, we may have to update the parent instead.
// However it may not necessarily be so if some collections are themed and
// some are not, so we always need to check whether a parent exists.
if (sysData.decl.isCustom && if (sysData.decl.isCustom &&
Settings::getInstance()->getBool("UseCustomCollectionsSystem")) { Settings::getInstance()->getBool("UseCustomCollectionsSystem")) {
ViewController::get()->onFileChanged( // In case of a returned null pointer, we know there is no parent.
rootFolder->getParent(), FILE_METADATA_CHANGED); if (rootFolder->getParent() == nullptr)
ViewController::get()->onFileChanged(rootFolder, FILE_METADATA_CHANGED);
else
ViewController::get()->onFileChanged(
rootFolder->getParent(), FILE_METADATA_CHANGED);
} }
} }
} }
@ -914,12 +920,14 @@ void CollectionSystemManager::addEnabledCollectionsToDisplayedSystems(
FileData* rootFolder = it->second.system->getRootFolder(); FileData* rootFolder = it->second.system->getRootFolder();
rootFolder->sort(getSortTypeFromString(rootFolder->getSortTypeString()), rootFolder->sort(getSortTypeFromString(rootFolder->getSortTypeString()),
Settings::getInstance()->getBool("FavFirstCustom")); Settings::getInstance()->getBool("FavFirstCustom"));
// Jump to the first row of the game list // Jump to the first row of the game list, assuming it's not empty.
IGameListView* gameList = ViewController::get()-> IGameListView* gameList = ViewController::get()->
getGameListView((it->second.system)).get(); getGameListView((it->second.system)).get();
FileData* firstRow = gameList->getCursor()-> if (!gameList->getCursor()->isPlaceHolder()) {
getParent()->getChildrenListToDisplay()[0]; FileData* firstRow = gameList->getCursor()->
gameList->setCursor(firstRow); getParent()->getChildrenListToDisplay().front();
gameList->setCursor(firstRow);
}
} }
} }
else { else {

View file

@ -1,290 +0,0 @@
#include "ScraperCmdLine.h"
#include "Log.h"
#include "platform.h"
#include "SystemData.h"
#include <iostream>
#include <signal.h>
#if defined(__linux__)
#include <unistd.h>
#elif defined(WIN32)
#include <Windows.h>
#endif
std::ostream& out = std::cout;
void handle_interrupt_signal(int /*p*/)
{
sleep(50);
LOG(LogInfo) << "Interrupt received during scrape...";
SystemData::deleteSystems();
exit(1);
}
int run_scraper_cmdline()
{
out << "EmulationStation scraper\n";
out << "========================\n";
out << "\n";
signal(SIGINT, handle_interrupt_signal);
//==================================================================================
//filter
//==================================================================================
enum FilterChoice
{
FILTER_MISSING_IMAGES,
FILTER_ALL
};
int filter_choice;
do {
out << "Select filter for games to be scraped:\n";
out << FILTER_MISSING_IMAGES << " - games missing images\n";
out << FILTER_ALL << " - all games period, can overwrite existing metadata\n";
std::cin >> filter_choice;
std::cin.ignore(1, '\n'); //skip the unconsumed newline
} while(filter_choice < FILTER_MISSING_IMAGES || filter_choice > FILTER_ALL);
out << "\n";
//==================================================================================
//platforms
//==================================================================================
std::vector<SystemData*> systems;
out << "You can scrape only specific platforms, or scrape all of them.\n";
out << "Would you like to scrape all platforms? (y/n)\n";
std::string system_choice;
std::getline(std::cin, system_choice);
if(system_choice == "y" || system_choice == "Y")
{
out << "Will scrape all platforms.\n";
for(auto i = SystemData::sSystemVector.cbegin(); i != SystemData::sSystemVector.cend(); i++)
{
out << " " << (*i)->getName() << " (" << (*i)->getGameCount() << " games)\n";
systems.push_back(*i);
}
}else{
std::string sys_name;
out << "Enter the names of the platforms you would like to scrape, one at a time.\n";
out << "Type nothing and press enter when you are ready to continue.\n";
do {
for(auto i = SystemData::sSystemVector.cbegin(); i != SystemData::sSystemVector.cend(); i++)
{
if(std::find(systems.cbegin(), systems.cend(), (*i)) != systems.cend())
out << " C ";
else
out << " ";
out << "\"" << (*i)->getName() << "\" (" << (*i)->getGameCount() << " games)\n";
}
std::getline(std::cin, sys_name);
if(sys_name.empty())
break;
bool found = false;
for(auto i = SystemData::sSystemVector.cbegin(); i != SystemData::sSystemVector.cend(); i++)
{
if((*i)->getName() == sys_name)
{
systems.push_back(*i);
found = true;
break;
}
}
if(!found)
out << "System not found.\n";
} while(true);
}
//==================================================================================
//manual mode
//==================================================================================
out << "\n";
out << "You can let the scraper try to automatically choose the best result, or\n";
out << "you can manually approve each result. This \"manual mode\" is much more accurate.\n";
out << "It is highly recommended you use manual mode unless you have a very large collection.\n";
out << "Scrape in manual mode? (y/n)\n";
std::string manual_mode_str;
std::getline(std::cin, manual_mode_str);
bool manual_mode = false;
if(manual_mode_str == "y" || manual_mode_str == "Y")
{
manual_mode = true;
out << "Scraping in manual mode!\n";
}else{
out << "Scraping in automatic mode!\n";
}
//==================================================================================
//scraping
//==================================================================================
out << "\n";
out << "Alright, let's do this thing!\n";
out << "=============================\n";
/*
std::shared_ptr<Scraper> scraper = Settings::getInstance()->getScraper();
for(auto sysIt = systems.cbegin(); sysIt != systems.cend(); sysIt++)
{
std::vector<FileData*> files = (*sysIt)->getRootFolder()->getFilesRecursive(GAME);
ScraperSearchParams params;
params.system = (*sysIt);
for(auto gameIt = files.cbegin(); gameIt != files.cend(); gameIt++)
{
params.nameOverride = "";
params.game = *gameIt;
//print original search term
out << getCleanFileName(params.game->getPath()) << "...\n";
//need to take into account filter_choice
if(filter_choice == FILTER_MISSING_IMAGES)
{
if(!params.game->metadata.get("image").empty()) //maybe should also check if the image file exists/is a URL
{
out << " Skipping, metadata \"image\" entry is not empty.\n";
continue;
}
}
//actually get some results
do {
std::vector<MetaDataList> mdls = scraper->getResults(params);
//no results
if(mdls.size() == 0)
{
if(manual_mode)
{
//in manual mode let the user enter a custom search
out << " NO RESULTS FOUND! Enter a new name to search for, or nothing to skip.\n";
std::getline(std::cin, params.nameOverride);
if(params.nameOverride.empty())
{
out << " Skipping...\n";
break;
}
continue;
}else{
out << " NO RESULTS FOUND! Skipping...\n";
break;
}
}
//some results
if(manual_mode)
{
//print list of choices
for(unsigned int i = 0; i < mdls.size(); i++)
{
out << " " << i << " - " << mdls.at(i).get("name") << "\n";
}
int choice = -1;
std::string choice_str;
out << "Your choice: ";
std::getline(std::cin, choice_str);
std::stringstream choice_buff(choice_str); //convert to int
choice_buff >> choice;
if(choice >= 0 && choice < (int)mdls.size())
{
params.game->metadata = mdls.at(choice);
break;
}else{
out << "Invalid choice.\n";
continue;
}
}else{
//automatic mode
//always choose the first choice
out << " name -> " << mdls.at(0).get("name") << "\n";
params.game->metadata = mdls.at(0);
break;
}
} while(true);
out << "===================\n";
}
}
out << "\n\n";
out << "Downloading boxart...\n";
for(auto sysIt = systems.cbegin(); sysIt != systems.cend(); sysIt++)
{
std::vector<FileData*> files = (*sysIt)->getRootFolder()->getFilesRecursive(GAME);
for(auto gameIt = files.cbegin(); gameIt != files.cend(); gameIt++)
{
FileData* game = *gameIt;
const std::vector<MetaDataDecl>& mdd = game->metadata.getMDD();
for(auto i = mdd.cbegin(); i != mdd.cend(); i++)
{
std::string key = i->key;
std::string url = game->metadata.get(key);
if(i->type == MD_IMAGE_PATH && HttpReq::isUrl(url))
{
std::string urlShort = url.substr(0, url.length() > 35 ? 35 : url.length());
if(url.length() != urlShort.length()) urlShort += "...";
out << " " << game->metadata.get("name") << " [from: " << urlShort << "]...\n";
ScraperSearchParams p;
p.game = game;
p.system = *sysIt;
game->metadata.set(key, downloadImage(url, getSaveAsPath(p, key, url)));
if(game->metadata.get(key).empty())
{
out << " FAILED! Skipping.\n";
game->metadata.set(key, url); //result URL to what it was if download failed, retry some other time
}
}
}
}
}
out << "\n\n";
out << "==============================\n";
out << "SCRAPE COMPLETE!\n";
out << "==============================\n";
*/
out << "\n\n";
out << "ACTUALLY THIS IS STILL TODO\n";
return 0;
}

View file

@ -1,7 +0,0 @@
#pragma once
#ifndef ES_APP_SCRAPER_CMD_LINE_H
#define ES_APP_SCRAPER_CMD_LINE_H
int run_scraper_cmdline();
#endif // ES_APP_SCRAPER_CMD_LINE_H

View file

@ -56,6 +56,10 @@ void GuiCollectionSystemsOptions::initializeMenu()
ComponentListRow row; ComponentListRow row;
row.addElement(std::make_shared<TextComponent>(mWindow, "CREATE NEW CUSTOM COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); row.addElement(std::make_shared<TextComponent>(mWindow, "CREATE NEW CUSTOM COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
auto bracket = std::make_shared<ImageComponent>(mWindow);
bracket->setImage(":/arrow.svg");
bracket->setResize(Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()));
row.addElement(bracket, false);
auto createCustomCollection = [this](const std::string& newVal) { auto createCustomCollection = [this](const std::string& newVal) {
std::string name = newVal; std::string name = newVal;
// we need to store the first Gui and remove it, as it'll be deleted by the actual Gui // we need to store the first Gui and remove it, as it'll be deleted by the actual Gui
@ -65,7 +69,7 @@ void GuiCollectionSystemsOptions::initializeMenu()
createCollection(name); createCollection(name);
}; };
row.makeAcceptInputHandler([this, createCustomCollection] { row.makeAcceptInputHandler([this, createCustomCollection] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "New Collection Name", "", createCustomCollection, false)); mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "New Collection Name", "", createCustomCollection, false, "SAVE"));
}); });
mMenu.addRow(row); mMenu.addRow(row);
@ -220,6 +224,7 @@ bool GuiCollectionSystemsOptions::input(InputConfig* config, Input input)
std::vector<HelpPrompt> GuiCollectionSystemsOptions::getHelpPrompts() std::vector<HelpPrompt> GuiCollectionSystemsOptions::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts(); std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("a", "select"));
prompts.push_back(HelpPrompt("b", "back")); prompts.push_back(HelpPrompt("b", "back"));
return prompts; return prompts;
} }

View file

@ -54,7 +54,8 @@ GuiGameScraper::GuiGameScraper(
// Buttons // Buttons
std::vector< std::shared_ptr<ButtonComponent> > buttons; std::vector< std::shared_ptr<ButtonComponent> > buttons;
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "INPUT", "search", [&] { buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "REFINE SEARCH",
"refine search", [&] {
mSearch->openInputScreen(mSearchParams); mSearch->openInputScreen(mSearchParams);
mGrid.resetCursor(); mGrid.resetCursor();
})); }));

View file

@ -126,6 +126,7 @@ std::vector<HelpPrompt> GuiGamelistFilter::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts(); std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("b", "back")); prompts.push_back(HelpPrompt("b", "back"));
prompts.push_back(HelpPrompt("a", "select"));
return prompts; return prompts;
} }

View file

@ -29,7 +29,8 @@ GuiGamelistOptions::GuiGamelistOptions(
mSystem(system), mSystem(system),
mMenu(window, "OPTIONS"), mMenu(window, "OPTIONS"),
fromPlaceholder(false), fromPlaceholder(false),
mFiltersChanged(false) mFiltersChanged(false),
mCancelled(false)
{ {
addChild(&mMenu); addChild(&mMenu);
@ -140,8 +141,8 @@ GuiGamelistOptions::GuiGamelistOptions(
// Show filtered menu. // Show filtered menu.
if (system->getName() != "recent" && !Settings::getInstance()->getBool("ForceDisableFilters")) { if (system->getName() != "recent" && !Settings::getInstance()->getBool("ForceDisableFilters")) {
row.elements.clear(); row.elements.clear();
row.addElement(std::make_shared<TextComponent>( row.addElement(std::make_shared<TextComponent>
mWindow, "FILTER GAMELIST", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); (mWindow, "FILTER GAMELIST", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
row.addElement(makeArrow(mWindow), false); row.addElement(makeArrow(mWindow), false);
row.makeAcceptInputHandler(std::bind(&GuiGamelistOptions::openGamelistFilter, this)); row.makeAcceptInputHandler(std::bind(&GuiGamelistOptions::openGamelistFilter, this));
mMenu.addRow(row); mMenu.addRow(row);
@ -192,6 +193,9 @@ GuiGamelistOptions::GuiGamelistOptions(
GuiGamelistOptions::~GuiGamelistOptions() GuiGamelistOptions::~GuiGamelistOptions()
{ {
if (mCancelled)
return;
if (!fromPlaceholder) { if (!fromPlaceholder) {
FileData* root = mSystem->getRootFolder(); FileData* root = mSystem->getRootFolder();
@ -316,8 +320,11 @@ void GuiGamelistOptions::jumpToFirstRow()
bool GuiGamelistOptions::input(InputConfig* config, Input input) bool GuiGamelistOptions::input(InputConfig* config, Input input)
{ {
if ((config->isMappedTo("b", input) || if (input.value != 0 && config->isMappedTo("select", input))
config->isMappedTo("select", input)) && input.value) { mCancelled = true;
if (input.value != 0 && (config->isMappedTo("b", input) ||
config->isMappedTo("select", input))) {
delete this; delete this;
return true; return true;
} }
@ -335,7 +342,9 @@ HelpStyle GuiGamelistOptions::getHelpStyle()
std::vector<HelpPrompt> GuiGamelistOptions::getHelpPrompts() std::vector<HelpPrompt> GuiGamelistOptions::getHelpPrompts()
{ {
auto prompts = mMenu.getHelpPrompts(); auto prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("b", "close")); prompts.push_back(HelpPrompt("a", "select"));
prompts.push_back(HelpPrompt("b", "close (apply)"));
prompts.push_back(HelpPrompt("select", "close (cancel)"));
return prompts; return prompts;
} }

View file

@ -55,6 +55,7 @@ private:
bool mFavoritesSorting; bool mFavoritesSorting;
bool fromPlaceholder; bool fromPlaceholder;
bool mFiltersChanged; bool mFiltersChanged;
bool mCancelled;
}; };
#endif // ES_APP_GUIS_GUI_GAME_LIST_OPTIONS_H #endif // ES_APP_GUIS_GUI_GAME_LIST_OPTIONS_H

View file

@ -562,8 +562,7 @@ void GuiMenu::openQuitMenu()
if (Settings::getInstance()->getBool("ShowExit")) { if (Settings::getInstance()->getBool("ShowExit")) {
row.makeAcceptInputHandler([window, this] { row.makeAcceptInputHandler([window, this] {
window->pushGui(new GuiMsgBox(window, this->getHelpStyle(), window->pushGui(new GuiMsgBox(window, this->getHelpStyle(),
"REALLY QUIT?", "YES", "REALLY QUIT?", "YES", [] {
[] {
Scripting::fireEvent("quit"); Scripting::fireEvent("quit");
quitES(); quitES();
}, "NO", nullptr)); }, "NO", nullptr));
@ -651,14 +650,30 @@ void GuiMenu::addEntry(const char* name, unsigned int color,
mMenu.addRow(row); mMenu.addRow(row);
} }
void GuiMenu::close(bool closeAllWindows)
{
std::function<void()> closeFunc;
if (!closeAllWindows) {
closeFunc = [this] { delete this; };
}
else {
Window* window = mWindow;
closeFunc = [window, this] {
while (window->peekGui() != ViewController::get())
delete window->peekGui();
};
}
closeFunc();
}
bool GuiMenu::input(InputConfig* config, Input input) bool GuiMenu::input(InputConfig* config, Input input)
{ {
if (GuiComponent::input(config, input)) if (GuiComponent::input(config, input))
return true; return true;
if ((config->isMappedTo("b", input) || config->isMappedTo("start", input)) && const bool isStart = config->isMappedTo("start", input);
input.value != 0) { if (input.value != 0 && (config->isMappedTo("b", input) || isStart)) {
delete this; close(isStart);
return true; return true;
} }
@ -670,7 +685,8 @@ std::vector<HelpPrompt> GuiMenu::getHelpPrompts()
std::vector<HelpPrompt> prompts; std::vector<HelpPrompt> prompts;
prompts.push_back(HelpPrompt("up/down", "choose")); prompts.push_back(HelpPrompt("up/down", "choose"));
prompts.push_back(HelpPrompt("a", "select")); prompts.push_back(HelpPrompt("a", "select"));
prompts.push_back(HelpPrompt("start", "close")); prompts.push_back(HelpPrompt("b", "close menu"));
prompts.push_back(HelpPrompt("start", "close menu"));
return prompts; return prompts;
} }

View file

@ -23,6 +23,7 @@ public:
HelpStyle getHelpStyle() override; HelpStyle getHelpStyle() override;
private: private:
void close(bool closeAllWindows);
void addEntry(const char* name, unsigned int color, void addEntry(const char* name, unsigned int color,
bool add_arrow, const std::function<void()>& func); bool add_arrow, const std::function<void()>& func);
void addVersionInfo(); void addVersionInfo();

View file

@ -88,6 +88,9 @@ GuiMetaDataEd::GuiMetaDataEd(
// Create ed and add it (and any related components) to mMenu. // Create ed and add it (and any related components) to mMenu.
// ed's value will be set below. // ed's value will be set below.
// It's very important to put the element with the help prompt as the last row
// entry instead of for instance the spacer. That is so because ComponentList
// always looks for the help prompt at the back of the element stack.
ComponentListRow row; ComponentListRow row;
auto lbl = std::make_shared<TextComponent>(mWindow, auto lbl = std::make_shared<TextComponent>(mWindow,
Utils::String::toUpper(iter->displayName), Font::get(FONT_SIZE_SMALL), 0x777777FF); Utils::String::toUpper(iter->displayName), Font::get(FONT_SIZE_SMALL), 0x777777FF);
@ -100,28 +103,28 @@ GuiMetaDataEd::GuiMetaDataEd(
break; break;
} }
case MD_RATING: { case MD_RATING: {
auto spacer = std::make_shared<GuiComponent>(mWindow);
spacer->setSize(Renderer::getScreenWidth() * 0.0025f, 0);
row.addElement(spacer, false);
ed = std::make_shared<RatingComponent>(window); ed = std::make_shared<RatingComponent>(window);
const float height = lbl->getSize().y() * 0.71f; const float height = lbl->getSize().y() * 0.71f;
ed->setSize(0, height); ed->setSize(0, height);
row.addElement(ed, false, true); row.addElement(ed, false, true);
auto spacer = std::make_shared<GuiComponent>(mWindow);
spacer->setSize(Renderer::getScreenWidth() * 0.0025f, 0);
row.addElement(spacer, false);
// Pass input to the actual RatingComponent instead of the spacer. // Pass input to the actual RatingComponent instead of the spacer.
row.input_handler = std::bind(&GuiComponent::input, row.input_handler = std::bind(&GuiComponent::input,
ed.get(), std::placeholders::_1, std::placeholders::_2); ed.get(), std::placeholders::_1, std::placeholders::_2);
break; break;
} }
case MD_DATE: { case MD_DATE: {
ed = std::make_shared<DateTimeEditComponent>(window);
row.addElement(ed, false);
auto spacer = std::make_shared<GuiComponent>(mWindow); auto spacer = std::make_shared<GuiComponent>(mWindow);
spacer->setSize(Renderer::getScreenWidth() * 0.0025f, 0); spacer->setSize(Renderer::getScreenWidth() * 0.0025f, 0);
row.addElement(spacer, false); row.addElement(spacer, false);
ed = std::make_shared<DateTimeEditComponent>(window);
row.addElement(ed, false);
// Pass input to the actual DateTimeEditComponent instead of the spacer. // Pass input to the actual DateTimeEditComponent instead of the spacer.
row.input_handler = std::bind(&GuiComponent::input, ed.get(), row.input_handler = std::bind(&GuiComponent::input, ed.get(),
std::placeholders::_1, std::placeholders::_2); std::placeholders::_1, std::placeholders::_2);
@ -160,7 +163,7 @@ GuiMetaDataEd::GuiMetaDataEd(
defaultLaunchString, ed, updateVal, multiLine] { defaultLaunchString, ed, updateVal, multiLine] {
mWindow->pushGui(new GuiComplexTextEditPopup(mWindow, getHelpStyle(), mWindow->pushGui(new GuiComplexTextEditPopup(mWindow, getHelpStyle(),
title, staticTextString, defaultLaunchString, ed->getValue(), title, staticTextString, defaultLaunchString, ed->getValue(),
updateVal, multiLine)); updateVal, multiLine, "SAVE"));
}); });
break; break;
} }
@ -187,7 +190,7 @@ GuiMetaDataEd::GuiMetaDataEd(
auto updateVal = [ed](const std::string& newVal) { ed->setValue(newVal); }; auto updateVal = [ed](const std::string& newVal) { ed->setValue(newVal); };
row.makeAcceptInputHandler([this, title, ed, updateVal, multiLine] { row.makeAcceptInputHandler([this, title, ed, updateVal, multiLine] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), title, mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), title,
ed->getValue(), updateVal, multiLine)); ed->getValue(), updateVal, multiLine, "SAVE"));
}); });
break; break;
} }
@ -205,9 +208,9 @@ GuiMetaDataEd::GuiMetaDataEd(
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "SCRAPE", "scrape", buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "SCRAPE", "scrape",
std::bind(&GuiMetaDataEd::fetch, this))); std::bind(&GuiMetaDataEd::fetch, this)));
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "SAVE", "save", buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "SAVE", "save metadata",
[&] { save(); delete this; })); [&] { save(); delete this; }));
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "cancel", buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "cancel changes",
[&] { delete this; })); [&] { delete this; }));
if (mDeleteFunc) { if (mDeleteFunc) {
@ -217,7 +220,7 @@ GuiMetaDataEd::GuiMetaDataEd(
"THIS WILL DELETE THE ACTUAL GAME FILE(S)!\nARE YOU SURE?", "THIS WILL DELETE THE ACTUAL GAME FILE(S)!\nARE YOU SURE?",
"YES", deleteFileAndSelf, "NO", nullptr)); }; "YES", deleteFileAndSelf, "NO", nullptr)); };
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE", buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "DELETE",
"delete", deleteBtnFunc)); "delete game", deleteBtnFunc));
} }
mButtons = makeButtonGrid(mWindow, buttons); mButtons = makeButtonGrid(mWindow, buttons);
@ -292,16 +295,13 @@ void GuiMetaDataEd::fetchDone(const ScraperSearchResult& result)
// Update the list with the scraped metadata values. // Update the list with the scraped metadata values.
for (unsigned int i = 0; i < mEditors.size(); i++) { for (unsigned int i = 0; i < mEditors.size(); i++) {
const std::string& key = mMetaDataDecl.at(i).key; const std::string& key = mMetaDataDecl.at(i).key;
// if (mEditors.at(i)->getValue() != metadata->get(key)) {
// mEditors.at(i)->setOpacity(150);
// }
mEditors.at(i)->setValue(metadata->get(key)); mEditors.at(i)->setValue(metadata->get(key));
} }
delete metadata; delete metadata;
} }
void GuiMetaDataEd::close(bool closeAllWindows) void GuiMetaDataEd::close()
{ {
// Find out if the user made any changes. // Find out if the user made any changes.
bool dirty = mMetadataUpdated; bool dirty = mMetadataUpdated;
@ -311,9 +311,7 @@ void GuiMetaDataEd::close(bool closeAllWindows)
std::string mEditorsValue = mEditors.at(i)->getValue(); std::string mEditorsValue = mEditors.at(i)->getValue();
// Incredibly ugly workaround to avoid the "SAVE CHANGES?" window for games // Incredibly ugly workaround to avoid the "SAVE CHANGES?" window for games
// with mising metadata for rating and release date. // with missing release date metadata.
if (key == "rating" && (mMetaDataValue == "" || mMetaDataValue == "0.000000"))
mMetaDataValue = "0";
if (key == "releasedate" && (mMetaDataValue == "" || mMetaDataValue == "not-a-date-time")) if (key == "releasedate" && (mMetaDataValue == "" || mMetaDataValue == "not-a-date-time"))
mMetaDataValue = "19700101T010000"; mMetaDataValue = "19700101T010000";
@ -323,17 +321,21 @@ void GuiMetaDataEd::close(bool closeAllWindows)
} }
} }
// Keep code for potential future use.
// std::function<void()> closeFunc;
// if (!closeAllWindows) {
// closeFunc = [this] { delete this; };
// }
// else {
// Window* window = mWindow;
// closeFunc = [window, this] {
// while (window->peekGui() != ViewController::get())
// delete window->peekGui();
// };
// }
std::function<void()> closeFunc; std::function<void()> closeFunc;
if (!closeAllWindows) {
closeFunc = [this] { delete this; }; closeFunc = [this] { delete this; };
}
else {
Window* window = mWindow;
closeFunc = [window, this] {
while (window->peekGui() != ViewController::get())
delete window->peekGui();
};
}
if (dirty) if (dirty)
{ {
@ -354,9 +356,8 @@ bool GuiMetaDataEd::input(InputConfig* config, Input input)
if (GuiComponent::input(config, input)) if (GuiComponent::input(config, input))
return true; return true;
const bool isStart = config->isMappedTo("start", input); if (input.value != 0 && (config->isMappedTo("b", input))) {
if (input.value != 0 && (config->isMappedTo("b", input) || isStart)) { close();
close(isStart);
return true; return true;
} }
@ -367,7 +368,6 @@ std::vector<HelpPrompt> GuiMetaDataEd::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts = mGrid.getHelpPrompts(); std::vector<HelpPrompt> prompts = mGrid.getHelpPrompts();
prompts.push_back(HelpPrompt("b", "back")); prompts.push_back(HelpPrompt("b", "back"));
prompts.push_back(HelpPrompt("start", "close"));
return prompts; return prompts;
} }

View file

@ -41,7 +41,7 @@ private:
void save(); void save();
void fetch(); void fetch();
void fetchDone(const ScraperSearchResult& result); void fetchDone(const ScraperSearchResult& result);
void close(bool closeAllWindows); void close();
NinePatchComponent mBackground; NinePatchComponent mBackground;
ComponentGrid mGrid; ComponentGrid mGrid;

View file

@ -242,8 +242,6 @@ void GuiScraperMenu::start()
"NO GAMES TO SCRAPE")); "NO GAMES TO SCRAPE"));
} }
else { else {
bool testbool = Settings::getInstance()->getBool("ScraperInteractive");
GuiScraperMulti* gsm = new GuiScraperMulti(mWindow, searches, GuiScraperMulti* gsm = new GuiScraperMulti(mWindow, searches,
Settings::getInstance()->getBool("ScraperInteractive")); Settings::getInstance()->getBool("ScraperInteractive"));
mWindow->pushGui(gsm); mWindow->pushGui(gsm);
@ -293,7 +291,7 @@ bool GuiScraperMenu::input(InputConfig* config, Input input)
if (GuiComponent::input(config, input)) if (GuiComponent::input(config, input))
return true; return true;
if ((config->isMappedTo("b", input) || config->isMappedTo("start", input)) && if (config->isMappedTo("b", input) &&
input.value != 0) { input.value != 0) {
delete this; delete this;
return true; return true;
@ -304,10 +302,8 @@ bool GuiScraperMenu::input(InputConfig* config, Input input)
std::vector<HelpPrompt> GuiScraperMenu::getHelpPrompts() std::vector<HelpPrompt> GuiScraperMenu::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts; std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("up/down", "choose")); prompts.push_back(HelpPrompt("b", "back"));
prompts.push_back(HelpPrompt("a", "select"));
prompts.push_back(HelpPrompt("start", "close"));
return prompts; return prompts;
} }

View file

@ -68,12 +68,13 @@ GuiScraperMulti::GuiScraperMulti(
std::vector< std::shared_ptr<ButtonComponent> > buttons; std::vector< std::shared_ptr<ButtonComponent> > buttons;
if (approveResults) { if (approveResults) {
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "INPUT", "search", [&] { buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "REFINE SEARCH",
"refine search", [&] {
mSearchComp->openInputScreen(mSearchQueue.front()); mSearchComp->openInputScreen(mSearchQueue.front());
mGrid.resetCursor(); mGrid.resetCursor();
})); }));
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "SKIP", "skip", [&] { buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "SKIP", "skip game", [&] {
skip(); skip();
mGrid.resetCursor(); mGrid.resetCursor();
})); }));

View file

@ -285,6 +285,7 @@ void GuiScraperSearch::onSearchDone(const std::vector<ScraperSearchResult>& resu
"FINISH", mSkipCallback)); "FINISH", mSkipCallback));
} }
else { else {
mFoundGame = false;
ComponentListRow row; ComponentListRow row;
row.addElement(std::make_shared<TextComponent>(mWindow, "NO GAMES FOUND - SKIP", row.addElement(std::make_shared<TextComponent>(mWindow, "NO GAMES FOUND - SKIP",
font, color), true); font, color), true);
@ -297,6 +298,7 @@ void GuiScraperSearch::onSearchDone(const std::vector<ScraperSearchResult>& resu
} }
} }
else { else {
mFoundGame = true;
ComponentListRow row; ComponentListRow row;
for (size_t i = 0; i < results.size(); i++) { for (size_t i = 0; i < results.size(); i++) {
row.elements.clear(); row.elements.clear();
@ -587,7 +589,7 @@ void GuiScraperSearch::openInputScreen(ScraperSearchParams& params)
if (params.system->hasPlatformId(PlatformIds::ARCADE) || if (params.system->hasPlatformId(PlatformIds::ARCADE) ||
params.system->hasPlatformId(PlatformIds::NEOGEO)) { params.system->hasPlatformId(PlatformIds::NEOGEO)) {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "SEARCH FOR", mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "REFINE SEARCH",
// Initial value is last search if there was one, otherwise the clean path name. // Initial value is last search if there was one, otherwise the clean path name.
// If it's a MAME or Neo Geo game, expand the game name accordingly. // If it's a MAME or Neo Geo game, expand the game name accordingly.
params.nameOverride.empty() ? params.nameOverride.empty() ?
@ -596,7 +598,7 @@ void GuiScraperSearch::openInputScreen(ScraperSearchParams& params)
searchForFunc, false, "SEARCH", "APPLY CHANGES?")); searchForFunc, false, "SEARCH", "APPLY CHANGES?"));
} }
else { else {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "SEARCH FOR", mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "REFINE SEARCH",
// Initial value is last search if there was one, otherwise the clean path name. // Initial value is last search if there was one, otherwise the clean path name.
params.nameOverride.empty() ? params.game->getCleanName() : params.nameOverride, params.nameOverride.empty() ? params.game->getCleanName() : params.nameOverride,
searchForFunc, false, "SEARCH", "APPLY CHANGES?")); searchForFunc, false, "SEARCH", "APPLY CHANGES?"));
@ -660,8 +662,9 @@ bool GuiScraperSearch::saveMetadata(
std::vector<HelpPrompt> GuiScraperSearch::getHelpPrompts() std::vector<HelpPrompt> GuiScraperSearch::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts = mGrid.getHelpPrompts(); std::vector<HelpPrompt> prompts;
if (getSelectedIndex() != -1)
if (mFoundGame)
prompts.push_back(HelpPrompt("a", "accept result")); prompts.push_back(HelpPrompt("a", "accept result"));
return prompts; return prompts;

View file

@ -116,6 +116,7 @@ private:
std::function<void()> mSkipCallback; std::function<void()> mSkipCallback;
std::function<void()> mCancelCallback; std::function<void()> mCancelCallback;
bool mBlockAccept; bool mBlockAccept;
bool mFoundGame;
std::unique_ptr<ScraperSearchHandle> mSearchHandle; std::unique_ptr<ScraperSearchHandle> mSearchHandle;
std::unique_ptr<ScraperSearchHandle> mMDRetrieveURLsHandle; std::unique_ptr<ScraperSearchHandle> mMDRetrieveURLsHandle;

View file

@ -10,7 +10,7 @@ GuiScreensaverOptions::GuiScreensaverOptions(Window* window, const char* title)
{ {
addChild(&mMenu); addChild(&mMenu);
mMenu.addButton("BACK", "go back", [this] { delete this; }); mMenu.addButton("BACK", "back", [this] { delete this; });
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight()); setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2, Renderer::getScreenHeight() * 0.15f); mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2, Renderer::getScreenHeight() * 0.15f);
@ -34,22 +34,16 @@ void GuiScreensaverOptions::save()
bool GuiScreensaverOptions::input(InputConfig* config, Input input) bool GuiScreensaverOptions::input(InputConfig* config, Input input)
{ {
if(config->isMappedTo("b", input) && input.value != 0) if (GuiComponent::input(config, input))
{ return true;
if (config->isMappedTo("b", input) &&
input.value != 0) {
delete this; delete this;
return true; return true;
} }
if(config->isMappedTo("start", input) && input.value != 0) return false;
{
// close everything
Window* window = mWindow;
while(window->peekGui() && window->peekGui() != ViewController::get())
delete window->peekGui();
return true;
}
return GuiComponent::input(config, input);
} }
HelpStyle GuiScreensaverOptions::getHelpStyle() HelpStyle GuiScreensaverOptions::getHelpStyle()
@ -62,10 +56,7 @@ HelpStyle GuiScreensaverOptions::getHelpStyle()
std::vector<HelpPrompt> GuiScreensaverOptions::getHelpPrompts() std::vector<HelpPrompt> GuiScreensaverOptions::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts(); std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("b", "back")); prompts.push_back(HelpPrompt("b", "back"));
prompts.push_back(HelpPrompt("start", "close"));
return prompts; return prompts;
} }

View file

@ -9,7 +9,7 @@ GuiSettings::GuiSettings(Window* window, const char* title) : GuiComponent(windo
{ {
addChild(&mMenu); addChild(&mMenu);
mMenu.addButton("BACK", "go back", [this] { delete this; }); mMenu.addButton("BACK", "back", [this] { delete this; });
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight()); setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2, Renderer::getScreenHeight() * 0.15f); mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2, Renderer::getScreenHeight() * 0.15f);
@ -39,14 +39,15 @@ bool GuiSettings::input(InputConfig* config, Input input)
return true; return true;
} }
if(config->isMappedTo("start", input) && input.value != 0) // Keep code for potential future use.
{ // if(config->isMappedTo("start", input) && input.value != 0)
// close everything // {
Window* window = mWindow; // // close everything
while(window->peekGui() && window->peekGui() != ViewController::get()) // Window* window = mWindow;
delete window->peekGui(); // while(window->peekGui() && window->peekGui() != ViewController::get())
return true; // delete window->peekGui();
} // return true;
// }
return GuiComponent::input(config, input); return GuiComponent::input(config, input);
} }
@ -61,9 +62,6 @@ HelpStyle GuiSettings::getHelpStyle()
std::vector<HelpPrompt> GuiSettings::getHelpPrompts() std::vector<HelpPrompt> GuiSettings::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts(); std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("b", "back")); prompts.push_back(HelpPrompt("b", "back"));
prompts.push_back(HelpPrompt("start", "close"));
return prompts; return prompts;
} }

View file

@ -27,7 +27,6 @@
#include "MameNames.h" #include "MameNames.h"
#include "platform.h" #include "platform.h"
#include "PowerSaver.h" #include "PowerSaver.h"
#include "ScraperCmdLine.h"
#include "Settings.h" #include "Settings.h"
#include "SystemData.h" #include "SystemData.h"
#include "SystemScreenSaver.h" #include "SystemScreenSaver.h"
@ -42,8 +41,6 @@
#include <FreeImage.h> #include <FreeImage.h>
bool scrape_cmdline = false;
bool parseArgs(int argc, char* argv[]) bool parseArgs(int argc, char* argv[])
{ {
Utils::FileSystem::setExePath(argv[0]); Utils::FileSystem::setExePath(argv[0]);
@ -168,9 +165,6 @@ bool parseArgs(int argc, char* argv[])
strcmp(argv[i + 1], "1") == 0) ? true : false; strcmp(argv[i + 1], "1") == 0) ? true : false;
Settings::getInstance()->setBool("VSync", vsync); Settings::getInstance()->setBool("VSync", vsync);
i++; // Skip vsync value. i++; // Skip vsync value.
// }
// else if (strcmp(argv[i], "--scrape") == 0) {
// scrape_cmdline = true;
} }
else if (strcmp(argv[i], "--force-kiosk") == 0) { else if (strcmp(argv[i], "--force-kiosk") == 0) {
Settings::getInstance()->setBool("ForceKiosk", true); Settings::getInstance()->setBool("ForceKiosk", true);
@ -210,7 +204,6 @@ bool parseArgs(int argc, char* argv[])
#else #else
"--debug Print debug information\n" "--debug Print debug information\n"
#endif #endif
//"--scrape Scrape using command line interface\n"
"--windowed Windowed mode, should be combined with --resolution\n" "--windowed Windowed mode, should be combined with --resolution\n"
"--fullscreen-normal Normal fullscreen mode\n" "--fullscreen-normal Normal fullscreen mode\n"
"--fullscreen-borderless Borderless fullscreen mode (always on top)\n" "--fullscreen-borderless Borderless fullscreen mode (always on top)\n"
@ -356,18 +349,16 @@ int main(int argc, char* argv[])
bool splashScreen = Settings::getInstance()->getBool("SplashScreen"); bool splashScreen = Settings::getInstance()->getBool("SplashScreen");
bool splashScreenProgress = Settings::getInstance()->getBool("SplashScreenProgress"); bool splashScreenProgress = Settings::getInstance()->getBool("SplashScreenProgress");
if (!scrape_cmdline) { if (!window.init()) {
if (!window.init()) { LOG(LogError) << "Window failed to initialize!";
LOG(LogError) << "Window failed to initialize!"; return 1;
return 1; }
}
if (splashScreen) { if (splashScreen) {
std::string progressText = "Loading..."; std::string progressText = "Loading...";
if (splashScreenProgress) if (splashScreenProgress)
progressText = "Loading system config..."; progressText = "Loading system config...";
window.renderLoadingScreen(progressText); window.renderLoadingScreen(progressText);
}
} }
const char* errorMsg = NULL; const char* errorMsg = NULL;
@ -376,8 +367,7 @@ int main(int argc, char* argv[])
if (errorMsg == NULL) if (errorMsg == NULL)
{ {
LOG(LogError) << "Unknown error occured while parsing system config file."; LOG(LogError) << "Unknown error occured while parsing system config file.";
if (!scrape_cmdline) Renderer::deinit();
Renderer::deinit();
return 1; return 1;
} }
@ -395,12 +385,6 @@ int main(int argc, char* argv[])
})); }));
} }
// Run the command line scraper then quit.
if (scrape_cmdline)
{
return run_scraper_cmdline();
}
// Dont generate joystick events while we're loading. // Dont generate joystick events while we're loading.
// (Hopefully fixes "automatically started emulator" bug.) // (Hopefully fixes "automatically started emulator" bug.)
SDL_JoystickEventState(SDL_DISABLE); SDL_JoystickEventState(SDL_DISABLE);

View file

@ -257,6 +257,18 @@ void GuiComponent::setOpacity(unsigned char opacity)
(*it)->setOpacity(opacity); (*it)->setOpacity(opacity);
} }
void GuiComponent::setColor(unsigned int color)
{
mColor = color;
mColorOpacity = mColor & 0x000000FF;
}
void GuiComponent::setColorShift(unsigned int color)
{
mColorShift = color;
mColorShiftEnd = color;
}
const Transform4x4f& GuiComponent::getTransform() const Transform4x4f& GuiComponent::getTransform()
{ {
mTransform = Transform4x4f::Identity(); mTransform = Transform4x4f::Identity();

View file

@ -130,6 +130,8 @@ public:
virtual unsigned char getOpacity() const; virtual unsigned char getOpacity() const;
virtual void setOpacity(unsigned char opacity); virtual void setOpacity(unsigned char opacity);
virtual void setColor(unsigned int color);
virtual void setColorShift(unsigned int color);
const Transform4x4f& getTransform(); const Transform4x4f& getTransform();
@ -170,6 +172,10 @@ protected:
void updateChildren(int deltaTime); // Updates animations. void updateChildren(int deltaTime); // Updates animations.
unsigned char mOpacity; unsigned char mOpacity;
unsigned int mColor;
unsigned char mColorOpacity;
unsigned int mColorShift;
unsigned int mColorShiftEnd;
Window* mWindow; Window* mWindow;
GuiComponent* mParent; GuiComponent* mParent;

View file

@ -354,3 +354,10 @@ void DateTimeEditComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
setFont(Font::getFromTheme(elem, properties, mFont)); setFont(Font::getFromTheme(elem, properties, mFont));
} }
std::vector<HelpPrompt> DateTimeEditComponent::getHelpPrompts()
{
std::vector<HelpPrompt> prompts;
prompts.push_back(HelpPrompt("a", "edit date"));
return prompts;
}

View file

@ -52,6 +52,8 @@ public:
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view,
const std::string& element, unsigned int properties) override; const std::string& element, unsigned int properties) override;
virtual std::vector<HelpPrompt> getHelpPrompts() override;
private: private:
std::shared_ptr<Font> getFont() const; std::shared_ptr<Font> getFont() const;

View file

@ -250,7 +250,7 @@ private:
{ {
std::vector<HelpPrompt> prompts; std::vector<HelpPrompt> prompts;
if(!mMultiSelect) if(!mMultiSelect)
prompts.push_back(HelpPrompt("left/right", "change")); prompts.push_back(HelpPrompt("left/right", "change value"));
prompts.push_back(HelpPrompt("a", "select")); prompts.push_back(HelpPrompt("a", "select"));
return prompts; return prompts;
@ -325,7 +325,7 @@ private:
mMenu.addRow(row, (!mParent->mMultiSelect && it->selected)); mMenu.addRow(row, (!mParent->mMultiSelect && it->selected));
} }
mMenu.addButton("BACK", "accept", [this] { delete this; }); mMenu.addButton("BACK", "back", [this] { delete this; });
if(mParent->mMultiSelect) { if(mParent->mMultiSelect) {
mMenu.addButton("SELECT ALL", "select all", [this, checkboxes] { mMenu.addButton("SELECT ALL", "select all", [this, checkboxes] {
@ -363,6 +363,7 @@ private:
std::vector<HelpPrompt> getHelpPrompts() override std::vector<HelpPrompt> getHelpPrompts() override
{ {
auto prompts = mMenu.getHelpPrompts(); auto prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("a", "select"));
prompts.push_back(HelpPrompt("b", "back")); prompts.push_back(HelpPrompt("b", "back"));
return prompts; return prompts;
} }

View file

@ -8,16 +8,16 @@
#include "components/RatingComponent.h" #include "components/RatingComponent.h"
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include "Settings.h"
#include "ThemeData.h" #include "ThemeData.h"
RatingComponent::RatingComponent(Window* window) : GuiComponent(window), RatingComponent::RatingComponent(Window* window) : GuiComponent(window),
mColorShift(0xFFFFFFFF), mUnfilledColor(0xFFFFFFFF) mColorShift(0xFFFFFFFF), mColorShiftEnd(0xFFFFFFFF), mUnfilledColor(0xFFFFFFFF)
{ {
mFilledTexture = TextureResource::get(":/star_filled.svg", true); mFilledTexture = TextureResource::get(":/star_filled.svg", true);
mUnfilledTexture = TextureResource::get(":/star_unfilled.svg", true); mUnfilledTexture = TextureResource::get(":/star_unfilled.svg", true);
mValue = 0.5f; mValue = 0.5f;
mSize = Vector2f(64 * NUM_RATING_STARS, 64); mSize = Vector2f(64 * NUM_RATING_STARS, 64);
mHideRatingComponent = false;
updateVertices(); updateVertices();
updateColors(); updateColors();
} }
@ -50,12 +50,6 @@ std::string RatingComponent::getValue() const
void RatingComponent::setOpacity(unsigned char opacity) void RatingComponent::setOpacity(unsigned char opacity)
{ {
// Completely hide component if opacity if set to zero.
if (opacity == 0)
mHideRatingComponent = true;
else
mHideRatingComponent = false;
mOpacity = opacity; mOpacity = opacity;
mColorShift = (mColorShift >> 8 << 8) | mOpacity; mColorShift = (mColorShift >> 8 << 8) | mOpacity;
updateColors(); updateColors();
@ -64,6 +58,8 @@ void RatingComponent::setOpacity(unsigned char opacity)
void RatingComponent::setColorShift(unsigned int color) void RatingComponent::setColorShift(unsigned int color)
{ {
mColorShift = color; mColorShift = color;
mColorShiftEnd = color;
// Grab the opacity from the color shift because we may need // Grab the opacity from the color shift because we may need
// to apply it if fading in textures. // to apply it if fading in textures.
mOpacity = color & 0xff; mOpacity = color & 0xff;
@ -126,31 +122,34 @@ void RatingComponent::render(const Transform4x4f& parentTrans)
if (!isVisible() || mFilledTexture == nullptr || mUnfilledTexture == nullptr) if (!isVisible() || mFilledTexture == nullptr || mUnfilledTexture == nullptr)
return; return;
// If set to true, hide rating component.
if (mHideRatingComponent)
return;
Transform4x4f trans = parentTrans * getTransform(); Transform4x4f trans = parentTrans * getTransform();
Renderer::setMatrix(trans); Renderer::setMatrix(trans);
if (mUnfilledTexture->bind()) { if (mOpacity > 0) {
if (mUnfilledColor != mColorShift) { if(Settings::getInstance()->getBool("DebugImage")) {
const unsigned int color = Renderer::convertColor(mUnfilledColor); Renderer::drawRect(0.0f, 0.0f, mSize.y() * NUM_RATING_STARS,
for (int i = 0; i < 8; ++i) mSize.y(), 0x00000033, 0x00000033);
mVertices[i].col = color;
} }
Renderer::drawTriangleStrips(&mVertices[4], 4); if (mUnfilledTexture->bind()) {
Renderer::bindTexture(0); if (mUnfilledColor != mColorShift) {
const unsigned int color = Renderer::convertColor(mUnfilledColor);
for (int i = 0; i < 8; ++i)
mVertices[i].col = color;
}
if (mUnfilledColor != mColorShift) Renderer::drawTriangleStrips(&mVertices[4], 4);
updateColors(); Renderer::bindTexture(0);
}
if (mFilledTexture->bind()) { if (mUnfilledColor != mColorShift)
Renderer::drawTriangleStrips(&mVertices[0], 4); updateColors();
Renderer::bindTexture(0); }
if (mFilledTexture->bind()) {
Renderer::drawTriangleStrips(&mVertices[0], 4);
Renderer::bindTexture(0);
}
} }
renderChildren(trans); renderChildren(trans);
@ -206,6 +205,6 @@ void RatingComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
std::vector<HelpPrompt> RatingComponent::getHelpPrompts() std::vector<HelpPrompt> RatingComponent::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts; std::vector<HelpPrompt> prompts;
prompts.push_back(HelpPrompt("a", "add star")); prompts.push_back(HelpPrompt("a", "add half star"));
return prompts; return prompts;
} }

View file

@ -46,6 +46,8 @@ public:
virtual std::vector<HelpPrompt> getHelpPrompts() override; virtual std::vector<HelpPrompt> getHelpPrompts() override;
private: private:
Vector2f mTargetSize;
void updateVertices(); void updateVertices();
void updateColors(); void updateColors();
@ -54,9 +56,8 @@ private:
Renderer::Vertex mVertices[8]; Renderer::Vertex mVertices[8];
unsigned int mColorShift; unsigned int mColorShift;
unsigned int mColorShiftEnd;
unsigned int mUnfilledColor; unsigned int mUnfilledColor;
// If set to true, the rating component is hidden.
bool mHideRatingComponent;
std::shared_ptr<TextureResource> mFilledTexture; std::shared_ptr<TextureResource> mFilledTexture;
std::shared_ptr<TextureResource> mUnfilledTexture; std::shared_ptr<TextureResource> mUnfilledTexture;

View file

@ -137,6 +137,6 @@ void SliderComponent::onValueChanged()
std::vector<HelpPrompt> SliderComponent::getHelpPrompts() std::vector<HelpPrompt> SliderComponent::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts; std::vector<HelpPrompt> prompts;
prompts.push_back(HelpPrompt("left/right", "change")); prompts.push_back(HelpPrompt("left/right", "change value"));
return prompts; return prompts;
} }

View file

@ -76,6 +76,6 @@ void SwitchComponent::onStateChanged()
std::vector<HelpPrompt> SwitchComponent::getHelpPrompts() std::vector<HelpPrompt> SwitchComponent::getHelpPrompts()
{ {
std::vector<HelpPrompt> prompts; std::vector<HelpPrompt> prompts;
prompts.push_back(HelpPrompt("a", "change")); prompts.push_back(HelpPrompt("a", "toggle"));
return prompts; return prompts;
} }

View file

@ -127,9 +127,10 @@ bool TextEditComponent::input(InputConfig* config, Input input)
return true; return true;
} }
// Stop editing. // Done editing (accept changes).
if ((config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_ESCAPE) || if ((config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_ESCAPE) ||
(config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedTo("b", input))) { (config->getDeviceId() != DEVICE_KEYBOARD && (config->isMappedTo("a", input) ||
config->isMappedTo("b", input)))) {
mTextOrig = mText; mTextOrig = mText;
stopEditing(); stopEditing();
return true; return true;
@ -305,7 +306,8 @@ std::vector<HelpPrompt> TextEditComponent::getHelpPrompts()
if (mEditing) { if (mEditing) {
prompts.push_back(HelpPrompt("up/down/left/right", "move cursor")); prompts.push_back(HelpPrompt("up/down/left/right", "move cursor"));
prompts.push_back(HelpPrompt("y", "backspace")); prompts.push_back(HelpPrompt("y", "backspace"));
prompts.push_back(HelpPrompt("b", "stop editing")); prompts.push_back(HelpPrompt("a", "accept changes"));
prompts.push_back(HelpPrompt("b", "accept changes"));
} }
else { else {
prompts.push_back(HelpPrompt("a", "edit")); prompts.push_back(HelpPrompt("a", "edit"));

View file

@ -54,7 +54,8 @@ GuiComplexTextEditPopup::GuiComplexTextEditPopup(
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, acceptBtnText, acceptBtnText, buttons.push_back(std::make_shared<ButtonComponent>(mWindow, acceptBtnText, acceptBtnText,
[this, okCallback] { okCallback(mText->getValue()); delete this; })); [this, okCallback] { okCallback(mText->getValue()); delete this; }));
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "LOAD", "load default string", buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "LOAD", "load default string",
[this, infoString2] { mText->setValue(infoString2); })); [this, infoString2] {
mText->setValue(infoString2); mText->setCursor(infoString2.size()); }));
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CLEAR", "clear string", buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CLEAR", "clear string",
[this] { mText->setValue(""); })); [this] { mText->setValue(""); }));
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "discard changes", buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "discard changes",