diff --git a/CMakeLists.txt b/CMakeLists.txt index 706ba1604..766f14169 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,7 +221,6 @@ set(ES_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/components/DateTimeComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ImageComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/NinePatchComponent.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/components/OptionListComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/RatingComponent.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/ScrollableContainer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/SliderComponent.cpp diff --git a/src/components/GuiSettingsMenu.cpp b/src/components/GuiSettingsMenu.cpp index 67f30b2ae..30a3bd2d2 100644 --- a/src/components/GuiSettingsMenu.cpp +++ b/src/components/GuiSettingsMenu.cpp @@ -3,13 +3,17 @@ #include "../Settings.h" #include "../VolumeControl.h" +#include "../scrapers/TheArchiveScraper.h" +#include "../scrapers/GamesDBScraper.h" + GuiSettingsMenu::GuiSettingsMenu(Window* window) : GuiComponent(window), - mList(window, Eigen::Vector2i(2, 4)), + mList(window, Eigen::Vector2i(2, 5)), mBox(mWindow, ":/frame.png", 0x444444FF), mDrawFramerateSwitch(window), mVolumeSlider(window, 0, 100, 1), mDisableSoundsSwitch(window, false), - mSaveLabel(window) + mSaveLabel(window), + mScraperOptList(window) { loadStates(); @@ -20,6 +24,7 @@ GuiSettingsMenu::GuiSettingsMenu(Window* window) : GuiComponent(window), using namespace Eigen; + //drawFramerate label TextComponent* label = new TextComponent(mWindow); label->setText("Draw Framerate: "); label->setColor(0x0000FFFF); @@ -48,11 +53,27 @@ GuiSettingsMenu::GuiSettingsMenu(Window* window) : GuiComponent(window), mList.setEntry(Vector2i(1, 2), Vector2i(1, 1), &mDisableSoundsSwitch, true, ComponentListComponent::AlignCenter, Matrix(true, true)); + //scraper label + label = new TextComponent(mWindow); + label->setText("Scraper: "); + label->setColor(0x0000FFFF); + mLabels.push_back(label); + mList.setEntry(Vector2i(0, 3), Vector2i(1, 1), label, false, ComponentListComponent::AlignRight); + + //fill scraper list + std::vector< std::shared_ptr > scrapers; + scrapers.push_back(std::shared_ptr(new GamesDBScraper())); + scrapers.push_back(std::shared_ptr(new TheArchiveScraper())); + mScraperOptList.populate(scrapers, [&] (const std::shared_ptr& s) { + return mScraperOptList.makeEntry(s->getName(), 0x00FF00FF, s); + } ); + + mList.setEntry(Vector2i(1, 3), Vector2i(1, 1), &mScraperOptList, true, ComponentListComponent::AlignCenter); //save label mSaveLabel.setText("SAVE"); mSaveLabel.setColor(0x000000FF); - mList.setEntry(Vector2i(0, 3), Vector2i(2, 1), &mSaveLabel, true, ComponentListComponent::AlignCenter, Matrix(false, true)); + mList.setEntry(Vector2i(0, 4), Vector2i(2, 1), &mSaveLabel, true, ComponentListComponent::AlignCenter, Matrix(false, true)); //center list mList.setPosition(Renderer::getScreenWidth() / 2 - mList.getSize().x() / 2, Renderer::getScreenHeight() / 2 - mList.getSize().y() / 2); diff --git a/src/components/GuiSettingsMenu.h b/src/components/GuiSettingsMenu.h index f15fb965b..2f85bb34f 100644 --- a/src/components/GuiSettingsMenu.h +++ b/src/components/GuiSettingsMenu.h @@ -8,6 +8,8 @@ #include "SliderComponent.h" #include "TextComponent.h" #include "NinePatchComponent.h" +#include "OptionListComponent.h" +#include "../scrapers/Scraper.h" class GuiSettingsMenu : public GuiComponent { @@ -28,6 +30,7 @@ private: SwitchComponent mDrawFramerateSwitch; SliderComponent mVolumeSlider; SwitchComponent mDisableSoundsSwitch; + OptionListComponent< std::shared_ptr > mScraperOptList; TextComponent mSaveLabel; std::vector mLabels; diff --git a/src/components/OptionListComponent.cpp b/src/components/OptionListComponent.cpp deleted file mode 100644 index 76a071da2..000000000 --- a/src/components/OptionListComponent.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "OptionListComponent.h" - -OptionListComponent::OptionListComponent(Window* window) : GuiComponent(window), - mClosedCallback(nullptr) -{ -} - -void OptionListComponent::setClosedCallback(std::function)> callback) -{ - mClosedCallback = callback; -} - -bool OptionListComponent::input(InputConfig* config, Input input) -{ - return GuiComponent::input(config, input); -} - -void OptionListComponent::render(const Eigen::Affine3f& parentTrans) -{ - Eigen::Affine3f trans = parentTrans * getTransform(); - - renderChildren(trans); -} - -template -void OptionListComponent::populate(const std::vector& vec, std::function selector) -{ - for(auto it = vec.begin(); it != vec.end(); it++) - { - ListEntry e = selector(*it); - if(!e.name.empty()) - mEntries.push_back(e); - } -} - -std::vector OptionListComponent::getSelected() -{ - std::vector ret; - for(auto it = mEntries.begin(); it != mEntries.end(); it++) - { - if((*it).selected) - ret.push_back(&(*it)); - } - - return ret; -} - -void OptionListComponent::close() -{ - if(mClosedCallback) - mClosedCallback(getSelected()); - - delete this; -} - diff --git a/src/components/OptionListComponent.h b/src/components/OptionListComponent.h index 68cb614d9..e2955d38c 100644 --- a/src/components/OptionListComponent.h +++ b/src/components/OptionListComponent.h @@ -1,38 +1,189 @@ #pragma once #include "../GuiComponent.h" +#include "../Font.h" #include #include +#include "../Renderer.h" +#include "../Window.h" //Used to display a list of options. //Can select one or multiple options. -struct ListEntry -{ - std::string name; - unsigned int color; - bool selected; -}; - +template class OptionListComponent : public GuiComponent { public: - OptionListComponent(Window* window); + OptionListComponent(Window* window) : GuiComponent(window), + mClosedCallback(nullptr), mCursor(0), mScrollOffset(0) + { + } - bool input(InputConfig* config, Input input); - void render(const Eigen::Affine3f& trans); + struct ListEntry + { + std::string text; + unsigned int color; + bool selected; + T object; + }; - void setClosedCallback(std::function)> callback); - - template - void populate(const std::vector& vec, std::function selector); - std::vector getSelected(); + void setClosedCallback(std::function)> callback) + { + mClosedCallback = callback; + } + + bool input(InputConfig* config, Input input) + { + if(input.value != 0) + { + if(config->isMappedTo("b", input)) + { + close(); + return true; + } + if(config->isMappedTo("a", input)) + { + select(mCursor); + return true; + } + if(mEntries.size() > 1) + { + if(config->isMappedTo("up", input)) + { + if(mCursor > 0) + { + mCursor--; + return true; + } + } + if(config->isMappedTo("down", input)) + { + if(mCursor < mEntries.size() - 1) + { + mCursor++; + return true; + } + } + } + } + + return GuiComponent::input(config, input); + } + + void render(const Eigen::Affine3f& parentTrans) + { + Eigen::Affine3f trans = parentTrans * getTransform(); + + std::shared_ptr font = getFont(); + + Renderer::pushClipRect(Eigen::Vector2i((int)trans.translation().x(), (int)trans.translation().y()), + Eigen::Vector2i((int)getSize().x(), (int)getSize().y())); + + for(unsigned int i = mScrollOffset; i < mTextCaches.size(); i++) + { + Renderer::setMatrix(trans); + + if(i == mCursor) + Renderer::drawRect(0, 0, (int)mSize.x(), font->getHeight(), 0x000000FF); + + font->renderTextCache(mTextCaches.at(i)); + trans = trans.translate(Eigen::Vector3f(0, (float)font->getHeight(), 0)); + } + + Renderer::popClipRect(); + + trans = parentTrans * getTransform(); + renderChildren(trans); + } + + ListEntry makeEntry(const std::string& name, unsigned int color, T obj) const + { + ListEntry e = {name, color, false, obj}; + return e; + } + + void populate(std::vector& vec, std::function selector) + { + for(auto it = vec.begin(); it != vec.end(); it++) + { + ListEntry e = selector(*it); + if(!e.text.empty()) + mEntries.push_back(e); + } + + updateTextCaches(); + } + + void addEntry(ListEntry e) + { + mEntries.push_back(e); + updateTextCaches(); + } + + std::vector getSelected() + { + std::vector ret; + for(auto it = mEntries.begin(); it != mEntries.end(); it++) + { + if((*it).selected) + ret.push_back(&(*it)); + } + + return ret; + } private: - void close(); + void select(unsigned int i) + { + if(i >= mEntries.size()) + return; + + mEntries.at(i).selected = !mEntries.at(i).selected; + updateTextCaches(); + } + + void close() + { + if(mClosedCallback) + mClosedCallback(getSelected()); + } + + void updateTextCaches() + { + for(auto it = mTextCaches.begin(); it != mTextCaches.end(); it++) + { + delete *it; + } + mTextCaches.clear(); + + TextCache* cache; + std::shared_ptr font = getFont(); + Eigen::Vector2f newSize = getSize(); + newSize[1] = 0; + for(unsigned int i = 0; i < mEntries.size(); i++) + { + cache = font->buildTextCache(mEntries.at(i).text, 0, 0, mEntries.at(i).color); + mTextCaches.push_back(cache); + + if(cache->metrics.size.x() > newSize.x()) + newSize[0] = cache->metrics.size.x(); + + newSize[1] += cache->metrics.size.y(); + } + setSize(newSize); + } + + std::shared_ptr getFont() + { + return Font::get(*mWindow->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_SMALL); + } + std::function)> mClosedCallback; + unsigned int mCursor; + unsigned int mScrollOffset; std::vector mEntries; + std::vector mTextCaches; }; diff --git a/src/scrapers/GamesDBScraper.cpp b/src/scrapers/GamesDBScraper.cpp index 8965529a3..1d8d7e39d 100644 --- a/src/scrapers/GamesDBScraper.cpp +++ b/src/scrapers/GamesDBScraper.cpp @@ -5,6 +5,8 @@ #include "../pugiXML/pugixml.hpp" #include "../MetaData.h" +const char* GamesDBScraper::getName() { return "TheGamesDB"; } + std::shared_ptr GamesDBScraper::makeHttpReq(ScraperSearchParams params) { std::string path = "/api/GetGame.php?"; diff --git a/src/scrapers/GamesDBScraper.h b/src/scrapers/GamesDBScraper.h index 3c80cde50..3a306ee99 100644 --- a/src/scrapers/GamesDBScraper.h +++ b/src/scrapers/GamesDBScraper.h @@ -5,6 +5,8 @@ class GamesDBScraper : public Scraper { +public: + const char* getName(); private: std::shared_ptr makeHttpReq(ScraperSearchParams params) override; std::vector parseReq(ScraperSearchParams params, std::shared_ptr) override; diff --git a/src/scrapers/Scraper.h b/src/scrapers/Scraper.h index 9bb2cff7a..f5f9a8ed3 100644 --- a/src/scrapers/Scraper.h +++ b/src/scrapers/Scraper.h @@ -24,7 +24,9 @@ public: virtual std::vector getResults(ScraperSearchParams params); virtual void getResultsAsync(ScraperSearchParams params, Window* window, std::function)> returnFunc); + virtual const char* getName() = 0; private: virtual std::shared_ptr makeHttpReq(ScraperSearchParams params) = 0; virtual std::vector parseReq(ScraperSearchParams params, std::shared_ptr) = 0; }; + diff --git a/src/scrapers/TheArchiveScraper.cpp b/src/scrapers/TheArchiveScraper.cpp index 73ad0dbc6..61a5e03ca 100644 --- a/src/scrapers/TheArchiveScraper.cpp +++ b/src/scrapers/TheArchiveScraper.cpp @@ -4,6 +4,8 @@ #include "../Log.h" #include "../pugiXML/pugixml.hpp" +const char* TheArchiveScraper::getName() { return "TheArchiveVG"; } + std::shared_ptr TheArchiveScraper::makeHttpReq(ScraperSearchParams params) { std::string path = "/2.0/Archive.search/xml/7TTRM4MNTIKR2NNAGASURHJOZJ3QXQC5/"; diff --git a/src/scrapers/TheArchiveScraper.h b/src/scrapers/TheArchiveScraper.h index a9a027ee8..bf5ef0bef 100644 --- a/src/scrapers/TheArchiveScraper.h +++ b/src/scrapers/TheArchiveScraper.h @@ -5,6 +5,8 @@ class TheArchiveScraper : public Scraper { +public: + const char* getName(); private: std::shared_ptr makeHttpReq(ScraperSearchParams params) override; std::vector parseReq(ScraperSearchParams params, std::shared_ptr) override;