Fixed lots of code formatting issues.

This commit is contained in:
Leon Styhre 2021-09-27 21:06:07 +02:00
parent a928142d5b
commit f6dd49071e
48 changed files with 828 additions and 556 deletions

View file

@ -377,21 +377,21 @@ void CollectionSystemsManager::updateCollectionSystem(FileData* file, Collection
// If the countasgame flag has been set to false, then remove the game. // If the countasgame flag has been set to false, then remove the game.
if (curSys->isGroupedCustomCollection()) { if (curSys->isGroupedCustomCollection()) {
ViewController::get() ViewController::get()
->getGameListView(curSys->getRootFolder()->getParent()->getSystem()) ->getGameListView(curSys->getRootFolder()->getParent()->getSystem())
.get() .get()
->remove(collectionEntry, false); ->remove(collectionEntry, false);
FileData *parentRootFolder = FileData* parentRootFolder =
rootFolder->getParent()->getSystem()->getRootFolder(); rootFolder->getParent()->getSystem()->getRootFolder();
parentRootFolder->sort(parentRootFolder->getSortTypeFromString( parentRootFolder->sort(parentRootFolder->getSortTypeFromString(
parentRootFolder->getSortTypeString()), parentRootFolder->getSortTypeString()),
mFavoritesSorting); mFavoritesSorting);
GuiInfoPopup *s = new GuiInfoPopup( GuiInfoPopup* s = new GuiInfoPopup(
mWindow, mWindow,
"DISABLED '" + "DISABLED '" +
Utils::String::toUpper( Utils::String::toUpper(
Utils::String::removeParenthesis(file->getName())) + Utils::String::removeParenthesis(file->getName())) +
"' IN '" + Utils::String::toUpper(sysData.system->getName()) + "'", "' IN '" + Utils::String::toUpper(sysData.system->getName()) + "'",
4000); 4000);
mWindow->setInfoPopup(s); mWindow->setInfoPopup(s);
} }
else { else {
@ -550,26 +550,28 @@ bool CollectionSystemsManager::isThemeCustomCollectionCompatible(
return true; return true;
} }
std::string CollectionSystemsManager::getValidNewCollectionName(std::string inName, int index) { std::string CollectionSystemsManager::getValidNewCollectionName(std::string inName, int index)
{
std::string name = inName; std::string name = inName;
// Trim leading and trailing whitespaces. // Trim leading and trailing whitespaces.
name.erase(name.begin(), std::find_if(name.begin(), name.end(), [](char c) { name.erase(name.begin(), std::find_if(name.begin(), name.end(), [](char c) {
return !std::isspace(static_cast<unsigned char>(c)); return !std::isspace(static_cast<unsigned char>(c));
})); }));
name.erase(std::find_if(name.rbegin(), name.rend(), name.erase(std::find_if(name.rbegin(), name.rend(),
[](char c) { return !std::isspace(static_cast<unsigned char>(c)); }) [](char c) { return !std::isspace(static_cast<unsigned char>(c)); })
.base(), .base(),
name.end()); name.end());
if (index == 0) { if (index == 0) {
size_t remove = std::string::npos; size_t remove = std::string::npos;
// Get valid name. // Get valid name.
while ((remove = name.find_first_not_of( while ((remove = name.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-[]()' ")) != "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-[]()' ")) !=
std::string::npos) std::string::npos)
name.erase(remove, 1); name.erase(remove, 1);
} else { }
else {
name += " (" + std::to_string(index) + ")"; name += " (" + std::to_string(index) + ")";
} }
@ -1331,7 +1333,8 @@ void CollectionSystemsManager::addEnabledCollectionsToDisplayedSystems(
} }
} }
std::vector<std::string> CollectionSystemsManager::getSystemsFromConfig() { std::vector<std::string> CollectionSystemsManager::getSystemsFromConfig()
{
std::vector<std::string> systems; std::vector<std::string> systems;
std::vector<std::string> configPaths = SystemData::getConfigPath(false); std::vector<std::string> configPaths = SystemData::getConfigPath(false);
@ -1339,7 +1342,7 @@ std::vector<std::string> CollectionSystemsManager::getSystemsFromConfig() {
// file under ~/.emulationstation/custom_systems as we really want to include all the themes // file under ~/.emulationstation/custom_systems as we really want to include all the themes
// supported by ES-DE. Otherwise a user may accidentally create a custom collection that // supported by ES-DE. Otherwise a user may accidentally create a custom collection that
// corresponds to a supported theme. // corresponds to a supported theme.
for (auto path: configPaths) { for (auto path : configPaths) {
if (!Utils::FileSystem::exists(path)) if (!Utils::FileSystem::exists(path))
return systems; return systems;

View file

@ -30,11 +30,18 @@
#include <assert.h> #include <assert.h>
FileData::FileData(FileType type, FileData::FileData(FileType type,
const std::string &path, const std::string& path,
SystemEnvironmentData *envData, SystemEnvironmentData* envData,
SystemData *system) SystemData* system)
: metadata(type == GAME ? GAME_METADATA : FOLDER_METADATA), mSourceFileData(nullptr), mParent(nullptr), : metadata(type == GAME ? GAME_METADATA : FOLDER_METADATA)
mType(type), mPath(path), mEnvData(envData), mSystem(system), mOnlyFolders(false), mDeletionFlag(false) , mSourceFileData(nullptr)
, mParent(nullptr)
, mType(type)
, mPath(path)
, mEnvData(envData)
, mSystem(system)
, mOnlyFolders(false)
, mDeletionFlag(false)
{ {
// Metadata needs at least a name field (since that's what getName() will return). // Metadata needs at least a name field (since that's what getName() will return).
if (metadata.get("name").empty()) { if (metadata.get("name").empty()) {
@ -735,10 +742,11 @@ FileData::SortType FileData::getSortTypeFromString(std::string desc)
return FileSorts::SortTypes.at(0); return FileSorts::SortTypes.at(0);
} }
void FileData::launchGame(Window *window) { void FileData::launchGame(Window* window)
{
LOG(LogInfo) << "Launching game \"" << this->metadata.get("name") << "\"..."; LOG(LogInfo) << "Launching game \"" << this->metadata.get("name") << "\"...";
SystemData *gameSystem = nullptr; SystemData* gameSystem = nullptr;
std::string command = ""; std::string command = "";
std::string alternativeEmulator; std::string alternativeEmulator;
@ -1347,8 +1355,8 @@ const std::string& CollectionFileData::getName()
if (mDirty) { if (mDirty) {
mCollectionFileName = mSourceFileData->metadata.get("name"); mCollectionFileName = mSourceFileData->metadata.get("name");
mCollectionFileName.append(" [") mCollectionFileName.append(" [")
.append(Utils::String::toUpper(mSourceFileData->getSystem()->getName())) .append(Utils::String::toUpper(mSourceFileData->getSystem()->getName()))
.append("]"); .append("]");
mDirty = false; mDirty = false;
} }

View file

@ -20,9 +20,17 @@
#define INCLUDE_UNKNOWN false; #define INCLUDE_UNKNOWN false;
FileFilterIndex::FileFilterIndex() FileFilterIndex::FileFilterIndex()
: mFilterByText(false), mTextRemoveSystem(false), mFilterByFavorites(false), mFilterByGenre(false), : mFilterByText(false)
mFilterByPlayers(false), mFilterByPubDev(false), mFilterByRatings(false), mFilterByKidGame(false), , mTextRemoveSystem(false)
mFilterByCompleted(false), mFilterByBroken(false), mFilterByHidden(false) , mFilterByFavorites(false)
, mFilterByGenre(false)
, mFilterByPlayers(false)
, mFilterByPubDev(false)
, mFilterByRatings(false)
, mFilterByKidGame(false)
, mFilterByCompleted(false)
, mFilterByBroken(false)
, mFilterByHidden(false)
{ {
clearAllFilters(); clearAllFilters();
@ -357,10 +365,11 @@ bool FileFilterIndex::showFile(FileData* game)
// in [] from the search string. // in [] from the search string.
if (mTextFilter != "" && mTextRemoveSystem && if (mTextFilter != "" && mTextRemoveSystem &&
!(Utils::String::toUpper(game->getName().substr(0, game->getName().find_last_of("["))) !(Utils::String::toUpper(game->getName().substr(0, game->getName().find_last_of("[")))
.find(mTextFilter) != std::string::npos)) { .find(mTextFilter) != std::string::npos)) {
return false; return false;
} else if (mTextFilter != "" && }
!(Utils::String::toUpper(game->getName()).find(mTextFilter) != std::string::npos)) { else if (mTextFilter != "" &&
!(Utils::String::toUpper(game->getName()).find(mTextFilter) != std::string::npos)) {
return false; return false;
} }
@ -372,7 +381,8 @@ bool FileFilterIndex::showFile(FileData* game)
FilterDataDecl filterData = (*it); FilterDataDecl filterData = (*it);
if (filterData.primaryKey == "kidgame" && UIModeController::getInstance()->isUIModeKid()) { if (filterData.primaryKey == "kidgame" && UIModeController::getInstance()->isUIModeKid()) {
return (getIndexableKey(game, filterData.type, false) != "FALSE"); return (getIndexableKey(game, filterData.type, false) != "FALSE");
} else if (*(filterData.filteredByRef)) { }
else if (*(filterData.filteredByRef)) {
// Try to find a match. // Try to find a match.
std::string key = getIndexableKey(game, filterData.type, false); std::string key = getIndexableKey(game, filterData.type, false);
keepGoing = isKeyBeingFilteredBy(key, filterData.type); keepGoing = isKeyBeingFilteredBy(key, filterData.type);

View file

@ -49,11 +49,11 @@ public:
FileFilterIndex(); FileFilterIndex();
~FileFilterIndex(); ~FileFilterIndex();
void addToIndex(FileData *game); void addToIndex(FileData* game);
void removeFromIndex(FileData *game); void removeFromIndex(FileData* game);
void setFilter(FilterIndexType type, std::vector<std::string> *values); void setFilter(FilterIndexType type, std::vector<std::string>* values);
void setTextFilter(std::string textFilter); void setTextFilter(std::string textFilter);
@ -63,17 +63,17 @@ public:
void debugPrintIndexes(); void debugPrintIndexes();
bool showFile(FileData *game); bool showFile(FileData* game);
bool isFiltered(); bool isFiltered();
bool isKeyBeingFilteredBy(std::string key, FilterIndexType type); bool isKeyBeingFilteredBy(std::string key, FilterIndexType type);
std::vector<FilterDataDecl> &getFilterDataDecls() { return filterDataDecl; } std::vector<FilterDataDecl>& getFilterDataDecls() { return filterDataDecl; }
void setTextRemoveSystem(bool status) { mTextRemoveSystem = status; } void setTextRemoveSystem(bool status) { mTextRemoveSystem = status; }
void importIndex(FileFilterIndex *indexToImport); void importIndex(FileFilterIndex* indexToImport);
void resetIndex(); void resetIndex();

View file

@ -227,7 +227,8 @@ namespace FileSorts
return system1.compare(system2) < 0; return system1.compare(system2) < 0;
} }
bool compareSystemDescending(const FileData *file1, const FileData *file2) { bool compareSystemDescending(const FileData* file1, const FileData* file2)
{
std::string system1 = Utils::String::toUpper(file1->getSystemName()); std::string system1 = Utils::String::toUpper(file1->getSystemName());
std::string system2 = Utils::String::toUpper(file2->getSystemName()); std::string system2 = Utils::String::toUpper(file2->getSystemName());
return system1.compare(system2) > 0; return system1.compare(system2) > 0;

View file

@ -19,41 +19,41 @@ namespace FileSorts
bool compareName(const FileData* file1, const FileData* file2); bool compareName(const FileData* file1, const FileData* file2);
bool compareNameDescending(const FileData* file1, const FileData* file2); bool compareNameDescending(const FileData* file1, const FileData* file2);
bool compareRating(const FileData *file1, const FileData *file2); bool compareRating(const FileData* file1, const FileData* file2);
bool compareRatingDescending(const FileData *file1, const FileData *file2); bool compareRatingDescending(const FileData* file1, const FileData* file2);
bool compareReleaseDate(const FileData *file1, const FileData *file2); bool compareReleaseDate(const FileData* file1, const FileData* file2);
bool compareReleaseDateDescending(const FileData *file1, const FileData *file2); bool compareReleaseDateDescending(const FileData* file1, const FileData* file2);
bool compareDeveloper(const FileData *file1, const FileData *file2); bool compareDeveloper(const FileData* file1, const FileData* file2);
bool compareDeveloperDescending(const FileData *file1, const FileData *file2); bool compareDeveloperDescending(const FileData* file1, const FileData* file2);
bool comparePublisher(const FileData *file1, const FileData *file2); bool comparePublisher(const FileData* file1, const FileData* file2);
bool comparePublisherDescending(const FileData *file1, const FileData *file2); bool comparePublisherDescending(const FileData* file1, const FileData* file2);
bool compareGenre(const FileData *file1, const FileData *file2); bool compareGenre(const FileData* file1, const FileData* file2);
bool compareGenreDescending(const FileData *file1, const FileData *file2); bool compareGenreDescending(const FileData* file1, const FileData* file2);
bool compareNumPlayers(const FileData *file1, const FileData *file2); bool compareNumPlayers(const FileData* file1, const FileData* file2);
bool compareNumPlayersDescending(const FileData *file1, const FileData *file2); bool compareNumPlayersDescending(const FileData* file1, const FileData* file2);
bool compareLastPlayed(const FileData *file1, const FileData *file2); bool compareLastPlayed(const FileData* file1, const FileData* file2);
bool compareLastPlayedDescending(const FileData *file1, const FileData *file2); bool compareLastPlayedDescending(const FileData* file1, const FileData* file2);
bool compareTimesPlayed(const FileData *file1, const FileData *fil2); bool compareTimesPlayed(const FileData* file1, const FileData* fil2);
bool compareTimesPlayedDescending(const FileData *file1, const FileData *fil2); bool compareTimesPlayedDescending(const FileData* file1, const FileData* fil2);
bool compareSystem(const FileData *file1, const FileData *file2); bool compareSystem(const FileData* file1, const FileData* file2);
bool compareSystemDescending(const FileData *file1, const FileData *file2); bool compareSystemDescending(const FileData* file1, const FileData* file2);
extern const std::vector<FileData::SortType> SortTypes; extern const std::vector<FileData::SortType> SortTypes;
} // namespace FileSorts } // namespace FileSorts

View file

@ -200,12 +200,12 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
glm::vec2{0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()}); glm::vec2{0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()});
row.addElement(newCollection, true); row.addElement(newCollection, true);
row.addElement(bracketNewCollection, false); row.addElement(bracketNewCollection, false);
auto createCollectionCall = [this](const std::string &newVal) { auto createCollectionCall = [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 // We need to store the first GUI and remove it, as it'll be deleted
// by the actual GUI. // by the actual GUI.
Window *window = mWindow; Window* window = mWindow;
GuiComponent *topGui = window->peekGui(); GuiComponent* topGui = window->peekGui();
window->removeGui(topGui); window->removeGui(topGui);
createCustomCollection(name); createCustomCollection(name);
}; };
@ -213,10 +213,11 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
if (Settings::getInstance()->getBool("VirtualKeyboard")) { if (Settings::getInstance()->getBool("VirtualKeyboard")) {
row.makeAcceptInputHandler([this, createCollectionCall] { row.makeAcceptInputHandler([this, createCollectionCall] {
mWindow->pushGui(new GuiTextEditKeyboardPopup( mWindow->pushGui(new GuiTextEditKeyboardPopup(
mWindow, getHelpStyle(), "New Collection Name", "", createCollectionCall, false, mWindow, getHelpStyle(), "New Collection Name", "", createCollectionCall, false,
"CREATE", "CREATE COLLECTION?")); "CREATE", "CREATE COLLECTION?"));
}); });
} else { }
else {
row.makeAcceptInputHandler([this, createCollectionCall] { row.makeAcceptInputHandler([this, createCollectionCall] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "New Collection Name", mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "New Collection Name",
"", createCollectionCall, false, "CREATE", "", createCollectionCall, false, "CREATE",
@ -228,11 +229,11 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window, std::st
// Delete custom collection. // Delete custom collection.
row.elements.clear(); row.elements.clear();
auto deleteCollection = std::make_shared<TextComponent>( auto deleteCollection = std::make_shared<TextComponent>(
mWindow, "DELETE CUSTOM COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF); mWindow, "DELETE CUSTOM COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
auto bracketDeleteCollection = std::make_shared<ImageComponent>(mWindow); auto bracketDeleteCollection = std::make_shared<ImageComponent>(mWindow);
bracketDeleteCollection->setImage(":/graphics/arrow.svg"); bracketDeleteCollection->setImage(":/graphics/arrow.svg");
bracketDeleteCollection->setResize( bracketDeleteCollection->setResize(
glm::vec2{0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()}); glm::vec2{0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()});
row.addElement(deleteCollection, true); row.addElement(deleteCollection, true);
row.addElement(bracketDeleteCollection, false); row.addElement(bracketDeleteCollection, false);
row.makeAcceptInputHandler([this, customSystems] { row.makeAcceptInputHandler([this, customSystems] {

View file

@ -18,11 +18,14 @@
#include "components/TextComponent.h" #include "components/TextComponent.h"
#include "views/ViewController.h" #include "views/ViewController.h"
GuiGameScraper::GuiGameScraper(Window *window, GuiGameScraper::GuiGameScraper(Window* window,
ScraperSearchParams params, ScraperSearchParams params,
std::function<void(const ScraperSearchResult &)> doneFunc) std::function<void(const ScraperSearchResult&)> doneFunc)
: GuiComponent(window), mClose(false), mGrid(window, glm::ivec2{1, 7}), mBox(window, ":/graphics/frame.svg"), : GuiComponent(window)
mSearchParams(params) , mClose(false)
, mGrid(window, glm::ivec2{1, 7})
, mBox(window, ":/graphics/frame.svg")
, mSearchParams(params)
{ {
addChild(&mBox); addChild(&mBox);
addChild(&mGrid); addChild(&mGrid);

View file

@ -29,7 +29,8 @@ GuiGamelistFilter::GuiGamelistFilter(Window* window,
initializeMenu(); initializeMenu();
} }
void GuiGamelistFilter::initializeMenu() { void GuiGamelistFilter::initializeMenu()
{
addChild(&mMenu); addChild(&mMenu);
// Get filters from system. // Get filters from system.
@ -93,12 +94,13 @@ void GuiGamelistFilter::resetAllFilters()
GuiGamelistFilter::~GuiGamelistFilter() { mFilterOptions.clear(); } GuiGamelistFilter::~GuiGamelistFilter() { mFilterOptions.clear(); }
void GuiGamelistFilter::addFiltersToMenu() { void GuiGamelistFilter::addFiltersToMenu()
{
ComponentListRow row; ComponentListRow row;
auto lbl = std::make_shared<TextComponent>( auto lbl = std::make_shared<TextComponent>(
mWindow, Utils::String::toUpper(ViewController::KEYBOARD_CHAR + " GAME NAME"), mWindow, Utils::String::toUpper(ViewController::KEYBOARD_CHAR + " GAME NAME"),
Font::get(FONT_SIZE_MEDIUM), 0x777777FF); Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
mTextFilterField = std::make_shared<TextComponent>(mWindow, "", Font::get(FONT_SIZE_MEDIUM), mTextFilterField = std::make_shared<TextComponent>(mWindow, "", Font::get(FONT_SIZE_MEDIUM),
0x777777FF, ALIGN_RIGHT); 0x777777FF, ALIGN_RIGHT);
@ -121,7 +123,7 @@ void GuiGamelistFilter::addFiltersToMenu() {
} }
// Callback function. // Callback function.
auto updateVal = [this](const std::string &newVal) { auto updateVal = [this](const std::string& newVal) {
mTextFilterField->setValue(Utils::String::toUpper(newVal)); mTextFilterField->setValue(Utils::String::toUpper(newVal));
mFilterIndex->setTextFilter(Utils::String::toUpper(newVal)); mFilterIndex->setTextFilter(Utils::String::toUpper(newVal));
}; };
@ -132,7 +134,8 @@ void GuiGamelistFilter::addFiltersToMenu() {
mTextFilterField->getValue(), updateVal, mTextFilterField->getValue(), updateVal,
false, "OK", "APPLY CHANGES?")); false, "OK", "APPLY CHANGES?"));
}); });
} else { }
else {
row.makeAcceptInputHandler([this, updateVal] { row.makeAcceptInputHandler([this, updateVal] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "GAME NAME", mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "GAME NAME",
mTextFilterField->getValue(), updateVal, false, mTextFilterField->getValue(), updateVal, false,

View file

@ -25,9 +25,15 @@
#include "views/ViewController.h" #include "views/ViewController.h"
#include "views/gamelist/IGameListView.h" #include "views/gamelist/IGameListView.h"
GuiGamelistOptions::GuiGamelistOptions(Window *window, SystemData *system) GuiGamelistOptions::GuiGamelistOptions(Window* window, SystemData* system)
: GuiComponent(window), mMenu(window, "OPTIONS"), mSystem(system), mFiltersChanged(false), mCancelled(false), : GuiComponent(window)
mIsCustomCollection(false), mIsCustomCollectionGroup(false), mCustomCollectionSystem(nullptr) , mMenu(window, "OPTIONS")
, mSystem(system)
, mFiltersChanged(false)
, mCancelled(false)
, mIsCustomCollection(false)
, mIsCustomCollectionGroup(false)
, mCustomCollectionSystem(nullptr)
{ {
addChild(&mMenu); addChild(&mMenu);

View file

@ -14,9 +14,12 @@
#include "components/TextComponent.h" #include "components/TextComponent.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
GuiLaunchScreen::GuiLaunchScreen(Window *window) GuiLaunchScreen::GuiLaunchScreen(Window* window)
: GuiComponent(window), mWindow(window), mBackground(window, ":/graphics/frame.svg"), mGrid(nullptr), : GuiComponent(window)
mMarquee(nullptr) , mWindow(window)
, mBackground(window, ":/graphics/frame.svg")
, mGrid(nullptr)
, mMarquee(nullptr)
{ {
addChild(&mBackground); addChild(&mBackground);
mWindow->setLaunchScreen(this); mWindow->setLaunchScreen(this);
@ -217,7 +220,8 @@ void GuiLaunchScreen::update(int deltaTime)
mScaleUp = glm::clamp(mScaleUp + 0.07f, 0.0f, 1.0f); mScaleUp = glm::clamp(mScaleUp + 0.07f, 0.0f, 1.0f);
} }
void GuiLaunchScreen::render(const glm::mat4 & /*parentTrans*/) { void GuiLaunchScreen::render(const glm::mat4& /*parentTrans*/)
{
// Scale up animation. // Scale up animation.
if (mScaleUp < 1.0f) if (mScaleUp < 1.0f)
setScale(mScaleUp); setScale(mScaleUp);

View file

@ -21,11 +21,11 @@ class FileData;
class GuiLaunchScreen : public Window::GuiLaunchScreen, GuiComponent class GuiLaunchScreen : public Window::GuiLaunchScreen, GuiComponent
{ {
public: public:
GuiLaunchScreen(Window *window); GuiLaunchScreen(Window* window);
virtual ~GuiLaunchScreen(); virtual ~GuiLaunchScreen();
virtual void displayLaunchScreen(FileData *game) override; virtual void displayLaunchScreen(FileData* game) override;
virtual void closeLaunchScreen() override; virtual void closeLaunchScreen() override;
@ -33,12 +33,12 @@ public:
virtual void update(int deltaTime) override; virtual void update(int deltaTime) override;
virtual void render(const glm::mat4 &parentTrans) override; virtual void render(const glm::mat4& parentTrans) override;
private: private:
Window *mWindow; Window* mWindow;
NinePatchComponent mBackground; NinePatchComponent mBackground;
ComponentGrid *mGrid; ComponentGrid* mGrid;
std::shared_ptr<TextComponent> mTitle; std::shared_ptr<TextComponent> mTitle;
std::shared_ptr<TextComponent> mGameName; std::shared_ptr<TextComponent> mGameName;

View file

@ -36,8 +36,10 @@
#include <SDL2/SDL_events.h> #include <SDL2/SDL_events.h>
#include <algorithm> #include <algorithm>
GuiMenu::GuiMenu(Window *window) GuiMenu::GuiMenu(Window* window)
: GuiComponent(window), mMenu(window, "MAIN MENU"), mVersion(window) : GuiComponent(window)
, mMenu(window, "MAIN MENU")
, mVersion(window)
{ {
bool isFullUI = UIModeController::getInstance()->isUIModeFull(); bool isFullUI = UIModeController::getInstance()->isUIModeFull();
@ -822,16 +824,17 @@ void GuiMenu::openOtherOptions()
multiLineMediaDir] { multiLineMediaDir] {
if (Settings::getInstance()->getBool("VirtualKeyboard")) { if (Settings::getInstance()->getBool("VirtualKeyboard")) {
mWindow->pushGui(new GuiTextEditKeyboardPopup( mWindow->pushGui(new GuiTextEditKeyboardPopup(
mWindow, getHelpStyle(), titleMediaDir, mWindow, getHelpStyle(), titleMediaDir,
Settings::getInstance()->getString("MediaDirectory"), updateValMediaDir, Settings::getInstance()->getString("MediaDirectory"), updateValMediaDir,
multiLineMediaDir, "SAVE", "SAVE CHANGES?", mediaDirectoryStaticText, multiLineMediaDir, "SAVE", "SAVE CHANGES?", mediaDirectoryStaticText,
defaultDirectoryText, "load default directory")); defaultDirectoryText, "load default directory"));
} else { }
else {
mWindow->pushGui(new GuiTextEditPopup( mWindow->pushGui(new GuiTextEditPopup(
mWindow, getHelpStyle(), titleMediaDir, mWindow, getHelpStyle(), titleMediaDir,
Settings::getInstance()->getString("MediaDirectory"), updateValMediaDir, Settings::getInstance()->getString("MediaDirectory"), updateValMediaDir,
multiLineMediaDir, "SAVE", "SAVE CHANGES?", mediaDirectoryStaticText, multiLineMediaDir, "SAVE", "SAVE CHANGES?", mediaDirectoryStaticText,
defaultDirectoryText, "load default directory")); defaultDirectoryText, "load default directory"));
} }
}); });
s->addRow(rowMediaDir); s->addRow(rowMediaDir);

View file

@ -31,18 +31,25 @@
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "views/ViewController.h" #include "views/ViewController.h"
GuiMetaDataEd::GuiMetaDataEd(Window *window, GuiMetaDataEd::GuiMetaDataEd(Window* window,
MetaDataList *md, MetaDataList* md,
const std::vector<MetaDataDecl> &mdd, const std::vector<MetaDataDecl>& mdd,
ScraperSearchParams scraperParams, ScraperSearchParams scraperParams,
const std::string & /*header*/, const std::string& /*header*/,
std::function<void()> saveCallback, std::function<void()> saveCallback,
std::function<void()> clearGameFunc, std::function<void()> clearGameFunc,
std::function<void()> deleteGameFunc) std::function<void()> deleteGameFunc)
: GuiComponent(window), mBackground(window, ":/graphics/frame.svg"), mGrid(window, glm::ivec2{1, 3}), : GuiComponent(window)
mScraperParams(scraperParams), mMetaDataDecl(mdd), mMetaData(md), mSavedCallback(saveCallback), , mBackground(window, ":/graphics/frame.svg")
mClearGameFunc(clearGameFunc), mDeleteGameFunc(deleteGameFunc), mMediaFilesUpdated(false), , mGrid(window, glm::ivec2{1, 3})
mInvalidEmulatorEntry(false) , mScraperParams(scraperParams)
, mMetaDataDecl(mdd)
, mMetaData(md)
, mSavedCallback(saveCallback)
, mClearGameFunc(clearGameFunc)
, mDeleteGameFunc(deleteGameFunc)
, mMediaFilesUpdated(false)
, mInvalidEmulatorEntry(false)
{ {
addChild(&mBackground); addChild(&mBackground);
addChild(&mGrid); addChild(&mGrid);
@ -211,11 +218,11 @@ GuiMetaDataEd::GuiMetaDataEd(Window *window,
if (mInvalidEmulatorEntry || if (mInvalidEmulatorEntry ||
scraperParams.system->getSystemEnvData()->mLaunchCommands.size() > 1) { scraperParams.system->getSystemEnvData()->mLaunchCommands.size() > 1) {
row.makeAcceptInputHandler([this, title, scraperParams, ed, updateVal, row.makeAcceptInputHandler([this, title, scraperParams, ed, updateVal,
originalValue] { originalValue] {
GuiSettings *s = nullptr; GuiSettings* s = nullptr;
bool singleEntry = bool singleEntry =
scraperParams.system->getSystemEnvData()->mLaunchCommands.size() == 1; scraperParams.system->getSystemEnvData()->mLaunchCommands.size() == 1;
if (mInvalidEmulatorEntry && singleEntry) if (mInvalidEmulatorEntry && singleEntry)
s = new GuiSettings(mWindow, "CLEAR INVALID ENTRY"); s = new GuiSettings(mWindow, "CLEAR INVALID ENTRY");
@ -226,16 +233,16 @@ GuiMetaDataEd::GuiMetaDataEd(Window *window,
return; return;
std::vector<std::pair<std::string, std::string>> launchCommands = std::vector<std::pair<std::string, std::string>> launchCommands =
scraperParams.system->getSystemEnvData()->mLaunchCommands; scraperParams.system->getSystemEnvData()->mLaunchCommands;
if (ed->getValue() != "" && mInvalidEmulatorEntry && singleEntry) if (ed->getValue() != "" && mInvalidEmulatorEntry && singleEntry)
launchCommands.push_back(std::make_pair( launchCommands.push_back(std::make_pair(
"", ViewController::EXCLAMATION_CHAR + " " + originalValue)); "", ViewController::EXCLAMATION_CHAR + " " + originalValue));
else if (ed->getValue() != "") else if (ed->getValue() != "")
launchCommands.push_back(std::make_pair( launchCommands.push_back(std::make_pair(
"", ViewController::CROSSEDCIRCLE_CHAR + " CLEAR ENTRY")); "", ViewController::CROSSEDCIRCLE_CHAR + " CLEAR ENTRY"));
for (auto entry: launchCommands) { for (auto entry : launchCommands) {
std::string selectedLabel = ed->getValue(); std::string selectedLabel = ed->getValue();
std::string label; std::string label;
ComponentListRow row; ComponentListRow row;
@ -356,7 +363,8 @@ GuiMetaDataEd::GuiMetaDataEd(Window *window,
ed->setColor(DEFAULT_TEXTCOLOR); ed->setColor(DEFAULT_TEXTCOLOR);
else else
ed->setColor(TEXTCOLOR_USERMARKED); ed->setColor(TEXTCOLOR_USERMARKED);
} else { }
else {
ed->setValue(newVal); ed->setValue(newVal);
if (newVal == originalValue) if (newVal == originalValue)
ed->setColor(DEFAULT_TEXTCOLOR); ed->setColor(DEFAULT_TEXTCOLOR);
@ -368,10 +376,11 @@ GuiMetaDataEd::GuiMetaDataEd(Window *window,
if (Settings::getInstance()->getBool("VirtualKeyboard")) { if (Settings::getInstance()->getBool("VirtualKeyboard")) {
row.makeAcceptInputHandler([this, title, ed, updateVal, multiLine] { row.makeAcceptInputHandler([this, title, ed, updateVal, multiLine] {
mWindow->pushGui(new GuiTextEditKeyboardPopup( mWindow->pushGui(new GuiTextEditKeyboardPopup(
mWindow, getHelpStyle(), title, ed->getValue(), updateVal, multiLine, mWindow, getHelpStyle(), title, ed->getValue(), updateVal, multiLine,
"apply", "APPLY CHANGES?", "", "")); "apply", "APPLY CHANGES?", "", ""));
}); });
} else { }
else {
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,

View file

@ -13,9 +13,11 @@
#include "components/MenuComponent.h" #include "components/MenuComponent.h"
#include "views/ViewController.h" #include "views/ViewController.h"
GuiOfflineGenerator::GuiOfflineGenerator(Window *window, const std::queue<FileData *> &gameQueue) GuiOfflineGenerator::GuiOfflineGenerator(Window* window, const std::queue<FileData*>& gameQueue)
: GuiComponent(window), mGameQueue(gameQueue), mBackground(window, ":/graphics/frame.svg"), : GuiComponent(window)
mGrid(window, glm::ivec2{6, 13}) , mGameQueue(gameQueue)
, mBackground(window, ":/graphics/frame.svg")
, mGrid(window, glm::ivec2{6, 13})
{ {
addChild(&mBackground); addChild(&mBackground);
addChild(&mGrid); addChild(&mGrid);

View file

@ -86,19 +86,19 @@ GuiScraperMulti::GuiScraperMulti(Window* window,
// Previously refined. // Previously refined.
if (mSearchComp->getRefinedSearch()) if (mSearchComp->getRefinedSearch())
allowRefine = true; allowRefine = true;
// Interactive mode and "Auto-accept single game matches" not enabled. // Interactive mode and "Auto-accept single game matches" not enabled.
else if (mSearchComp->getSearchType() != else if (mSearchComp->getSearchType() !=
GuiScraperSearch::ACCEPT_SINGLE_MATCHES) GuiScraperSearch::ACCEPT_SINGLE_MATCHES)
allowRefine = true; allowRefine = true;
// Interactive mode with "Auto-accept single game matches" enabled and more // Interactive mode with "Auto-accept single game matches" enabled and more
// than one result. // than one result.
else if (mSearchComp->getSearchType() == else if (mSearchComp->getSearchType() ==
GuiScraperSearch::ACCEPT_SINGLE_MATCHES && GuiScraperSearch::ACCEPT_SINGLE_MATCHES &&
mSearchComp->getScraperResultsSize() > 1) mSearchComp->getScraperResultsSize() > 1)
allowRefine = true; allowRefine = true;
// Dito but there were no games found, or the search has not been completed. // Dito but there were no games found, or the search has not been completed.
else if (mSearchComp->getSearchType() == else if (mSearchComp->getSearchType() ==
GuiScraperSearch::ACCEPT_SINGLE_MATCHES && GuiScraperSearch::ACCEPT_SINGLE_MATCHES &&
!mSearchComp->getFoundGame()) !mSearchComp->getFoundGame())
allowRefine = true; allowRefine = true;

View file

@ -37,9 +37,15 @@
#define FAILED_VERIFICATION_RETRIES 8 #define FAILED_VERIFICATION_RETRIES 8
GuiScraperSearch::GuiScraperSearch(Window *window, SearchType type, unsigned int scrapeCount) GuiScraperSearch::GuiScraperSearch(Window* window, SearchType type, unsigned int scrapeCount)
: GuiComponent(window), mGrid(window, glm::ivec2{4, 3}), mSearchType(type), mScrapeCount(scrapeCount), : GuiComponent(window)
mRefinedSearch(false), mFoundGame(false), mScrapeRatings(false), mBusyAnim(window) , mGrid(window, glm::ivec2{4, 3})
, mSearchType(type)
, mScrapeCount(scrapeCount)
, mRefinedSearch(false)
, mFoundGame(false)
, mScrapeRatings(false)
, mBusyAnim(window)
{ {
addChild(&mGrid); addChild(&mGrid);
@ -467,14 +473,14 @@ void GuiScraperSearch::updateInfoPane()
i = 0; i = 0;
if (i != -1 && static_cast<int>(mScraperResults.size()) > i) { if (i != -1 && static_cast<int>(mScraperResults.size()) > i) {
ScraperSearchResult &res = mScraperResults.at(i); ScraperSearchResult& res = mScraperResults.at(i);
mResultName->setText(Utils::String::toUpper(res.mdl.get("name"))); mResultName->setText(Utils::String::toUpper(res.mdl.get("name")));
mResultDesc->setText(Utils::String::toUpper(res.mdl.get("desc"))); mResultDesc->setText(Utils::String::toUpper(res.mdl.get("desc")));
mDescContainer->reset(); mDescContainer->reset();
mResultThumbnail->setImage(""); mResultThumbnail->setImage("");
const std::string &thumb = res.screenshotUrl.empty() ? res.coverUrl : res.screenshotUrl; const std::string& thumb = res.screenshotUrl.empty() ? res.coverUrl : res.screenshotUrl;
mScraperResults[i].thumbnailImageUrl = thumb; mScraperResults[i].thumbnailImageUrl = thumb;
// Cache the thumbnail image in mScraperResults so that we don't need to download // Cache the thumbnail image in mScraperResults so that we don't need to download
@ -547,13 +553,13 @@ bool GuiScraperSearch::input(InputConfig* config, Input input)
// Previously refined. // Previously refined.
if (mRefinedSearch) if (mRefinedSearch)
allowRefine = true; allowRefine = true;
// Interactive mode and "Auto-accept single game matches" not enabled. // Interactive mode and "Auto-accept single game matches" not enabled.
else if (mSearchType != ACCEPT_SINGLE_MATCHES) else if (mSearchType != ACCEPT_SINGLE_MATCHES)
allowRefine = true; allowRefine = true;
// Interactive mode with "Auto-accept single game matches" enabled and more than one result. // Interactive mode with "Auto-accept single game matches" enabled and more than one result.
else if (mSearchType == ACCEPT_SINGLE_MATCHES && mScraperResults.size() > 1) else if (mSearchType == ACCEPT_SINGLE_MATCHES && mScraperResults.size() > 1)
allowRefine = true; allowRefine = true;
// Dito but there were no games found, or the search has not been completed. // Dito but there were no games found, or the search has not been completed.
else if (mSearchType == ACCEPT_SINGLE_MATCHES && !mFoundGame) else if (mSearchType == ACCEPT_SINGLE_MATCHES && !mFoundGame)
allowRefine = true; allowRefine = true;
@ -784,15 +790,16 @@ void GuiScraperSearch::updateThumbnail()
} }
} }
void GuiScraperSearch::openInputScreen(ScraperSearchParams &params) { void GuiScraperSearch::openInputScreen(ScraperSearchParams& params)
{
auto searchForFunc = [&](std::string name) { auto searchForFunc = [&](std::string name) {
// Trim leading and trailing whitespaces. // Trim leading and trailing whitespaces.
name.erase(name.begin(), std::find_if(name.begin(), name.end(), [](char c) { name.erase(name.begin(), std::find_if(name.begin(), name.end(), [](char c) {
return !std::isspace(static_cast<unsigned char>(c)); return !std::isspace(static_cast<unsigned char>(c));
})); }));
name.erase(std::find_if(name.rbegin(), name.rend(), name.erase(std::find_if(name.rbegin(), name.rend(),
[](char c) { return !std::isspace(static_cast<unsigned char>(c)); }) [](char c) { return !std::isspace(static_cast<unsigned char>(c)); })
.base(), .base(),
name.end()); name.end());
stop(); stop();
@ -810,7 +817,8 @@ void GuiScraperSearch::openInputScreen(ScraperSearchParams &params) {
// regardless of whether the entry is an arcade game and TheGamesDB is used. // regardless of whether the entry is an arcade game and TheGamesDB is used.
if (Settings::getInstance()->getBool("ScraperSearchMetadataName")) { if (Settings::getInstance()->getBool("ScraperSearchMetadataName")) {
searchString = Utils::String::removeParenthesis(params.game->metadata.get("name")); searchString = Utils::String::removeParenthesis(params.game->metadata.get("name"));
} else { }
else {
// If searching based on the actual file name, then expand to the full game name // If searching based on the actual file name, then expand to the full game name
// in case the scraper is set to TheGamesDB and it's an arcade game. This is // in case the scraper is set to TheGamesDB and it's an arcade game. This is
// required as TheGamesDB does not support searches using the short MAME names. // required as TheGamesDB does not support searches using the short MAME names.
@ -820,7 +828,8 @@ void GuiScraperSearch::openInputScreen(ScraperSearchParams &params) {
else else
searchString = params.game->getCleanName(); searchString = params.game->getCleanName();
} }
} else { }
else {
searchString = params.nameOverride; searchString = params.nameOverride;
} }
@ -828,7 +837,8 @@ void GuiScraperSearch::openInputScreen(ScraperSearchParams &params) {
mWindow->pushGui(new GuiTextEditKeyboardPopup(mWindow, getHelpStyle(), "REFINE SEARCH", mWindow->pushGui(new GuiTextEditKeyboardPopup(mWindow, getHelpStyle(), "REFINE SEARCH",
searchString, searchForFunc, false, "SEARCH", searchString, searchForFunc, false, "SEARCH",
"SEARCH USING REFINED NAME?")); "SEARCH USING REFINED NAME?"));
} else { }
else {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "REFINE SEARCH", mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "REFINE SEARCH",
searchString, searchForFunc, false, "SEARCH", searchString, searchForFunc, false, "SEARCH",
"SEARCH USING REFINED NAME?")); "SEARCH USING REFINED NAME?"));
@ -918,7 +928,8 @@ bool GuiScraperSearch::saveMetadata(const ScraperSearchResult& result,
return metadataUpdated; return metadataUpdated;
} }
std::vector<HelpPrompt> GuiScraperSearch::getHelpPrompts() { std::vector<HelpPrompt> GuiScraperSearch::getHelpPrompts()
{
std::vector<HelpPrompt> prompts; std::vector<HelpPrompt> prompts;
prompts.push_back(HelpPrompt("y", "refine search")); prompts.push_back(HelpPrompt("y", "refine search"));

View file

@ -64,19 +64,21 @@ public:
mAcceptCallback = acceptCallback; mAcceptCallback = acceptCallback;
} }
void setSkipCallback(const std::function<void()> &skipCallback) { void setSkipCallback(const std::function<void()>& skipCallback)
{
mSkipCallback = skipCallback; mSkipCallback = skipCallback;
} }
void setCancelCallback(const std::function<void()> &cancelCallback) { void setCancelCallback(const std::function<void()>& cancelCallback)
{
mCancelCallback = cancelCallback; mCancelCallback = cancelCallback;
} }
bool input(InputConfig *config, Input input) override; bool input(InputConfig* config, Input input) override;
void update(int deltaTime) override; void update(int deltaTime) override;
void render(const glm::mat4 &parentTrans) override; void render(const glm::mat4& parentTrans) override;
std::vector<HelpPrompt> getHelpPrompts() override; std::vector<HelpPrompt> getHelpPrompts() override;
@ -84,7 +86,8 @@ public:
void onSizeChanged() override; void onSizeChanged() override;
void decreaseScrapeCount() { void decreaseScrapeCount()
{
if (mScrapeCount > 0) if (mScrapeCount > 0)
mScrapeCount--; mScrapeCount--;
} }
@ -95,7 +98,7 @@ public:
bool getFoundGame() { return mFoundGame; } bool getFoundGame() { return mFoundGame; }
const std::string &getNameOverride() { return mLastSearch.nameOverride; } const std::string& getNameOverride() { return mLastSearch.nameOverride; }
void onFocusGained() override { mGrid.onFocusGained(); } void onFocusGained() override { mGrid.onFocusGained(); }

View file

@ -21,11 +21,21 @@
#include "views/ViewController.h" #include "views/ViewController.h"
#include "views/gamelist/IGameListView.h" #include "views/gamelist/IGameListView.h"
GuiSettings::GuiSettings(Window *window, std::string title) GuiSettings::GuiSettings(Window* window, std::string title)
: GuiComponent(window), mMenu(window, title), mGoToSystem(nullptr), mNeedsSaving(false), : GuiComponent(window)
mNeedsReloadHelpPrompts(false), mNeedsCollectionsUpdate(false), mNeedsSorting(false), , mMenu(window, title)
mNeedsSortingCollections(false), mNeedsResetFilters(false), mNeedsReloading(false), mNeedsGoToStart(false), , mGoToSystem(nullptr)
mNeedsGoToSystem(false), mNeedsGoToGroupedCollections(false), mInvalidateCachedBackground(false) , mNeedsSaving(false)
, mNeedsReloadHelpPrompts(false)
, mNeedsCollectionsUpdate(false)
, mNeedsSorting(false)
, mNeedsSortingCollections(false)
, mNeedsResetFilters(false)
, mNeedsReloading(false)
, mNeedsGoToStart(false)
, mNeedsGoToSystem(false)
, mNeedsGoToGroupedCollections(false)
, mInvalidateCachedBackground(false)
{ {
addChild(&mMenu); addChild(&mMenu);
mMenu.addButton("BACK", "back", [this] { delete this; }); mMenu.addButton("BACK", "back", [this] { delete this; });
@ -174,10 +184,12 @@ void GuiSettings::addEditableTextComponent(const std::string label,
else if (isPassword && newVal == "") { else if (isPassword && newVal == "") {
ed->setValue(""); ed->setValue("");
ed->setHiddenValue(""); ed->setHiddenValue("");
} else if (isPassword) { }
else if (isPassword) {
ed->setValue("********"); ed->setValue("********");
ed->setHiddenValue(newVal); ed->setHiddenValue(newVal);
} else { }
else {
ed->setValue(newVal); ed->setValue(newVal);
} }
}; };
@ -187,13 +199,14 @@ void GuiSettings::addEditableTextComponent(const std::string label,
// Never display the value if it's a password, instead set it to blank. // Never display the value if it's a password, instead set it to blank.
if (isPassword) if (isPassword)
mWindow->pushGui(new GuiTextEditKeyboardPopup( mWindow->pushGui(new GuiTextEditKeyboardPopup(
mWindow, getHelpStyle(), label, "", updateVal, false, "SAVE", "SAVE CHANGES?")); mWindow, getHelpStyle(), label, "", updateVal, false, "SAVE", "SAVE CHANGES?"));
else else
mWindow->pushGui(new GuiTextEditKeyboardPopup(mWindow, getHelpStyle(), label, mWindow->pushGui(new GuiTextEditKeyboardPopup(mWindow, getHelpStyle(), label,
ed->getValue(), updateVal, false, ed->getValue(), updateVal, false,
"SAVE", "SAVE CHANGES?")); "SAVE", "SAVE CHANGES?"));
}); });
} else { }
else {
row.makeAcceptInputHandler([this, label, ed, updateVal, isPassword] { row.makeAcceptInputHandler([this, label, ed, updateVal, isPassword] {
if (isPassword) if (isPassword)
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), label, "", updateVal, mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), label, "", updateVal,

View file

@ -147,7 +147,8 @@ void thegamesdb_generate_json_scraper_requests(
// using this regardless of whether the entry is an arcade game. // using this regardless of whether the entry is an arcade game.
if (Settings::getInstance()->getBool("ScraperSearchMetadataName")) { if (Settings::getInstance()->getBool("ScraperSearchMetadataName")) {
cleanName = Utils::String::removeParenthesis(params.game->metadata.get("name")); cleanName = Utils::String::removeParenthesis(params.game->metadata.get("name"));
} else { }
else {
// If not searching based on the metadata name, then check whether it's an // If not searching based on the metadata name, then check whether it's an
// arcade game and if so expand to the full game name. This is required as // arcade game and if so expand to the full game name. This is required as
// TheGamesDB has issues with searching using the short MAME names. // TheGamesDB has issues with searching using the short MAME names.
@ -164,10 +165,10 @@ void thegamesdb_generate_json_scraper_requests(
return !std::isspace(static_cast<unsigned char>(c)); return !std::isspace(static_cast<unsigned char>(c));
})); }));
cleanName.erase( cleanName.erase(
std::find_if(cleanName.rbegin(), cleanName.rend(), std::find_if(cleanName.rbegin(), cleanName.rend(),
[](char c) { return !std::isspace(static_cast<unsigned char>(c)); }) [](char c) { return !std::isspace(static_cast<unsigned char>(c)); })
.base(), .base(),
cleanName.end()); cleanName.end());
path += "/Games/ByGameName?" + apiKey + path += "/Games/ByGameName?" + apiKey +
"&fields=players,publishers,genres,overview,last_updated,rating," "&fields=players,publishers,genres,overview,last_updated,rating,"
@ -456,7 +457,7 @@ void TheGamesDBJSONRequest::process(const std::unique_ptr<HttpReq>& req,
if (doc.HasMember("remaining_monthly_allowance") && doc.HasMember("extra_allowance")) { if (doc.HasMember("remaining_monthly_allowance") && doc.HasMember("extra_allowance")) {
for (size_t i = 0; i < results.size(); i++) { for (size_t i = 0; i < results.size(); i++) {
results[i].scraperRequestAllowance = results[i].scraperRequestAllowance =
doc["remaining_monthly_allowance"].GetInt() + doc["extra_allowance"].GetInt(); doc["remaining_monthly_allowance"].GetInt() + doc["extra_allowance"].GetInt();
} }
LOG(LogDebug) << "TheGamesDBJSONRequest::process(): " LOG(LogDebug) << "TheGamesDBJSONRequest::process(): "
"Remaining monthly scraping allowance: " "Remaining monthly scraping allowance: "

View file

@ -17,12 +17,32 @@
#define FADE_IN_TIME 650 #define FADE_IN_TIME 650
DetailedGameListView::DetailedGameListView(Window* window, FileData* root) DetailedGameListView::DetailedGameListView(Window* window, FileData* root)
: BasicGameListView(window, root), mThumbnail(window), mMarquee(window), mImage(window), mLblRating(window), : BasicGameListView(window, root)
mLblReleaseDate(window), mLblDeveloper(window), mLblPublisher(window), mLblGenre(window), mLblPlayers(window), , mThumbnail(window)
mLblLastPlayed(window), mLblPlayCount(window), mBadges(window), mRating(window), mReleaseDate(window), , mMarquee(window)
mDeveloper(window), , mImage(window)
mPublisher(window), mGenre(window), mPlayers(window), mLastPlayed(window), mPlayCount(window), mName(window), , mLblRating(window)
mDescContainer(window), mDescription(window), mGamelistInfo(window), mLastUpdated(nullptr) , mLblReleaseDate(window)
, mLblDeveloper(window)
, mLblPublisher(window)
, mLblGenre(window)
, mLblPlayers(window)
, mLblLastPlayed(window)
, mLblPlayCount(window)
, mBadges(window)
, mRating(window)
, mReleaseDate(window)
, mDeveloper(window)
, mPublisher(window)
, mGenre(window)
, mPlayers(window)
, mLastPlayed(window)
, mPlayCount(window)
, mName(window)
, mDescContainer(window)
, mDescription(window)
, mGamelistInfo(window)
, mLastUpdated(nullptr)
{ {
const float padding = 0.01f; const float padding = 0.01f;
@ -111,7 +131,8 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root)
initMDValues(); initMDValues();
} }
void DetailedGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme) { void DetailedGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
{
BasicGameListView::onThemeChanged(theme); BasicGameListView::onThemeChanged(theme);
using namespace ThemeFlags; using namespace ThemeFlags;
@ -124,21 +145,21 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& them
mName.applyTheme(theme, getName(), "md_name", ALL); mName.applyTheme(theme, getName(), "md_name", ALL);
initMDLabels(); initMDLabels();
std::vector<TextComponent *> labels = getMDLabels(); std::vector<TextComponent*> labels = getMDLabels();
assert(labels.size() == 8); assert(labels.size() == 8);
std::vector<std::string> lblElements = { std::vector<std::string> lblElements = {
"md_lbl_rating", "md_lbl_releasedate", "md_lbl_developer", "md_lbl_publisher", "md_lbl_rating", "md_lbl_releasedate", "md_lbl_developer", "md_lbl_publisher",
"md_lbl_genre", "md_lbl_players", "md_lbl_lastplayed", "md_lbl_playcount"}; "md_lbl_genre", "md_lbl_players", "md_lbl_lastplayed", "md_lbl_playcount"};
for (unsigned int i = 0; i < labels.size(); i++) for (unsigned int i = 0; i < labels.size(); i++)
labels[i]->applyTheme(theme, getName(), lblElements[i], ALL); labels[i]->applyTheme(theme, getName(), lblElements[i], ALL);
initMDValues(); initMDValues();
std::vector<GuiComponent *> values = getMDValues(); std::vector<GuiComponent*> values = getMDValues();
assert(values.size() == 9); assert(values.size() == 9);
std::vector<std::string> valElements = {"md_rating", "md_releasedate", "md_developer", std::vector<std::string> valElements = {"md_rating", "md_releasedate", "md_developer",
"md_publisher", "md_genre", "md_players", "md_publisher", "md_genre", "md_players",
"md_badges", "md_lastplayed", "md_playcount"}; "md_badges", "md_lastplayed", "md_playcount"};
for (unsigned int i = 0; i < values.size(); i++) for (unsigned int i = 0; i < values.size(); i++)
values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT); values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT);
@ -402,7 +423,8 @@ void DetailedGameListView::updateInfoPanel()
mLastPlayed.setValue(file->metadata.get("lastplayed")); mLastPlayed.setValue(file->metadata.get("lastplayed"));
mPlayCount.setValue(file->metadata.get("playcount")); mPlayCount.setValue(file->metadata.get("playcount"));
} }
} else if (file->getType() == FOLDER) { }
else if (file->getType() == FOLDER) {
if (!hideMetaDataFields) { if (!hideMetaDataFields) {
mLastPlayed.setValue(file->metadata.get("lastplayed")); mLastPlayed.setValue(file->metadata.get("lastplayed"));
mLblPlayCount.setVisible(false); mLblPlayCount.setVisible(false);

View file

@ -20,12 +20,31 @@
#define FADE_IN_TIME 650 #define FADE_IN_TIME 650
GridGameListView::GridGameListView(Window* window, FileData* root) GridGameListView::GridGameListView(Window* window, FileData* root)
: ISimpleGameListView(window, root), mGrid(window), mMarquee(window), mImage(window), mLblRating(window), : ISimpleGameListView(window, root)
mLblReleaseDate(window), mLblDeveloper(window), mLblPublisher(window), mLblGenre(window), mLblPlayers(window), , mGrid(window)
mLblLastPlayed(window), mLblPlayCount(window), mBadges(window), mRating(window), mReleaseDate(window), , mMarquee(window)
mDeveloper(window), , mImage(window)
mPublisher(window), mGenre(window), mPlayers(window), mLastPlayed(window), mPlayCount(window), mName(window), , mLblRating(window)
mDescContainer(window), mDescription(window), mGamelistInfo(window) , mLblReleaseDate(window)
, mLblDeveloper(window)
, mLblPublisher(window)
, mLblGenre(window)
, mLblPlayers(window)
, mLblLastPlayed(window)
, mLblPlayCount(window)
, mBadges(window)
, mRating(window)
, mReleaseDate(window)
, mDeveloper(window)
, mPublisher(window)
, mGenre(window)
, mPlayers(window)
, mLastPlayed(window)
, mPlayCount(window)
, mName(window)
, mDescContainer(window)
, mDescription(window)
, mGamelistInfo(window)
{ {
const float padding = 0.01f; const float padding = 0.01f;

View file

@ -68,12 +68,12 @@ protected:
ImageGridComponent<FileData*> mGrid; ImageGridComponent<FileData*> mGrid;
// Points to the first game in the list, i.e. the first entry which is of the type 'GAME'. // Points to the first game in the list, i.e. the first entry which is of the type 'GAME'.
FileData *firstGameEntry; FileData* firstGameEntry;
private: private:
void updateInfoPanel(); void updateInfoPanel();
const std::string getImagePath(FileData *file); const std::string getImagePath(FileData* file);
void initMDLabels(); void initMDLabels();

View file

@ -20,7 +20,7 @@ class VideoComponent;
class VideoGameListView : public BasicGameListView class VideoGameListView : public BasicGameListView
{ {
public: public:
VideoGameListView(Window *window, FileData *root); VideoGameListView(Window* window, FileData* root);
virtual ~VideoGameListView() noexcept; virtual ~VideoGameListView() noexcept;

View file

@ -16,11 +16,22 @@
#include <algorithm> #include <algorithm>
GuiComponent::GuiComponent(Window *window) GuiComponent::GuiComponent(Window* window)
: mWindow(window), mParent(nullptr), mOpacity(255), mColor(0), mSaturation(1.0f), mColorShift(0), : mWindow(window)
mColorShiftEnd(0), , mParent(nullptr)
mPosition({}), mOrigin({}), mRotationOrigin(0.5f, 0.5f), mSize({}), mIsProcessing(false), mVisible(true), , mOpacity(255)
mEnabled(true), mTransform(Renderer::getIdentity()) , mColor(0)
, mSaturation(1.0f)
, mColorShift(0)
, mColorShiftEnd(0)
, mPosition({})
, mOrigin({})
, mRotationOrigin(0.5f, 0.5f)
, mSize({})
, mIsProcessing(false)
, mVisible(true)
, mEnabled(true)
, mTransform(Renderer::getIdentity())
{ {
for (unsigned char i = 0; i < MAX_ANIMATIONS; i++) for (unsigned char i = 0; i < MAX_ANIMATIONS; i++)
mAnimationMap[i] = nullptr; mAnimationMap[i] = nullptr;

View file

@ -37,7 +37,7 @@ class Window;
class GuiComponent class GuiComponent
{ {
public: public:
GuiComponent(Window *window); GuiComponent(Window* window);
virtual ~GuiComponent() noexcept; virtual ~GuiComponent() noexcept;
@ -231,15 +231,15 @@ public:
const static unsigned char MAX_ANIMATIONS = 4; const static unsigned char MAX_ANIMATIONS = 4;
protected: protected:
void renderChildren(const glm::mat4 &transform) const; void renderChildren(const glm::mat4& transform) const;
void updateSelf(int deltaTime); // Updates animations. void updateSelf(int deltaTime); // Updates animations.
void updateChildren(int deltaTime); // Updates animations. void updateChildren(int deltaTime); // Updates animations.
Window *mWindow; Window* mWindow;
GuiComponent *mParent; GuiComponent* mParent;
std::vector<GuiComponent *> mChildren; std::vector<GuiComponent*> mChildren;
unsigned char mOpacity; unsigned char mOpacity;
unsigned int mColor; unsigned int mColor;

View file

@ -80,7 +80,7 @@ private:
static CURLM* s_multi_handle; static CURLM* s_multi_handle;
Status mStatus; Status mStatus;
CURL *mHandle; CURL* mHandle;
std::stringstream mContent; std::stringstream mContent;
std::string mErrorMsg; std::string mErrorMsg;

View file

@ -14,11 +14,12 @@
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
// Available slot definitions. // Available slot definitions.
std::vector<std::string> BadgesComponent::mSlots = {SLOT_FAVORITE, SLOT_COMPLETED, SLOT_KIDS, SLOT_BROKEN, std::vector<std::string> BadgesComponent::mSlots = {SLOT_FAVORITE, SLOT_COMPLETED, SLOT_KIDS,
SLOT_ALTERNATIVE_EMULATOR}; SLOT_BROKEN, SLOT_ALTERNATIVE_EMULATOR};
BadgesComponent::BadgesComponent(Window *window) BadgesComponent::BadgesComponent(Window* window)
: FlexboxComponent(window) { : FlexboxComponent(window)
{
mBadgeIcons = std::map<std::string, std::string>(); mBadgeIcons = std::map<std::string, std::string>();
mBadgeIcons[SLOT_FAVORITE] = ":/graphics/badge_favorite.svg"; mBadgeIcons[SLOT_FAVORITE] = ":/graphics/badge_favorite.svg";
@ -45,16 +46,17 @@ BadgesComponent::BadgesComponent(Window *window)
mImageComponents.insert({SLOT_ALTERNATIVE_EMULATOR, mImageAltEmu}); mImageComponents.insert({SLOT_ALTERNATIVE_EMULATOR, mImageAltEmu});
} }
BadgesComponent::~BadgesComponent() noexcept { BadgesComponent::~BadgesComponent() noexcept
for (GuiComponent *c: mChildren) {
for (GuiComponent* c : mChildren)
c->clearChildren(); c->clearChildren();
clearChildren(); clearChildren();
mBadgeIcons.clear(); mBadgeIcons.clear();
mImageComponents.clear(); mImageComponents.clear();
} }
void BadgesComponent::setValue(const std::string& value)
void BadgesComponent::setValue(const std::string &value) { {
mChildren.clear(); mChildren.clear();
if (!value.empty()) { if (!value.empty()) {
std::string temp; std::string temp;
@ -94,7 +96,8 @@ void BadgesComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
bool imgChanged = false; bool imgChanged = false;
for (auto& slot : mSlots) { for (auto& slot : mSlots) {
if (properties & PATH && elem->has(slot) && mBadgeIcons[slot] != elem->get<std::string>(slot)) { if (properties & PATH && elem->has(slot) &&
mBadgeIcons[slot] != elem->get<std::string>(slot)) {
mBadgeIcons[slot] = elem->get<std::string>(slot); mBadgeIcons[slot] = elem->get<std::string>(slot);
mImageComponents.find(slot)->second.setImage(mBadgeIcons[slot], false, true, true); mImageComponents.find(slot)->second.setImage(mBadgeIcons[slot], false, true, true);
imgChanged = true; imgChanged = true;

View file

@ -27,16 +27,16 @@ class TextureResource;
class BadgesComponent : public FlexboxComponent class BadgesComponent : public FlexboxComponent
{ {
public: public:
BadgesComponent(Window *window); BadgesComponent(Window* window);
~BadgesComponent() noexcept; ~BadgesComponent() noexcept;
std::string getValue() const override; std::string getValue() const override;
// Should be a list of strings. // Should be a list of strings.
void setValue(const std::string &value) override; void setValue(const std::string& value) override;
virtual void applyTheme(const std::shared_ptr<ThemeData> &theme, virtual void applyTheme(const std::shared_ptr<ThemeData>& theme,
const std::string &view, const std::string& view,
const std::string &element, const std::string& element,
unsigned int properties) override; unsigned int properties) override;
virtual std::vector<HelpPrompt> getHelpPrompts() override; virtual std::vector<HelpPrompt> getHelpPrompts() override;

View file

@ -12,15 +12,24 @@
#include "resources/Font.h" #include "resources/Font.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
ButtonComponent::ButtonComponent(Window *window, ButtonComponent::ButtonComponent(Window* window,
const std::string &text, const std::string& text,
const std::string &helpText, const std::string& helpText,
const std::function<void()> &func, const std::function<void()>& func,
bool upperCase, bool upperCase,
bool flatStyle) bool flatStyle)
: GuiComponent{window}, mBox{window, ":/graphics/button.svg"}, mFont{Font::get(FONT_SIZE_MEDIUM)}, mPadding{{}}, : GuiComponent{window}
mFocused{false}, mEnabled{true}, mFlatStyle{flatStyle}, mTextColorFocused{0xFFFFFFFF}, , mBox{window, ":/graphics/button.svg"}
mTextColorUnfocused{0x777777FF}, mFlatColorFocused{0x878787FF}, mFlatColorUnfocused{0x60606025} { , mFont{Font::get(FONT_SIZE_MEDIUM)}
, mPadding{{}}
, mFocused{false}
, mEnabled{true}
, mFlatStyle{flatStyle}
, mTextColorFocused{0xFFFFFFFF}
, mTextColorUnfocused{0x777777FF}
, mFlatColorFocused{0x878787FF}
, mFlatColorUnfocused{0x60606025}
{
setPressedFunc(func); setPressedFunc(func);
setText(text, helpText, upperCase); setText(text, helpText, upperCase);
@ -28,7 +37,8 @@ ButtonComponent::ButtonComponent(Window *window,
updateImage(); updateImage();
} }
void ButtonComponent::onSizeChanged() { void ButtonComponent::onSizeChanged()
{
if (mFlatStyle) if (mFlatStyle)
return; return;
@ -39,24 +49,27 @@ void ButtonComponent::onSizeChanged() {
glm::vec2{-cornerSize.x * 2.0f, -cornerSize.y * 2.0f}); glm::vec2{-cornerSize.x * 2.0f, -cornerSize.y * 2.0f});
} }
void ButtonComponent::onFocusGained() { void ButtonComponent::onFocusGained()
{
mFocused = true; mFocused = true;
if (!mFlatStyle) if (!mFlatStyle)
updateImage(); updateImage();
} }
void ButtonComponent::onFocusLost() { void ButtonComponent::onFocusLost()
{
mFocused = false; mFocused = false;
if (!mFlatStyle) if (!mFlatStyle)
updateImage(); updateImage();
} }
void ButtonComponent::setText(const std::string &text, const std::string &helpText, bool upperCase) { void ButtonComponent::setText(const std::string& text, const std::string& helpText, bool upperCase)
{
mText = upperCase ? Utils::String::toUpper(text) : text; mText = upperCase ? Utils::String::toUpper(text) : text;
mHelpText = helpText; mHelpText = helpText;
mTextCache = mTextCache =
std::unique_ptr<TextCache>(mFont->buildTextCache(mText, 0.0f, 0.0f, getCurTextColor())); std::unique_ptr<TextCache>(mFont->buildTextCache(mText, 0.0f, 0.0f, getCurTextColor()));
float minWidth = mFont->sizeText("DELETE").x + (12.0f * Renderer::getScreenWidthModifier()); float minWidth = mFont->sizeText("DELETE").x + (12.0f * Renderer::getScreenWidthModifier());
setSize(std::max(mTextCache->metrics.size.x + (12.0f * Renderer::getScreenWidthModifier()), setSize(std::max(mTextCache->metrics.size.x + (12.0f * Renderer::getScreenWidthModifier()),
@ -66,13 +79,15 @@ void ButtonComponent::setText(const std::string &text, const std::string &helpTe
updateHelpPrompts(); updateHelpPrompts();
} }
void ButtonComponent::setEnabled(bool state) { void ButtonComponent::setEnabled(bool state)
{
mEnabled = state; mEnabled = state;
if (!mFlatStyle) if (!mFlatStyle)
updateImage(); updateImage();
} }
void ButtonComponent::setPadding(const glm::vec4 padding) { void ButtonComponent::setPadding(const glm::vec4 padding)
{
if (mPadding == padding) if (mPadding == padding)
return; return;
@ -80,7 +95,8 @@ void ButtonComponent::setPadding(const glm::vec4 padding) {
onSizeChanged(); onSizeChanged();
} }
bool ButtonComponent::input(InputConfig *config, Input input) { bool ButtonComponent::input(InputConfig* config, Input input)
{
if (config->isMappedTo("a", input) && input.value != 0) { if (config->isMappedTo("a", input) && input.value != 0) {
if (mPressedFunc && mEnabled) if (mPressedFunc && mEnabled)
mPressedFunc(); mPressedFunc();
@ -90,7 +106,8 @@ bool ButtonComponent::input(InputConfig *config, Input input) {
return GuiComponent::input(config, input); return GuiComponent::input(config, input);
} }
void ButtonComponent::render(const glm::mat4 &parentTrans) { void ButtonComponent::render(const glm::mat4& parentTrans)
{
glm::mat4 trans{parentTrans * getTransform()}; glm::mat4 trans{parentTrans * getTransform()};
if (mFlatStyle) { if (mFlatStyle) {
@ -99,13 +116,15 @@ void ButtonComponent::render(const glm::mat4 &parentTrans) {
Renderer::drawRect(mPadding.x, mPadding.y, mSize.x - mPadding.x - mPadding.z, Renderer::drawRect(mPadding.x, mPadding.y, mSize.x - mPadding.x - mPadding.z,
mSize.y - mPadding.y - mPadding.w, mFlatColorFocused, mSize.y - mPadding.y - mPadding.w, mFlatColorFocused,
mFlatColorFocused); mFlatColorFocused);
} else { }
else {
Renderer::setMatrix(trans); Renderer::setMatrix(trans);
Renderer::drawRect(mPadding.x, mPadding.y, mSize.x - mPadding.x - mPadding.z, Renderer::drawRect(mPadding.x, mPadding.y, mSize.x - mPadding.x - mPadding.z,
mSize.y - mPadding.y - mPadding.w, mFlatColorUnfocused, mSize.y - mPadding.y - mPadding.w, mFlatColorUnfocused,
mFlatColorUnfocused); mFlatColorUnfocused);
} }
} else { }
else {
mBox.render(trans); mBox.render(trans);
} }
@ -131,20 +150,23 @@ void ButtonComponent::render(const glm::mat4 &parentTrans) {
renderChildren(trans); renderChildren(trans);
} }
std::vector<HelpPrompt> ButtonComponent::getHelpPrompts() { std::vector<HelpPrompt> ButtonComponent::getHelpPrompts()
{
std::vector<HelpPrompt> prompts; std::vector<HelpPrompt> prompts;
prompts.push_back(HelpPrompt("a", mHelpText.empty() ? mText.c_str() : mHelpText.c_str())); prompts.push_back(HelpPrompt("a", mHelpText.empty() ? mText.c_str() : mHelpText.c_str()));
return prompts; return prompts;
} }
unsigned int ButtonComponent::getCurTextColor() const { unsigned int ButtonComponent::getCurTextColor() const
{
if (!mFocused) if (!mFocused)
return mTextColorUnfocused; return mTextColorUnfocused;
else else
return mTextColorFocused; return mTextColorFocused;
} }
void ButtonComponent::updateImage() { void ButtonComponent::updateImage()
{
if (!mEnabled || !mPressedFunc) { if (!mEnabled || !mPressedFunc) {
mBox.setImagePath(":/graphics/button_filled.svg"); mBox.setImagePath(":/graphics/button_filled.svg");
mBox.setCenterColor(0x770000FF); mBox.setCenterColor(0x770000FF);

View file

@ -14,12 +14,13 @@
class TextCache; class TextCache;
class ButtonComponent : public GuiComponent { class ButtonComponent : public GuiComponent
{
public: public:
ButtonComponent(Window *window, ButtonComponent(Window* window,
const std::string &text = "", const std::string& text = "",
const std::string &helpText = "", const std::string& helpText = "",
const std::function<void()> &func = nullptr, const std::function<void()>& func = nullptr,
bool upperCase = true, bool upperCase = true,
bool flatStyle = false); bool flatStyle = false);
@ -29,9 +30,9 @@ public:
void onFocusLost() override; void onFocusLost() override;
void setText(const std::string &text, const std::string &helpText, bool upperCase = true); void setText(const std::string& text, const std::string& helpText, bool upperCase = true);
const std::string &getText() const { return mText; } const std::string& getText() const { return mText; }
void setPressedFunc(std::function<void()> f) { mPressedFunc = f; } void setPressedFunc(std::function<void()> f) { mPressedFunc = f; }
@ -45,11 +46,11 @@ public:
void setFlatColorUnfocused(unsigned int color) { mFlatColorUnfocused = color; } void setFlatColorUnfocused(unsigned int color) { mFlatColorUnfocused = color; }
const std::function<void()> &getPressedFunc() const { return mPressedFunc; } const std::function<void()>& getPressedFunc() const { return mPressedFunc; }
bool input(InputConfig *config, Input input) override; bool input(InputConfig* config, Input input) override;
void render(const glm::mat4 &parentTrans) override; void render(const glm::mat4& parentTrans) override;
virtual std::vector<HelpPrompt> getHelpPrompts() override; virtual std::vector<HelpPrompt> getHelpPrompts() override;

View file

@ -245,7 +245,7 @@ const ComponentGrid::GridEntry* ComponentGrid::getCellAt(int x, int y) const
bool ComponentGrid::input(InputConfig* config, Input input) bool ComponentGrid::input(InputConfig* config, Input input)
{ {
const GridEntry *cursorEntry = getCellAt(mCursor); const GridEntry* cursorEntry = getCellAt(mCursor);
if (cursorEntry && cursorEntry->component->input(config, input)) if (cursorEntry && cursorEntry->component->input(config, input))
return true; return true;
@ -287,11 +287,12 @@ void ComponentGrid::resetCursor()
} }
} }
bool ComponentGrid::moveCursor(glm::ivec2 dir) { bool ComponentGrid::moveCursor(glm::ivec2 dir)
{
assert(dir.x || dir.y); assert(dir.x || dir.y);
const glm::ivec2 origCursor{mCursor}; const glm::ivec2 origCursor{mCursor};
const GridEntry *currentCursorEntry = getCellAt(mCursor); const GridEntry* currentCursorEntry = getCellAt(mCursor);
glm::ivec2 searchAxis(dir.x == 0, dir.y == 0); glm::ivec2 searchAxis(dir.x == 0, dir.y == 0);
// Logic to handle entries that span several cells. // Logic to handle entries that span several cells.
@ -325,7 +326,7 @@ bool ComponentGrid::moveCursor(glm::ivec2 dir) {
while (mCursor.x >= 0 && mCursor.y >= 0 && mCursor.x < mGridSize.x && mCursor.y < mGridSize.y) { while (mCursor.x >= 0 && mCursor.y >= 0 && mCursor.x < mGridSize.x && mCursor.y < mGridSize.y) {
mCursor = mCursor + dir; mCursor = mCursor + dir;
glm::ivec2 curDirPos{mCursor}; glm::ivec2 curDirPos{mCursor};
const GridEntry *cursorEntry; const GridEntry* cursorEntry;
// Spread out on search axis+ // Spread out on search axis+
while (mCursor.x < mGridSize.x && mCursor.y < mGridSize.y && mCursor.x >= 0 && while (mCursor.x < mGridSize.x && mCursor.y < mGridSize.y && mCursor.x >= 0 &&
@ -367,7 +368,8 @@ bool ComponentGrid::moveCursor(glm::ivec2 dir) {
return false; return false;
} }
void ComponentGrid::moveCursorTo(int xPos, int yPos, bool selectLeftCell) { void ComponentGrid::moveCursorTo(int xPos, int yPos, bool selectLeftCell)
{
const glm::ivec2 origCursor{mCursor}; const glm::ivec2 origCursor{mCursor};
if (xPos != -1) if (xPos != -1)
@ -375,7 +377,7 @@ void ComponentGrid::moveCursorTo(int xPos, int yPos, bool selectLeftCell) {
if (yPos != -1) if (yPos != -1)
mCursor.y = yPos; mCursor.y = yPos;
const GridEntry *currentCursorEntry = getCellAt(mCursor); const GridEntry* currentCursorEntry = getCellAt(mCursor);
// If requested, select the leftmost cell of entries wider than 1 cell. // If requested, select the leftmost cell of entries wider than 1 cell.
if (selectLeftCell && mCursor.x > currentCursorEntry->pos.x) if (selectLeftCell && mCursor.x > currentCursorEntry->pos.x)
@ -384,14 +386,16 @@ void ComponentGrid::moveCursorTo(int xPos, int yPos, bool selectLeftCell) {
onCursorMoved(origCursor, mCursor); onCursorMoved(origCursor, mCursor);
} }
void ComponentGrid::onFocusLost() { void ComponentGrid::onFocusLost()
const GridEntry *cursorEntry = getCellAt(mCursor); {
const GridEntry* cursorEntry = getCellAt(mCursor);
if (cursorEntry) if (cursorEntry)
cursorEntry->component->onFocusLost(); cursorEntry->component->onFocusLost();
} }
void ComponentGrid::onFocusGained() { void ComponentGrid::onFocusGained()
const GridEntry *cursorEntry = getCellAt(mCursor); {
const GridEntry* cursorEntry = getCellAt(mCursor);
if (cursorEntry) if (cursorEntry)
cursorEntry->component->onFocusGained(); cursorEntry->component->onFocusGained();
} }

View file

@ -30,33 +30,35 @@ namespace GridFlags
} // namespace GridFlags } // namespace GridFlags
// Provides basic layout of components in an X*Y grid. // Provides basic layout of components in an X*Y grid.
class ComponentGrid : public GuiComponent { class ComponentGrid : public GuiComponent
{
public: public:
ComponentGrid(Window *window, const glm::ivec2 &gridDimensions); ComponentGrid(Window* window, const glm::ivec2& gridDimensions);
virtual ~ComponentGrid(); virtual ~ComponentGrid();
bool removeEntry(const std::shared_ptr<GuiComponent> &comp); bool removeEntry(const std::shared_ptr<GuiComponent>& comp);
void setEntry(const std::shared_ptr<GuiComponent> &comp, void setEntry(const std::shared_ptr<GuiComponent>& comp,
const glm::ivec2 &pos, const glm::ivec2& pos,
bool canFocus, bool canFocus,
bool resize = true, bool resize = true,
const glm::ivec2 &size = glm::ivec2{1, 1}, const glm::ivec2& size = glm::ivec2{1, 1},
unsigned int border = GridFlags::BORDER_NONE, unsigned int border = GridFlags::BORDER_NONE,
GridFlags::UpdateType updateType = GridFlags::UPDATE_ALWAYS); GridFlags::UpdateType updateType = GridFlags::UPDATE_ALWAYS);
void setPastBoundaryCallback(const std::function<bool(InputConfig *config, Input input)> &func) { void setPastBoundaryCallback(const std::function<bool(InputConfig* config, Input input)>& func)
{
mPastBoundaryCallback = func; mPastBoundaryCallback = func;
} }
void textInput(const std::string &text) override; void textInput(const std::string& text) override;
bool input(InputConfig *config, Input input) override; bool input(InputConfig* config, Input input) override;
void update(int deltaTime) override; void update(int deltaTime) override;
void render(const glm::mat4 &parentTrans) override; void render(const glm::mat4& parentTrans) override;
void onSizeChanged() override; void onSizeChanged() override;
@ -80,10 +82,11 @@ public:
// Pass -1 for xPos or yPos to keep its axis cursor position. // Pass -1 for xPos or yPos to keep its axis cursor position.
void moveCursorTo(int xPos, int yPos, bool selectLeftCell = false); void moveCursorTo(int xPos, int yPos, bool selectLeftCell = false);
void setCursorTo(const std::shared_ptr<GuiComponent> &comp); void setCursorTo(const std::shared_ptr<GuiComponent>& comp);
std::shared_ptr<GuiComponent> getSelectedComponent() { std::shared_ptr<GuiComponent> getSelectedComponent()
const GridEntry *e = getCellAt(mCursor); {
const GridEntry* e = getCellAt(mCursor);
if (e) if (e)
return e->component; return e->component;
else else
@ -129,25 +132,25 @@ private:
}; };
// Update position and size. // Update position and size.
void updateCellComponent(const GridEntry &cell); void updateCellComponent(const GridEntry& cell);
void updateSeparators(); void updateSeparators();
void onCursorMoved(glm::ivec2 from, glm::ivec2 to); void onCursorMoved(glm::ivec2 from, glm::ivec2 to);
const GridEntry *getCellAt(int x, int y) const; const GridEntry* getCellAt(int x, int y) const;
const GridEntry *getCellAt(const glm::ivec2 &pos) const { return getCellAt(pos.x, pos.y); } const GridEntry* getCellAt(const glm::ivec2& pos) const { return getCellAt(pos.x, pos.y); }
std::vector<std::vector<float>> mSeparators; std::vector<std::vector<float>> mSeparators;
glm::ivec2 mGridSize; glm::ivec2 mGridSize;
std::vector<GridEntry> mCells; std::vector<GridEntry> mCells;
glm::ivec2 mCursor; glm::ivec2 mCursor;
std::function<bool(InputConfig *config, Input input)> mPastBoundaryCallback; std::function<bool(InputConfig* config, Input input)> mPastBoundaryCallback;
float *mRowHeights; float* mRowHeights;
float *mColWidths; float* mColWidths;
}; };
#endif // ES_CORE_COMPONENTS_COMPONENT_GRID_H #endif // ES_CORE_COMPONENTS_COMPONENT_GRID_H

View file

@ -71,10 +71,11 @@ bool ComponentList::input(InputConfig* config, Input input)
if (mEntries.at(mCursor).data.input_handler) { if (mEntries.at(mCursor).data.input_handler) {
if (mEntries.at(mCursor).data.input_handler(config, input)) if (mEntries.at(mCursor).data.input_handler(config, input))
return true; return true;
} else { }
else {
// No input handler assigned, do the default, which is to give it // No input handler assigned, do the default, which is to give it
// to the rightmost element in the row. // to the rightmost element in the row.
auto &row = mEntries.at(mCursor).data; auto& row = mEntries.at(mCursor).data;
if (row.elements.size()) { if (row.elements.size()) {
if (row.elements.back().component->input(config, input)) if (row.elements.back().component->input(config, input))
return true; return true;
@ -196,7 +197,7 @@ void ComponentList::render(const glm::mat4& parentTrans)
std::vector<GuiComponent*> drawAfterCursor; std::vector<GuiComponent*> drawAfterCursor;
bool drawAll; bool drawAll;
for (size_t i = 0; i < mEntries.size(); i++) { for (size_t i = 0; i < mEntries.size(); i++) {
auto &entry = mEntries.at(i); auto& entry = mEntries.at(i);
drawAll = !mFocused || i != static_cast<unsigned int>(mCursor); drawAll = !mFocused || i != static_cast<unsigned int>(mCursor);
for (auto it = entry.data.elements.cbegin(); it != entry.data.elements.cend(); it++) { for (auto it = entry.data.elements.cbegin(); it != entry.data.elements.cend(); it++) {
if (drawAll || it->invert_when_selected) { if (drawAll || it->invert_when_selected) {

View file

@ -12,10 +12,17 @@
#include "resources/Font.h" #include "resources/Font.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
DateTimeEditComponent::DateTimeEditComponent(Window *window, bool alignRight, DisplayMode dispMode) DateTimeEditComponent::DateTimeEditComponent(Window* window, bool alignRight, DisplayMode dispMode)
: GuiComponent(window), mEditing(false), mEditIndex(0), mDisplayMode(dispMode), mRelativeUpdateAccumulator(0), : GuiComponent(window)
mColor(0x777777FF), mFont(Font::get(FONT_SIZE_SMALL, FONT_PATH_LIGHT)), mAlignRight(alignRight), , mEditing(false)
mUppercase(false), mAutoSize(true) , mEditIndex(0)
, mDisplayMode(dispMode)
, mRelativeUpdateAccumulator(0)
, mColor(0x777777FF)
, mFont(Font::get(FONT_SIZE_SMALL, FONT_PATH_LIGHT))
, mAlignRight(alignRight)
, mUppercase(false)
, mAutoSize(true)
{ {
updateTextCache(); updateTextCache();
} }

View file

@ -60,9 +60,7 @@ void FlexboxComponent::setItemWidth(float value)
} }
float FlexboxComponent::getItemWidth() { return mItemWidth; } float FlexboxComponent::getItemWidth() { return mItemWidth; }
void FlexboxComponent::onSizeChanged() { void FlexboxComponent::onSizeChanged() { mLayoutValid = false; }
mLayoutValid = false;
}
void FlexboxComponent::computeLayout() void FlexboxComponent::computeLayout()
{ {
@ -95,9 +93,9 @@ void FlexboxComponent::computeLayout()
// Pre-compute layout parameters. // Pre-compute layout parameters.
int n = mChildren.size(); int n = mChildren.size();
int nLines = std::max(1, (int) std::ceil(n / std::max(1, (int) mItemsPerLine))); int nLines = std::max(1, (int)std::ceil(n / std::max(1, (int)mItemsPerLine)));
float lineWidth = float lineWidth =
(mDirection == "row" ? (maxItemSize.y + mItemMargin.y) : (maxItemSize.x + mItemMargin.x)); (mDirection == "row" ? (maxItemSize.y + mItemMargin.y) : (maxItemSize.x + mItemMargin.x));
float anchorXStart = anchorX; float anchorXStart = anchorX;
float anchorYStart = anchorY; float anchorYStart = anchorY;
@ -106,14 +104,15 @@ void FlexboxComponent::computeLayout()
if (mDirection == "row") { if (mDirection == "row") {
totalSize.x += (mItemMargin.x + mItemWidth) * mItemsPerLine; totalSize.x += (mItemMargin.x + mItemWidth) * mItemsPerLine;
totalSize.y += (mItemMargin.y + maxItemSize.y) * nLines; totalSize.y += (mItemMargin.y + maxItemSize.y) * nLines;
} else { }
else {
totalSize.x += (mItemMargin.x + mItemWidth) * nLines; totalSize.x += (mItemMargin.x + mItemWidth) * nLines;
totalSize.y += (mItemMargin.y + maxItemSize.y) * mItemsPerLine; totalSize.y += (mItemMargin.y + maxItemSize.y) * mItemsPerLine;
} }
// Iterate through the children. // Iterate through the children.
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
GuiComponent *child = mChildren[i]; GuiComponent* child = mChildren[i];
auto size = child->getSize(); auto size = child->getSize();
// Top-left anchor position. // Top-left anchor position.
@ -132,10 +131,12 @@ void FlexboxComponent::computeLayout()
if (mAlign == ITEM_ALIGN_END) { if (mAlign == ITEM_ALIGN_END) {
x += directionLine.x == 0 ? (maxItemSize.x - size.x) : 0; x += directionLine.x == 0 ? (maxItemSize.x - size.x) : 0;
y += directionLine.y == 0 ? (maxItemSize.y - size.y) : 0; y += directionLine.y == 0 ? (maxItemSize.y - size.y) : 0;
} else if (mAlign == ITEM_ALIGN_CENTER) { }
else if (mAlign == ITEM_ALIGN_CENTER) {
x += directionLine.x == 0 ? (maxItemSize.x - size.x) / 2 : 0; x += directionLine.x == 0 ? (maxItemSize.x - size.x) / 2 : 0;
y += directionLine.y == 0 ? (maxItemSize.y - size.y) / 2 : 0; y += directionLine.y == 0 ? (maxItemSize.y - size.y) / 2 : 0;
} else if (mAlign == ITEM_ALIGN_STRETCH && mDirection == "row") { }
else if (mAlign == ITEM_ALIGN_STRETCH && mDirection == "row") {
child->setSize(child->getSize().x, maxItemSize.y); child->setSize(child->getSize().x, maxItemSize.y);
} }
@ -149,7 +150,7 @@ void FlexboxComponent::computeLayout()
child->setPosition(getPosition().x + x, getPosition().y + y); child->setPosition(getPosition().x + x, getPosition().y + y);
// Translate anchor. // Translate anchor.
if ((i + 1) % std::max(1, (int) mItemsPerLine) != 0) { if ((i + 1) % std::max(1, (int)mItemsPerLine) != 0) {
// Translate on same line. // Translate on same line.
anchorX += (size.x + mItemMargin.x) * directionLine.x; anchorX += (size.x + mItemMargin.x) * directionLine.x;
anchorY += (size.y + mItemMargin.y) * directionLine.y; anchorY += (size.y + mItemMargin.y) * directionLine.y;
@ -159,7 +160,8 @@ void FlexboxComponent::computeLayout()
if (directionRow.x == 0) { if (directionRow.x == 0) {
anchorY += lineWidth * directionRow.y; anchorY += lineWidth * directionRow.y;
anchorX = anchorXStart; anchorX = anchorXStart;
} else { }
else {
anchorX += lineWidth * directionRow.x; anchorX += lineWidth * directionRow.x;
anchorY = anchorYStart; anchorY = anchorYStart;
} }
@ -169,7 +171,8 @@ void FlexboxComponent::computeLayout()
mLayoutValid = true; mLayoutValid = true;
} }
void FlexboxComponent::render(const glm::mat4& parentTrans) { void FlexboxComponent::render(const glm::mat4& parentTrans)
{
if (!isVisible()) if (!isVisible())
return; return;

View file

@ -37,36 +37,36 @@ void HelpComponent::assignIcons()
":/help/dpad_updown.svg" : ":/help/dpad_updown.svg" :
mStyle.mCustomButtons.dpad_updown; mStyle.mCustomButtons.dpad_updown;
sIconPathMap["left/right"] = mStyle.mCustomButtons.dpad_leftright.empty() ? sIconPathMap["left/right"] = mStyle.mCustomButtons.dpad_leftright.empty() ?
":/help/dpad_leftright.svg" : ":/help/dpad_leftright.svg" :
mStyle.mCustomButtons.dpad_leftright; mStyle.mCustomButtons.dpad_leftright;
sIconPathMap["up/down/left/right"] = mStyle.mCustomButtons.dpad_all.empty() ? sIconPathMap["up/down/left/right"] = mStyle.mCustomButtons.dpad_all.empty() ?
":/help/dpad_all.svg" : ":/help/dpad_all.svg" :
mStyle.mCustomButtons.dpad_all; mStyle.mCustomButtons.dpad_all;
sIconPathMap["thumbstickclick"] = mStyle.mCustomButtons.thumbstick_click.empty() ? sIconPathMap["thumbstickclick"] = mStyle.mCustomButtons.thumbstick_click.empty() ?
":/help/thumbstick_click.svg" : ":/help/thumbstick_click.svg" :
mStyle.mCustomButtons.thumbstick_click; mStyle.mCustomButtons.thumbstick_click;
sIconPathMap["l"] = mStyle.mCustomButtons.button_l.empty() ? ":/help/button_l.svg" : sIconPathMap["l"] = mStyle.mCustomButtons.button_l.empty() ? ":/help/button_l.svg" :
mStyle.mCustomButtons.button_l; mStyle.mCustomButtons.button_l;
sIconPathMap["r"] = mStyle.mCustomButtons.button_r.empty() ? ":/help/button_r.svg" : sIconPathMap["r"] = mStyle.mCustomButtons.button_r.empty() ? ":/help/button_r.svg" :
mStyle.mCustomButtons.button_r; mStyle.mCustomButtons.button_r;
sIconPathMap["lr"] = mStyle.mCustomButtons.button_lr.empty() ? ":/help/button_lr.svg" : sIconPathMap["lr"] = mStyle.mCustomButtons.button_lr.empty() ? ":/help/button_lr.svg" :
mStyle.mCustomButtons.button_lr; mStyle.mCustomButtons.button_lr;
sIconPathMap["lt"] = mStyle.mCustomButtons.button_lt.empty() ? ":/help/button_lt.svg" : sIconPathMap["lt"] = mStyle.mCustomButtons.button_lt.empty() ? ":/help/button_lt.svg" :
mStyle.mCustomButtons.button_lt; mStyle.mCustomButtons.button_lt;
sIconPathMap["rt"] = mStyle.mCustomButtons.button_rt.empty() ? ":/help/button_rt.svg" : sIconPathMap["rt"] = mStyle.mCustomButtons.button_rt.empty() ? ":/help/button_rt.svg" :
mStyle.mCustomButtons.button_rt; mStyle.mCustomButtons.button_rt;
// These graphics files are custom per controller type. // These graphics files are custom per controller type.
if (controllerType == "snes") { if (controllerType == "snes") {
sIconPathMap["a"] = mStyle.mCustomButtons.button_a_SNES.empty() ? sIconPathMap["a"] = mStyle.mCustomButtons.button_a_SNES.empty() ?
":/help/button_a_SNES.svg" : ":/help/button_a_SNES.svg" :
mStyle.mCustomButtons.button_a_SNES; mStyle.mCustomButtons.button_a_SNES;
sIconPathMap["b"] = mStyle.mCustomButtons.button_b_SNES.empty() ? sIconPathMap["b"] = mStyle.mCustomButtons.button_b_SNES.empty() ?
":/help/button_b_SNES.svg" : ":/help/button_b_SNES.svg" :
mStyle.mCustomButtons.button_b_SNES; mStyle.mCustomButtons.button_b_SNES;
sIconPathMap["x"] = mStyle.mCustomButtons.button_x_SNES.empty() ? sIconPathMap["x"] = mStyle.mCustomButtons.button_x_SNES.empty() ?
":/help/button_x_SNES.svg" : ":/help/button_x_SNES.svg" :
mStyle.mCustomButtons.button_x_SNES; mStyle.mCustomButtons.button_x_SNES;
sIconPathMap["y"] = mStyle.mCustomButtons.button_y_SNES.empty() ? sIconPathMap["y"] = mStyle.mCustomButtons.button_y_SNES.empty() ?
":/help/button_y_SNES.svg" : ":/help/button_y_SNES.svg" :
mStyle.mCustomButtons.button_y_SNES; mStyle.mCustomButtons.button_y_SNES;

View file

@ -27,11 +27,23 @@ glm::vec2 ImageComponent::getSize() const
return GuiComponent::getSize() * (mBottomRightCrop - mTopLeftCrop); return GuiComponent::getSize() * (mBottomRightCrop - mTopLeftCrop);
} }
ImageComponent::ImageComponent(Window *window, bool forceLoad, bool dynamic) ImageComponent::ImageComponent(Window* window, bool forceLoad, bool dynamic)
: GuiComponent(window), mTargetSize({}), mFlipX(false), mFlipY(false), mTargetIsMax(false), mTargetIsMin(false), : GuiComponent(window)
mColorShift(0xFFFFFFFF), mColorShiftEnd(0xFFFFFFFF), mColorGradientHorizontal(true), mFadeOpacity(0), , mTargetSize({})
mFading(false), mForceLoad(forceLoad), mDynamic(dynamic), mRotateByTargetSize(false), mTopLeftCrop({}), , mFlipX(false)
mBottomRightCrop(1.0f, 1.0f) , mFlipY(false)
, mTargetIsMax(false)
, mTargetIsMin(false)
, mColorShift(0xFFFFFFFF)
, mColorShiftEnd(0xFFFFFFFF)
, mColorGradientHorizontal(true)
, mFadeOpacity(0)
, mFading(false)
, mForceLoad(forceLoad)
, mDynamic(dynamic)
, mRotateByTargetSize(false)
, mTopLeftCrop({})
, mBottomRightCrop(1.0f, 1.0f)
{ {
updateColors(); updateColors();
} }
@ -126,7 +138,8 @@ void ImageComponent::resize()
onSizeChanged(); onSizeChanged();
} }
void ImageComponent::setImage(std::string path, bool tile, bool linearMagnify, bool cacheImage) { void ImageComponent::setImage(std::string path, bool tile, bool linearMagnify, bool cacheImage)
{
// Always load bundled graphic resources statically, unless mForceLoad has been set. // Always load bundled graphic resources statically, unless mForceLoad has been set.
// This eliminates annoying texture pop-in problems that would otherwise occur. // This eliminates annoying texture pop-in problems that would otherwise occur.
if (!mForceLoad && (path[0] == ':') && (path[1] == '/')) { if (!mForceLoad && (path[0] == ':') && (path[1] == '/')) {
@ -137,11 +150,12 @@ void ImageComponent::setImage(std::string path, bool tile, bool linearMagnify, b
if (mDefaultPath.empty() || !ResourceManager::getInstance()->fileExists(mDefaultPath)) if (mDefaultPath.empty() || !ResourceManager::getInstance()->fileExists(mDefaultPath))
mTexture.reset(); mTexture.reset();
else else
mTexture = mTexture = TextureResource::get(mDefaultPath, tile, mForceLoad, mDynamic, linearMagnify,
TextureResource::get(mDefaultPath, tile, mForceLoad, mDynamic, linearMagnify, 1.0f, cacheImage); 1.0f, cacheImage);
} }
else { else {
mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, linearMagnify, 1.0f, cacheImage); mTexture =
TextureResource::get(path, tile, mForceLoad, mDynamic, linearMagnify, 1.0f, cacheImage);
} }
resize(); resize();

View file

@ -14,9 +14,10 @@
class TextureResource; class TextureResource;
class ImageComponent : public GuiComponent { class ImageComponent : public GuiComponent
{
public: public:
ImageComponent(Window *window, bool forceLoad = false, bool dynamic = true); ImageComponent(Window* window, bool forceLoad = false, bool dynamic = true);
virtual ~ImageComponent() noexcept {}; virtual ~ImageComponent() noexcept {};
@ -24,13 +25,16 @@ public:
// Loads the image at the given filepath. Will tile if tile is true (retrieves texture // Loads the image at the given filepath. Will tile if tile is true (retrieves texture
// as tiling, creates vertices accordingly). // as tiling, creates vertices accordingly).
void setImage(std::string path, bool tile = false, bool linearMagnify = false, bool cacheSVG = false); void setImage(std::string path,
bool tile = false,
bool linearMagnify = false,
bool cacheSVG = false);
// Loads an image from memory. // Loads an image from memory.
void setImage(const char *data, size_t length, bool tile = false); void setImage(const char* data, size_t length, bool tile = false);
// Use an already existing texture. // Use an already existing texture.
void setImage(const std::shared_ptr<TextureResource> &texture); void setImage(const std::shared_ptr<TextureResource>& texture);
void onSizeChanged() override { updateVertices(); } void onSizeChanged() override { updateVertices(); }

View file

@ -181,7 +181,7 @@ GuiInputConfig::GuiInputConfig(Window* window,
}; };
buttons.push_back( buttons.push_back(
std::make_shared<ButtonComponent>(mWindow, "OK", "ok", [okFunction] { okFunction(); })); std::make_shared<ButtonComponent>(mWindow, "OK", "ok", [okFunction] { okFunction(); }));
mButtonGrid = makeButtonGrid(mWindow, buttons); mButtonGrid = makeButtonGrid(mWindow, buttons);
mGrid.setEntry(mButtonGrid, glm::ivec2{0, 6}, true, false); mGrid.setEntry(mButtonGrid, glm::ivec2{0, 6}, true, false);

View file

@ -15,18 +15,22 @@
#define HORIZONTAL_PADDING_PX 20.0f #define HORIZONTAL_PADDING_PX 20.0f
GuiMsgBox::GuiMsgBox(Window* window, GuiMsgBox::GuiMsgBox(Window* window,
const HelpStyle &helpstyle, const HelpStyle& helpstyle,
const std::string &text, const std::string& text,
const std::string &name1, const std::string& name1,
const std::function<void()> &func1, const std::function<void()>& func1,
const std::string &name2, const std::string& name2,
const std::function<void()> &func2, const std::function<void()>& func2,
const std::string &name3, const std::string& name3,
const std::function<void()> &func3, const std::function<void()>& func3,
bool disableBackButton, bool disableBackButton,
bool deleteOnButtonPress) bool deleteOnButtonPress)
: GuiComponent(window), mBackground(window, ":/graphics/frame.svg"), mGrid(window, glm::ivec2{1, 2}), : GuiComponent(window)
mHelpStyle(helpstyle), mDisableBackButton(disableBackButton), mDeleteOnButtonPress(deleteOnButtonPress) , mBackground(window, ":/graphics/frame.svg")
, mGrid(window, glm::ivec2{1, 2})
, mHelpStyle(helpstyle)
, mDisableBackButton(disableBackButton)
, mDeleteOnButtonPress(deleteOnButtonPress)
{ {
// Adjust the width relative to the aspect ratio of the screen to make the GUI look coherent // Adjust the width relative to the aspect ratio of the screen to make the GUI look coherent
// regardless of screen type. The 1.778 aspect ratio value is the 16:9 reference. // regardless of screen type. The 1.778 aspect ratio value is the 16:9 reference.

View file

@ -74,33 +74,47 @@ std::vector<std::vector<const char *>> kbLastRowLoad{
// clang-format on // clang-format on
GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup( GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
Window *window, Window* window,
const HelpStyle &helpstyle, const HelpStyle& helpstyle,
const std::string &title, const std::string& title,
const std::string &initValue, const std::string& initValue,
const std::function<void(const std::string &)> &okCallback, const std::function<void(const std::string&)>& okCallback,
bool multiLine, bool multiLine,
const std::string &acceptBtnHelpText, const std::string& acceptBtnHelpText,
const std::string &saveConfirmationText, const std::string& saveConfirmationText,
const std::string &infoString, const std::string& infoString,
const std::string &defaultValue, const std::string& defaultValue,
const std::string &loadBtnHelpText, const std::string& loadBtnHelpText,
const std::string &clearBtnHelpText, const std::string& clearBtnHelpText,
const std::string &cancelBtnHelpText) const std::string& cancelBtnHelpText)
: GuiComponent{window}, mBackground{window, ":/graphics/frame.svg"}, : GuiComponent{window}
mGrid{window, glm::ivec2{1, (infoString != "" && defaultValue != "" ? 8 : 6)}}, mHelpStyle{helpstyle}, , mBackground{window, ":/graphics/frame.svg"}
mInitValue{initValue}, mAcceptBtnHelpText{acceptBtnHelpText}, mSaveConfirmationText{saveConfirmationText}, , mGrid{window, glm::ivec2{1, (infoString != "" && defaultValue != "" ? 8 : 6)}}
mLoadBtnHelpText{loadBtnHelpText}, mClearBtnHelpText{clearBtnHelpText}, mCancelBtnHelpText{cancelBtnHelpText}, , mHelpStyle{helpstyle}
mOkCallback{okCallback}, mMultiLine{multiLine}, mComplexMode{(infoString != "" && defaultValue != "")}, , mInitValue{initValue}
mDeleteRepeat{false}, mShift{false}, mAlt{false}, mDeleteRepeatTimer{0}, mNavigationRepeatTimer{0}, , mAcceptBtnHelpText{acceptBtnHelpText}
mNavigationRepeatDirX{0}, mNavigationRepeatDirY{0} { , mSaveConfirmationText{saveConfirmationText}
, mLoadBtnHelpText{loadBtnHelpText}
, mClearBtnHelpText{clearBtnHelpText}
, mCancelBtnHelpText{cancelBtnHelpText}
, mOkCallback{okCallback}
, mMultiLine{multiLine}
, mComplexMode{(infoString != "" && defaultValue != "")}
, mDeleteRepeat{false}
, mShift{false}
, mAlt{false}
, mDeleteRepeatTimer{0}
, mNavigationRepeatTimer{0}
, mNavigationRepeatDirX{0}
, mNavigationRepeatDirY{0}
{
addChild(&mBackground); addChild(&mBackground);
addChild(&mGrid); addChild(&mGrid);
mTitle = std::make_shared<TextComponent>(mWindow, Utils::String::toUpper(title), mTitle = std::make_shared<TextComponent>(mWindow, Utils::String::toUpper(title),
Font::get(FONT_SIZE_LARGE), 0x555555FF, ALIGN_CENTER); Font::get(FONT_SIZE_LARGE), 0x555555FF, ALIGN_CENTER);
std::vector<std::vector<const char *>> kbLayout; std::vector<std::vector<const char*>> kbLayout;
// At the moment there is only the US keyboard layout available. // At the moment there is only the US keyboard layout available.
kbLayout.insert(kbLayout.cend(), kbBaseUS.cbegin(), kbBaseUS.cend()); kbLayout.insert(kbLayout.cend(), kbBaseUS.cbegin(), kbBaseUS.cend());
@ -114,7 +128,7 @@ GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
mHorizontalKeyCount = static_cast<int>(kbLayout[0].size()); mHorizontalKeyCount = static_cast<int>(kbLayout[0].size());
mKeyboardGrid = std::make_shared<ComponentGrid>( mKeyboardGrid = std::make_shared<ComponentGrid>(
mWindow, glm::ivec2(mHorizontalKeyCount, static_cast<int>(kbLayout.size()) / 3)); mWindow, glm::ivec2(mHorizontalKeyCount, static_cast<int>(kbLayout.size()) / 3));
mText = std::make_shared<TextEditComponent>(mWindow); mText = std::make_shared<TextEditComponent>(mWindow);
mText->setValue(initValue); mText->setValue(initValue);
@ -129,11 +143,11 @@ GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
if (mComplexMode) { if (mComplexMode) {
mInfoString = std::make_shared<TextComponent>( mInfoString = std::make_shared<TextComponent>(
mWindow, infoString, Font::get(FONT_SIZE_MEDIUM), 0x555555FF, ALIGN_CENTER); mWindow, infoString, Font::get(FONT_SIZE_MEDIUM), 0x555555FF, ALIGN_CENTER);
mGrid.setEntry(mInfoString, glm::ivec2{0, yPos}, false, true); mGrid.setEntry(mInfoString, glm::ivec2{0, yPos}, false, true);
mDefaultValue = std::make_shared<TextComponent>( mDefaultValue = std::make_shared<TextComponent>(
mWindow, defaultValue, Font::get(FONT_SIZE_SMALL), 0x555555FF, ALIGN_CENTER); mWindow, defaultValue, Font::get(FONT_SIZE_SMALL), 0x555555FF, ALIGN_CENTER);
mGrid.setEntry(mDefaultValue, glm::ivec2{0, yPos + 1}, false, true); mGrid.setEntry(mDefaultValue, glm::ivec2{0, yPos + 1}, false, true);
yPos += 2; yPos += 2;
} }
@ -164,17 +178,20 @@ GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
upper = DELETE_SYMBOL; upper = DELETE_SYMBOL;
alted = DELETE_SYMBOL; alted = DELETE_SYMBOL;
altshifted = DELETE_SYMBOL; altshifted = DELETE_SYMBOL;
} else if (lower == "OK") { }
else if (lower == "OK") {
lower = OK_SYMBOL; lower = OK_SYMBOL;
upper = OK_SYMBOL; upper = OK_SYMBOL;
alted = OK_SYMBOL; alted = OK_SYMBOL;
altshifted = OK_SYMBOL; altshifted = OK_SYMBOL;
} else if (lower == "SPACE") { }
else if (lower == "SPACE") {
lower = " "; lower = " ";
upper = " "; upper = " ";
alted = " "; alted = " ";
altshifted = " "; altshifted = " ";
} else if (lower != "SHIFT" && lower.length() > 1) { }
else if (lower != "SHIFT" && lower.length() > 1) {
lower = (lower.c_str()); lower = (lower.c_str());
upper = (upper.c_str()); upper = (upper.c_str());
alted = (alted.c_str()); alted = (alted.c_str());
@ -183,19 +200,21 @@ GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
if (lower == "SHIFT") { if (lower == "SHIFT") {
mShiftButton = std::make_shared<ButtonComponent>( mShiftButton = std::make_shared<ButtonComponent>(
mWindow, (SHIFT_SYMBOL), ("SHIFT"), [this] { shiftKeys(); }, false, true); mWindow, (SHIFT_SYMBOL), ("SHIFT"), [this] { shiftKeys(); }, false, true);
button = mShiftButton; button = mShiftButton;
} else if (lower == "ALT") { }
else if (lower == "ALT") {
mAltButton = std::make_shared<ButtonComponent>( mAltButton = std::make_shared<ButtonComponent>(
mWindow, (ALT_SYMBOL), ("ALT"), [this] { altKeys(); }, false, true); mWindow, (ALT_SYMBOL), ("ALT"), [this] { altKeys(); }, false, true);
button = mAltButton; button = mAltButton;
} else { }
else {
button = makeButton(lower, upper, alted, altshifted); button = makeButton(lower, upper, alted, altshifted);
} }
button->setPadding( button->setPadding(
glm::vec4(BUTTON_GRID_HORIZ_PADDING / 4.0f, BUTTON_GRID_HORIZ_PADDING / 4.0f, glm::vec4(BUTTON_GRID_HORIZ_PADDING / 4.0f, BUTTON_GRID_HORIZ_PADDING / 4.0f,
BUTTON_GRID_HORIZ_PADDING / 4.0f, BUTTON_GRID_HORIZ_PADDING / 4.0f)); BUTTON_GRID_HORIZ_PADDING / 4.0f, BUTTON_GRID_HORIZ_PADDING / 4.0f));
buttons.push_back(button); buttons.push_back(button);
int colSpan = 1; int colSpan = 1;
@ -233,13 +252,14 @@ GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
mText->setSize(0.0f, textHeight); mText->setSize(0.0f, textHeight);
// If attempting to navigate beyond the edge of the keyboard grid, then wrap around. // If attempting to navigate beyond the edge of the keyboard grid, then wrap around.
mGrid.setPastBoundaryCallback([this, kbLayout](InputConfig *config, Input input) -> bool { mGrid.setPastBoundaryCallback([this, kbLayout](InputConfig* config, Input input) -> bool {
if (config->isMappedLike("left", input)) { if (config->isMappedLike("left", input)) {
if (mGrid.getSelectedComponent() == mKeyboardGrid) { if (mGrid.getSelectedComponent() == mKeyboardGrid) {
mKeyboardGrid->moveCursorTo(mHorizontalKeyCount - 1, -1, true); mKeyboardGrid->moveCursorTo(mHorizontalKeyCount - 1, -1, true);
return true; return true;
} }
} else if (config->isMappedLike("right", input)) { }
else if (config->isMappedLike("right", input)) {
if (mGrid.getSelectedComponent() == mKeyboardGrid) { if (mGrid.getSelectedComponent() == mKeyboardGrid) {
mKeyboardGrid->moveCursorTo(0, -1); mKeyboardGrid->moveCursorTo(0, -1);
return true; return true;
@ -259,7 +279,8 @@ GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
setPosition((static_cast<float>(Renderer::getScreenWidth()) - mSize.x) / 2.0f, setPosition((static_cast<float>(Renderer::getScreenWidth()) - mSize.x) / 2.0f,
(static_cast<float>(Renderer::getScreenHeight()) - mSize.y) / 2.0f); (static_cast<float>(Renderer::getScreenHeight()) - mSize.y) / 2.0f);
} else { }
else {
if (mComplexMode) if (mComplexMode)
setSize(width, KEYBOARD_HEIGHT + mDefaultValue->getSize().y * 3.0f); setSize(width, KEYBOARD_HEIGHT + mDefaultValue->getSize().y * 3.0f);
else else
@ -270,7 +291,8 @@ GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
} }
} }
void GuiTextEditKeyboardPopup::onSizeChanged() { void GuiTextEditKeyboardPopup::onSizeChanged()
{
mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f});
mText->setSize(mSize.x - KEYBOARD_PADDINGX - KEYBOARD_PADDINGX, mText->getSize().y); mText->setSize(mSize.x - KEYBOARD_PADDINGX - KEYBOARD_PADDINGX, mText->getSize().y);
@ -281,7 +303,8 @@ void GuiTextEditKeyboardPopup::onSizeChanged() {
mGrid.setRowHeightPerc(1, (mInfoString->getSize().y * 0.6f) / mSize.y); mGrid.setRowHeightPerc(1, (mInfoString->getSize().y * 0.6f) / mSize.y);
mGrid.setRowHeightPerc(2, (mDefaultValue->getSize().y * 1.6f) / mSize.y); mGrid.setRowHeightPerc(2, (mDefaultValue->getSize().y * 1.6f) / mSize.y);
mGrid.setRowHeightPerc(1, (mText->getSize().y * 1.0f) / mSize.y); mGrid.setRowHeightPerc(1, (mText->getSize().y * 1.0f) / mSize.y);
} else if (mMultiLine) { }
else if (mMultiLine) {
mGrid.setRowHeightPerc(1, (mText->getSize().y * 1.15f) / mSize.y); mGrid.setRowHeightPerc(1, (mText->getSize().y * 1.15f) / mSize.y);
} }
@ -296,7 +319,8 @@ void GuiTextEditKeyboardPopup::onSizeChanged() {
mKeyboardGrid->setPosition(KEYBOARD_PADDINGX, pos.y); mKeyboardGrid->setPosition(KEYBOARD_PADDINGX, pos.y);
} }
bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) { bool GuiTextEditKeyboardPopup::input(InputConfig* config, Input input)
{
// Enter/return key or numpad enter key accepts the changes. // Enter/return key or numpad enter key accepts the changes.
if (config->getDeviceId() == DEVICE_KEYBOARD && mText->isEditing() && !mMultiLine && if (config->getDeviceId() == DEVICE_KEYBOARD && mText->isEditing() && !mMultiLine &&
input.value && (input.id == SDLK_RETURN || input.id == SDLK_KP_ENTER)) { input.value && (input.id == SDLK_RETURN || input.id == SDLK_KP_ENTER)) {
@ -304,7 +328,7 @@ bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) {
delete this; delete this;
return true; return true;
} }
// Dito for the A button if using a controller. // Dito for the A button if using a controller.
else if (config->getDeviceId() != DEVICE_KEYBOARD && mText->isEditing() && else if (config->getDeviceId() != DEVICE_KEYBOARD && mText->isEditing() &&
config->isMappedTo("a", input) && input.value) { config->isMappedTo("a", input) && input.value) {
this->mOkCallback(mText->getValue()); this->mOkCallback(mText->getValue());
@ -330,18 +354,19 @@ bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) {
if (mText->getValue() != mInitValue) { if (mText->getValue() != mInitValue) {
// Changes were made, ask if the user wants to save them. // Changes were made, ask if the user wants to save them.
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
mWindow, mHelpStyle, mSaveConfirmationText, "YES", mWindow, mHelpStyle, mSaveConfirmationText, "YES",
[this] { [this] {
this->mOkCallback(mText->getValue()); this->mOkCallback(mText->getValue());
delete this; delete this;
return true; return true;
}, },
"NO", "NO",
[this] { [this] {
delete this; delete this;
return true; return true;
})); }));
} else { }
else {
delete this; delete this;
return true; return true;
} }
@ -374,7 +399,8 @@ bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) {
if (!editing) if (!editing)
mText->stopEditing(); mText->stopEditing();
} else { }
else {
mDeleteRepeat = false; mDeleteRepeat = false;
} }
return true; return true;
@ -400,7 +426,8 @@ bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) {
if (input.value) { if (input.value) {
mNavigationRepeatDirX = -1; mNavigationRepeatDirX = -1;
mNavigationRepeatTimer = -(NAVIGATION_REPEAT_START_DELAY - NAVIGATION_REPEAT_SPEED); mNavigationRepeatTimer = -(NAVIGATION_REPEAT_START_DELAY - NAVIGATION_REPEAT_SPEED);
} else { }
else {
mNavigationRepeatDirX = 0; mNavigationRepeatDirX = 0;
} }
} }
@ -409,7 +436,8 @@ bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) {
if (input.value) { if (input.value) {
mNavigationRepeatDirX = 1; mNavigationRepeatDirX = 1;
mNavigationRepeatTimer = -(NAVIGATION_REPEAT_START_DELAY - NAVIGATION_REPEAT_SPEED); mNavigationRepeatTimer = -(NAVIGATION_REPEAT_START_DELAY - NAVIGATION_REPEAT_SPEED);
} else { }
else {
mNavigationRepeatDirX = 0; mNavigationRepeatDirX = 0;
} }
} }
@ -418,7 +446,8 @@ bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) {
if (input.value) { if (input.value) {
mNavigationRepeatDirY = -1; mNavigationRepeatDirY = -1;
mNavigationRepeatTimer = -(NAVIGATION_REPEAT_START_DELAY - NAVIGATION_REPEAT_SPEED); mNavigationRepeatTimer = -(NAVIGATION_REPEAT_START_DELAY - NAVIGATION_REPEAT_SPEED);
} else { }
else {
mNavigationRepeatDirY = 0; mNavigationRepeatDirY = 0;
} }
} }
@ -427,7 +456,8 @@ bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) {
if (input.value) { if (input.value) {
mNavigationRepeatDirY = 1; mNavigationRepeatDirY = 1;
mNavigationRepeatTimer = -(NAVIGATION_REPEAT_START_DELAY - NAVIGATION_REPEAT_SPEED); mNavigationRepeatTimer = -(NAVIGATION_REPEAT_START_DELAY - NAVIGATION_REPEAT_SPEED);
} else { }
else {
mNavigationRepeatDirY = 0; mNavigationRepeatDirY = 0;
} }
} }
@ -438,19 +468,22 @@ bool GuiTextEditKeyboardPopup::input(InputConfig *config, Input input) {
return false; return false;
} }
void GuiTextEditKeyboardPopup::update(int deltaTime) { void GuiTextEditKeyboardPopup::update(int deltaTime)
{
updateNavigationRepeat(deltaTime); updateNavigationRepeat(deltaTime);
updateDeleteRepeat(deltaTime); updateDeleteRepeat(deltaTime);
GuiComponent::update(deltaTime); GuiComponent::update(deltaTime);
} }
std::vector<HelpPrompt> GuiTextEditKeyboardPopup::getHelpPrompts() { std::vector<HelpPrompt> GuiTextEditKeyboardPopup::getHelpPrompts()
{
std::vector<HelpPrompt> prompts = mGrid.getHelpPrompts(); std::vector<HelpPrompt> prompts = mGrid.getHelpPrompts();
if (!mText->isEditing()) { if (!mText->isEditing()) {
prompts.push_back(HelpPrompt("lt", "shift")); prompts.push_back(HelpPrompt("lt", "shift"));
prompts.push_back(HelpPrompt("rt", "alt")); prompts.push_back(HelpPrompt("rt", "alt"));
} else { }
else {
prompts.push_back(HelpPrompt("a", mAcceptBtnHelpText)); prompts.push_back(HelpPrompt("a", mAcceptBtnHelpText));
} }
@ -480,7 +513,8 @@ std::vector<HelpPrompt> GuiTextEditKeyboardPopup::getHelpPrompts() {
return prompts; return prompts;
} }
void GuiTextEditKeyboardPopup::updateDeleteRepeat(int deltaTime) { void GuiTextEditKeyboardPopup::updateDeleteRepeat(int deltaTime)
{
if (!mDeleteRepeat) if (!mDeleteRepeat)
return; return;
@ -500,7 +534,8 @@ void GuiTextEditKeyboardPopup::updateDeleteRepeat(int deltaTime) {
} }
} }
void GuiTextEditKeyboardPopup::updateNavigationRepeat(int deltaTime) { void GuiTextEditKeyboardPopup::updateNavigationRepeat(int deltaTime)
{
if (mNavigationRepeatDirX == 0 && mNavigationRepeatDirY == 0) if (mNavigationRepeatDirX == 0 && mNavigationRepeatDirY == 0)
return; return;
@ -527,13 +562,15 @@ void GuiTextEditKeyboardPopup::updateNavigationRepeat(int deltaTime) {
} }
} }
void GuiTextEditKeyboardPopup::shiftKeys() { void GuiTextEditKeyboardPopup::shiftKeys()
{
mShift = !mShift; mShift = !mShift;
if (mShift) { if (mShift) {
mShiftButton->setFlatColorFocused(0xFF2222FF); mShiftButton->setFlatColorFocused(0xFF2222FF);
mShiftButton->setFlatColorUnfocused(0xFF2222FF); mShiftButton->setFlatColorUnfocused(0xFF2222FF);
} else { }
else {
mShiftButton->setFlatColorFocused(0x878787FF); mShiftButton->setFlatColorFocused(0x878787FF);
mShiftButton->setFlatColorUnfocused(0x60606025); mShiftButton->setFlatColorUnfocused(0x60606025);
} }
@ -547,9 +584,10 @@ void GuiTextEditKeyboardPopup::shiftKeys() {
if (mAlt) { if (mAlt) {
altKeys(); altKeys();
altKeys(); altKeys();
} else { }
for (auto &kb: mKeyboardButtons) { else {
const std::string &text = mShift ? kb.shiftedKey : kb.key; for (auto& kb : mKeyboardButtons) {
const std::string& text = mShift ? kb.shiftedKey : kb.key;
auto sz = kb.button->getSize(); auto sz = kb.button->getSize();
kb.button->setText(text, text, false); kb.button->setText(text, text, false);
kb.button->setSize(sz); kb.button->setSize(sz);
@ -557,13 +595,15 @@ void GuiTextEditKeyboardPopup::shiftKeys() {
} }
} }
void GuiTextEditKeyboardPopup::altKeys() { void GuiTextEditKeyboardPopup::altKeys()
{
mAlt = !mAlt; mAlt = !mAlt;
if (mAlt) { if (mAlt) {
mAltButton->setFlatColorFocused(0xFF2222FF); mAltButton->setFlatColorFocused(0xFF2222FF);
mAltButton->setFlatColorUnfocused(0xFF2222FF); mAltButton->setFlatColorUnfocused(0xFF2222FF);
} else { }
else {
mAltButton->setFlatColorFocused(0x878787FF); mAltButton->setFlatColorFocused(0x878787FF);
mAltButton->setFlatColorUnfocused(0x60606025); mAltButton->setFlatColorUnfocused(0x60606025);
} }
@ -577,9 +617,10 @@ void GuiTextEditKeyboardPopup::altKeys() {
if (mShift) { if (mShift) {
shiftKeys(); shiftKeys();
shiftKeys(); shiftKeys();
} else { }
for (auto &kb: mKeyboardButtons) { else {
const std::string &text = mAlt ? kb.altedKey : kb.key; for (auto& kb : mKeyboardButtons) {
const std::string& text = mAlt ? kb.altedKey : kb.key;
auto sz = kb.button->getSize(); auto sz = kb.button->getSize();
kb.button->setText(text, text, false); kb.button->setText(text, text, false);
kb.button->setSize(sz); kb.button->setSize(sz);
@ -587,9 +628,10 @@ void GuiTextEditKeyboardPopup::altKeys() {
} }
} }
void GuiTextEditKeyboardPopup::altShiftKeys() { void GuiTextEditKeyboardPopup::altShiftKeys()
for (auto &kb: mKeyboardButtons) { {
const std::string &text = kb.altshiftedKey; for (auto& kb : mKeyboardButtons) {
const std::string& text = kb.altshiftedKey;
auto sz = kb.button->getSize(); auto sz = kb.button->getSize();
kb.button->setText(text, text, false); kb.button->setText(text, text, false);
kb.button->setSize(sz); kb.button->setSize(sz);
@ -597,56 +639,62 @@ void GuiTextEditKeyboardPopup::altShiftKeys() {
} }
std::shared_ptr<ButtonComponent> GuiTextEditKeyboardPopup::makeButton( std::shared_ptr<ButtonComponent> GuiTextEditKeyboardPopup::makeButton(
const std::string &key, const std::string& key,
const std::string &shiftedKey, const std::string& shiftedKey,
const std::string &altedKey, const std::string& altedKey,
const std::string &altshiftedKey) { const std::string& altshiftedKey)
{
std::shared_ptr<ButtonComponent> button = std::make_shared<ButtonComponent>( std::shared_ptr<ButtonComponent> button = std::make_shared<ButtonComponent>(
mWindow, key, key, mWindow, key, key,
[this, key, shiftedKey, altedKey, altshiftedKey] { [this, key, shiftedKey, altedKey, altshiftedKey] {
if (key == (OK_SYMBOL) || key.find("OK") != std::string::npos) { if (key == (OK_SYMBOL) || key.find("OK") != std::string::npos) {
mOkCallback(mText->getValue()); mOkCallback(mText->getValue());
delete this; delete this;
return; return;
} else if (key == (DELETE_SYMBOL) || key == "DEL") { }
mText->startEditing(); else if (key == (DELETE_SYMBOL) || key == "DEL") {
mText->textInput("\b");
mText->stopEditing();
return;
} else if (key == "SPACE" || key == " ") {
mText->startEditing();
mText->textInput(" ");
mText->stopEditing();
return;
} else if (key == "LOAD") {
mText->setValue(mDefaultValue->getValue());
mText->setCursor(mDefaultValue->getValue().size());
return;
} else if (key == "CLEAR") {
mText->setValue("");
return;
} else if (key == "CANCEL") {
delete this;
return;
}
if (mAlt && altedKey.empty())
return;
mText->startEditing(); mText->startEditing();
mText->textInput("\b");
if (mShift && mAlt)
mText->textInput(altshiftedKey.c_str());
else if (mAlt)
mText->textInput(altedKey.c_str());
else if (mShift)
mText->textInput(shiftedKey.c_str());
else
mText->textInput(key.c_str());
mText->stopEditing(); mText->stopEditing();
}, return;
false, true); }
else if (key == "SPACE" || key == " ") {
mText->startEditing();
mText->textInput(" ");
mText->stopEditing();
return;
}
else if (key == "LOAD") {
mText->setValue(mDefaultValue->getValue());
mText->setCursor(mDefaultValue->getValue().size());
return;
}
else if (key == "CLEAR") {
mText->setValue("");
return;
}
else if (key == "CANCEL") {
delete this;
return;
}
if (mAlt && altedKey.empty())
return;
mText->startEditing();
if (mShift && mAlt)
mText->textInput(altshiftedKey.c_str());
else if (mAlt)
mText->textInput(altedKey.c_str());
else if (mShift)
mText->textInput(shiftedKey.c_str());
else
mText->textInput(key.c_str());
mText->stopEditing();
},
false, true);
KeyboardButton kb(button, key, shiftedKey, altedKey, altshiftedKey); KeyboardButton kb(button, key, shiftedKey, altedKey, altshiftedKey);
mKeyboardButtons.push_back(kb); mKeyboardButtons.push_back(kb);

View file

@ -15,25 +15,26 @@
#include "components/ComponentGrid.h" #include "components/ComponentGrid.h"
#include "components/TextEditComponent.h" #include "components/TextEditComponent.h"
class GuiTextEditKeyboardPopup : public GuiComponent { class GuiTextEditKeyboardPopup : public GuiComponent
{
public: public:
GuiTextEditKeyboardPopup(Window *window, GuiTextEditKeyboardPopup(Window* window,
const HelpStyle &helpstyle, const HelpStyle& helpstyle,
const std::string &title, const std::string& title,
const std::string &initValue, const std::string& initValue,
const std::function<void(const std::string &)> &okCallback, const std::function<void(const std::string&)>& okCallback,
bool multiLine, bool multiLine,
const std::string &acceptBtnHelpText = "OK", const std::string& acceptBtnHelpText = "OK",
const std::string &saveConfirmationText = "SAVE CHANGES?", const std::string& saveConfirmationText = "SAVE CHANGES?",
const std::string &infoString = "", const std::string& infoString = "",
const std::string &defaultValue = "", const std::string& defaultValue = "",
const std::string &loadBtnHelpText = "LOAD DEFAULT", const std::string& loadBtnHelpText = "LOAD DEFAULT",
const std::string &clearBtnHelpText = "CLEAR", const std::string& clearBtnHelpText = "CLEAR",
const std::string &cancelBtnHelpText = "DISCARD CHANGES"); const std::string& cancelBtnHelpText = "DISCARD CHANGES");
void onSizeChanged() override; void onSizeChanged() override;
bool input(InputConfig *config, Input input) override; bool input(InputConfig* config, Input input) override;
void update(int deltaTime) override; void update(int deltaTime) override;
@ -42,7 +43,8 @@ public:
HelpStyle getHelpStyle() override { return mHelpStyle; } HelpStyle getHelpStyle() override { return mHelpStyle; }
private: private:
class KeyboardButton { class KeyboardButton
{
public: public:
std::shared_ptr<ButtonComponent> button; std::shared_ptr<ButtonComponent> button;
const std::string key; const std::string key;
@ -51,11 +53,15 @@ private:
const std::string altshiftedKey; const std::string altshiftedKey;
KeyboardButton(const std::shared_ptr<ButtonComponent> b, KeyboardButton(const std::shared_ptr<ButtonComponent> b,
const std::string &k, const std::string& k,
const std::string &sk, const std::string& sk,
const std::string &ak, const std::string& ak,
const std::string &ask) const std::string& ask)
: button{b}, key{k}, shiftedKey{sk}, altedKey{ak}, altshiftedKey{ask} {}; : button{b}
, key{k}
, shiftedKey{sk}
, altedKey{ak}
, altshiftedKey{ask} {};
}; };
void updateDeleteRepeat(int deltaTime); void updateDeleteRepeat(int deltaTime);
@ -68,10 +74,10 @@ private:
void altShiftKeys(); void altShiftKeys();
std::shared_ptr<ButtonComponent> makeButton(const std::string &key, std::shared_ptr<ButtonComponent> makeButton(const std::string& key,
const std::string &shiftedKey, const std::string& shiftedKey,
const std::string &altedKey, const std::string& altedKey,
const std::string &altshiftedKey); const std::string& altshiftedKey);
std::vector<KeyboardButton> mKeyboardButtons; std::vector<KeyboardButton> mKeyboardButtons;
@ -95,7 +101,7 @@ private:
std::string mClearBtnHelpText; std::string mClearBtnHelpText;
std::string mCancelBtnHelpText; std::string mCancelBtnHelpText;
std::function<void(const std::string &)> mOkCallback; std::function<void(const std::string&)> mOkCallback;
bool mMultiLine; bool mMultiLine;
bool mComplexMode; bool mComplexMode;

View file

@ -15,25 +15,35 @@
#include "components/MenuComponent.h" #include "components/MenuComponent.h"
#include "guis/GuiMsgBox.h" #include "guis/GuiMsgBox.h"
GuiTextEditPopup::GuiTextEditPopup(Window *window, GuiTextEditPopup::GuiTextEditPopup(Window* window,
const HelpStyle &helpstyle, const HelpStyle& helpstyle,
const std::string &title, const std::string& title,
const std::string &initValue, const std::string& initValue,
const std::function<void(const std::string &)> &okCallback, const std::function<void(const std::string&)>& okCallback,
bool multiLine, bool multiLine,
const std::string &acceptBtnText, const std::string& acceptBtnText,
const std::string &saveConfirmationText, const std::string& saveConfirmationText,
const std::string &infoString, const std::string& infoString,
const std::string &defaultValue, const std::string& defaultValue,
const std::string &loadBtnHelpText, const std::string& loadBtnHelpText,
const std::string &clearBtnHelpText, const std::string& clearBtnHelpText,
const std::string &cancelBtnHelpText) const std::string& cancelBtnHelpText)
: GuiComponent{window}, mBackground{window, ":/graphics/frame.svg"}, : GuiComponent{window}
mGrid{window, glm::ivec2{1, (infoString != "" && defaultValue != "" ? 5 : 3)}}, mHelpStyle{helpstyle}, , mBackground{window, ":/graphics/frame.svg"}
mInitValue{initValue}, mAcceptBtnText{acceptBtnText}, mSaveConfirmationText{saveConfirmationText}, , mGrid{window, glm::ivec2{1, (infoString != "" && defaultValue != "" ? 5 : 3)}}
mLoadBtnHelpText{loadBtnHelpText}, mClearBtnHelpText{clearBtnHelpText}, mCancelBtnHelpText{cancelBtnHelpText}, , mHelpStyle{helpstyle}
mOkCallback{okCallback}, mMultiLine{multiLine}, mComplexMode{(infoString != "" && defaultValue != "")}, , mInitValue{initValue}
mDeleteRepeat{false}, mDeleteRepeatTimer{0} { , mAcceptBtnText{acceptBtnText}
, mSaveConfirmationText{saveConfirmationText}
, mLoadBtnHelpText{loadBtnHelpText}
, mClearBtnHelpText{clearBtnHelpText}
, mCancelBtnHelpText{cancelBtnHelpText}
, mOkCallback{okCallback}
, mMultiLine{multiLine}
, mComplexMode{(infoString != "" && defaultValue != "")}
, mDeleteRepeat{false}
, mDeleteRepeatTimer{0}
{
addChild(&mBackground); addChild(&mBackground);
addChild(&mGrid); addChild(&mGrid);
@ -42,9 +52,9 @@ GuiTextEditPopup::GuiTextEditPopup(Window *window,
if (mComplexMode) { if (mComplexMode) {
mInfoString = std::make_shared<TextComponent>( mInfoString = std::make_shared<TextComponent>(
mWindow, infoString, Font::get(FONT_SIZE_SMALL), 0x555555FF, ALIGN_CENTER); mWindow, infoString, Font::get(FONT_SIZE_SMALL), 0x555555FF, ALIGN_CENTER);
mDefaultValue = std::make_shared<TextComponent>( mDefaultValue = std::make_shared<TextComponent>(
mWindow, defaultValue, Font::get(FONT_SIZE_SMALL), 0x555555FF, ALIGN_CENTER); mWindow, defaultValue, Font::get(FONT_SIZE_SMALL), 0x555555FF, ALIGN_CENTER);
} }
mText = std::make_shared<TextEditComponent>(mWindow); mText = std::make_shared<TextEditComponent>(mWindow);
@ -58,11 +68,11 @@ GuiTextEditPopup::GuiTextEditPopup(Window *window,
})); }));
if (mComplexMode) { if (mComplexMode) {
buttons.push_back(std::make_shared<ButtonComponent>( buttons.push_back(std::make_shared<ButtonComponent>(
mWindow, "load", loadBtnHelpText, [this, defaultValue] { mWindow, "load", loadBtnHelpText, [this, defaultValue] {
mText->setValue(defaultValue); mText->setValue(defaultValue);
mText->setCursor(0); mText->setCursor(0);
mText->setCursor(defaultValue.size()); mText->setCursor(defaultValue.size());
})); }));
} }
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "clear", clearBtnHelpText, buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "clear", clearBtnHelpText,
@ -99,21 +109,22 @@ GuiTextEditPopup::GuiTextEditPopup(Window *window,
if (mComplexMode) { if (mComplexMode) {
float infoWidth = float infoWidth =
glm::clamp(0.70f * aspectValue, 0.34f, 0.85f) * Renderer::getScreenWidth(); glm::clamp(0.70f * aspectValue, 0.34f, 0.85f) * Renderer::getScreenWidth();
float windowWidth = float windowWidth =
glm::clamp(0.75f * aspectValue, 0.40f, 0.90f) * Renderer::getScreenWidth(); glm::clamp(0.75f * aspectValue, 0.40f, 0.90f) * Renderer::getScreenWidth();
mDefaultValue->setSize(infoWidth, mDefaultValue->getFont()->getHeight()); mDefaultValue->setSize(infoWidth, mDefaultValue->getFont()->getHeight());
setSize(windowWidth, mTitle->getFont()->getHeight() + textHeight + setSize(windowWidth, mTitle->getFont()->getHeight() + textHeight +
mButtonGrid->getSize().y + mButtonGrid->getSize().y * 1.85f); mButtonGrid->getSize().y + mButtonGrid->getSize().y * 1.85f);
setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f,
(Renderer::getScreenHeight() - mSize.y) / 2.0f); (Renderer::getScreenHeight() - mSize.y) / 2.0f);
} else { }
else {
float width = glm::clamp(0.54f * aspectValue, 0.20f, 0.70f) * Renderer::getScreenWidth(); float width = glm::clamp(0.54f * aspectValue, 0.20f, 0.70f) * Renderer::getScreenWidth();
setSize(width, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y + setSize(width, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y +
mButtonGrid->getSize().y / 2.0f); mButtonGrid->getSize().y / 2.0f);
setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f, setPosition((Renderer::getScreenWidth() - mSize.x) / 2.0f,
(Renderer::getScreenHeight() - mSize.y) / 2.0f); (Renderer::getScreenHeight() - mSize.y) / 2.0f);
} }
@ -124,7 +135,8 @@ GuiTextEditPopup::GuiTextEditPopup(Window *window,
mText->startEditing(); mText->startEditing();
} }
void GuiTextEditPopup::onSizeChanged() { void GuiTextEditPopup::onSizeChanged()
{
mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f}); mBackground.fitTo(mSize, glm::vec3{}, glm::vec2{-32.0f, -32.0f});
mText->setSize(mSize.x - 40.0f * Renderer::getScreenHeightModifier(), mText->getSize().y); mText->setSize(mSize.x - 40.0f * Renderer::getScreenHeightModifier(), mText->getSize().y);
@ -138,7 +150,8 @@ void GuiTextEditPopup::onSizeChanged() {
mGrid.setSize(mSize); mGrid.setSize(mSize);
} }
bool GuiTextEditPopup::input(InputConfig *config, Input input) { bool GuiTextEditPopup::input(InputConfig* config, Input input)
{
// Enter key (main key or via numpad) accepts the changes. // Enter key (main key or via numpad) accepts the changes.
if (config->getDeviceId() == DEVICE_KEYBOARD && mText->isEditing() && !mMultiLine && if (config->getDeviceId() == DEVICE_KEYBOARD && mText->isEditing() && !mMultiLine &&
input.value && (input.id == SDLK_RETURN || input.id == SDLK_KP_ENTER)) { input.value && (input.id == SDLK_RETURN || input.id == SDLK_KP_ENTER)) {
@ -146,7 +159,7 @@ bool GuiTextEditPopup::input(InputConfig *config, Input input) {
delete this; delete this;
return true; return true;
} }
// Dito for the A button if using a controller. // Dito for the A button if using a controller.
else if (config->getDeviceId() != DEVICE_KEYBOARD && mText->isEditing() && else if (config->getDeviceId() != DEVICE_KEYBOARD && mText->isEditing() &&
config->isMappedTo("a", input) && input.value) { config->isMappedTo("a", input) && input.value) {
this->mOkCallback(mText->getValue()); this->mOkCallback(mText->getValue());
@ -166,18 +179,19 @@ bool GuiTextEditPopup::input(InputConfig *config, Input input) {
if (mText->getValue() != mInitValue) { if (mText->getValue() != mInitValue) {
// Changes were made, ask if the user wants to save them. // Changes were made, ask if the user wants to save them.
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
mWindow, mHelpStyle, mSaveConfirmationText, "YES", mWindow, mHelpStyle, mSaveConfirmationText, "YES",
[this] { [this] {
this->mOkCallback(mText->getValue()); this->mOkCallback(mText->getValue());
delete this; delete this;
return true; return true;
}, },
"NO", "NO",
[this] { [this] {
delete this; delete this;
return true; return true;
})); }));
} else { }
else {
delete this; delete this;
return true; return true;
} }
@ -202,7 +216,8 @@ bool GuiTextEditPopup::input(InputConfig *config, Input input) {
if (!editing) if (!editing)
mText->stopEditing(); mText->stopEditing();
} else { }
else {
mDeleteRepeat = false; mDeleteRepeat = false;
} }
return true; return true;
@ -228,12 +243,14 @@ bool GuiTextEditPopup::input(InputConfig *config, Input input) {
return false; return false;
} }
void GuiTextEditPopup::update(int deltaTime) { void GuiTextEditPopup::update(int deltaTime)
{
updateDeleteRepeat(deltaTime); updateDeleteRepeat(deltaTime);
GuiComponent::update(deltaTime); GuiComponent::update(deltaTime);
} }
std::vector<HelpPrompt> GuiTextEditPopup::getHelpPrompts() { std::vector<HelpPrompt> GuiTextEditPopup::getHelpPrompts()
{
std::vector<HelpPrompt> prompts = mGrid.getHelpPrompts(); std::vector<HelpPrompt> prompts = mGrid.getHelpPrompts();
if (mText->isEditing()) if (mText->isEditing())
@ -245,7 +262,8 @@ std::vector<HelpPrompt> GuiTextEditPopup::getHelpPrompts() {
return prompts; return prompts;
} }
void GuiTextEditPopup::updateDeleteRepeat(int deltaTime) { void GuiTextEditPopup::updateDeleteRepeat(int deltaTime)
{
if (!mDeleteRepeat) if (!mDeleteRepeat)
return; return;

View file

@ -15,25 +15,26 @@
#include "components/ComponentGrid.h" #include "components/ComponentGrid.h"
#include "components/TextEditComponent.h" #include "components/TextEditComponent.h"
class GuiTextEditPopup : public GuiComponent { class GuiTextEditPopup : public GuiComponent
{
public: public:
GuiTextEditPopup(Window *window, GuiTextEditPopup(Window* window,
const HelpStyle &helpstyle, const HelpStyle& helpstyle,
const std::string &title, const std::string& title,
const std::string &initValue, const std::string& initValue,
const std::function<void(const std::string &)> &okCallback, const std::function<void(const std::string&)>& okCallback,
bool multiLine, bool multiLine,
const std::string &acceptBtnText = "OK", const std::string& acceptBtnText = "OK",
const std::string &saveConfirmationText = "SAVE CHANGES?", const std::string& saveConfirmationText = "SAVE CHANGES?",
const std::string &infoString = "", const std::string& infoString = "",
const std::string &defaultValue = "", const std::string& defaultValue = "",
const std::string &loadBtnHelpText = "LOAD DEFAULT", const std::string& loadBtnHelpText = "LOAD DEFAULT",
const std::string &clearBtnHelpText = "CLEAR", const std::string& clearBtnHelpText = "CLEAR",
const std::string &cancelBtnHelpText = "DISCARD CHANGES"); const std::string& cancelBtnHelpText = "DISCARD CHANGES");
void onSizeChanged() override; void onSizeChanged() override;
bool input(InputConfig *config, Input input) override; bool input(InputConfig* config, Input input) override;
void update(int deltaTime) override; void update(int deltaTime) override;
@ -61,7 +62,7 @@ private:
std::string mClearBtnHelpText; std::string mClearBtnHelpText;
std::string mCancelBtnHelpText; std::string mCancelBtnHelpText;
std::function<void(const std::string &)> mOkCallback; std::function<void(const std::string&)> mOkCallback;
bool mMultiLine; bool mMultiLine;
bool mComplexMode; bool mComplexMode;

View file

@ -562,18 +562,18 @@ float Font::getNewlineStartOffset(const std::string& text,
endChar = static_cast<int>(text.find('\n', charStart)); endChar = static_cast<int>(text.find('\n', charStart));
return (xLen - sizeText(text.substr(charStart, return (xLen - sizeText(text.substr(charStart,
static_cast<size_t>(endChar) != std::string::npos ? static_cast<size_t>(endChar) != std::string::npos ?
endChar - charStart : endChar - charStart :
endChar)) endChar))
.x) / .x) /
2.0f; 2.0f;
} }
case ALIGN_RIGHT: { case ALIGN_RIGHT: {
int endChar = static_cast<int>(text.find('\n', charStart)); int endChar = static_cast<int>(text.find('\n', charStart));
return xLen - (sizeText(text.substr(charStart, return xLen - (sizeText(text.substr(charStart,
static_cast<size_t>(endChar) != std::string::npos ? static_cast<size_t>(endChar) != std::string::npos ?
endChar - charStart : endChar - charStart :
endChar)) endChar))
.x); .x);
} }
default: default:
return 0; return 0;

View file

@ -143,7 +143,7 @@ bool TextureResource::bind()
} }
} }
std::shared_ptr<TextureResource> TextureResource::get(const std::string &path, std::shared_ptr<TextureResource> TextureResource::get(const std::string& path,
bool tile, bool tile,
bool forceLoad, bool forceLoad,
bool dynamic, bool dynamic,

View file

@ -25,7 +25,7 @@ class TextureData;
class TextureResource : public IReloadable class TextureResource : public IReloadable
{ {
public: public:
static std::shared_ptr<TextureResource> get(const std::string &path, static std::shared_ptr<TextureResource> get(const std::string& path,
bool tile = false, bool tile = false,
bool forceLoad = false, bool forceLoad = false,
bool dynamic = true, bool dynamic = true,
@ -33,7 +33,7 @@ public:
float scaleDuringLoad = 1.0f, float scaleDuringLoad = 1.0f,
bool cacheImage = false); bool cacheImage = false);
void initFromPixels(const unsigned char *dataRGBA, size_t width, size_t height); void initFromPixels(const unsigned char* dataRGBA, size_t width, size_t height);
virtual void initFromMemory(const char* data, size_t length); virtual void initFromMemory(const char* data, size_t length);
static void manualUnload(std::string path, bool tile); static void manualUnload(std::string path, bool tile);