diff --git a/CMakeLists.txt b/CMakeLists.txt index 500218b7b..26a3f7759 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,9 +172,11 @@ set(ES_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMetaDataEd.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameScraper.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMenu.h ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiSettingsMenu.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/scrapers/Scraper.h ${CMAKE_CURRENT_SOURCE_DIR}/src/scrapers/GamesDBScraper.h ${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugiconfig.hpp ${CMAKE_CURRENT_SOURCE_DIR}/src/pugiXML/pugixml.hpp @@ -221,6 +223,7 @@ set(ES_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMetaDataEd.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameScraper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiSettingsMenu.cpp diff --git a/src/GameData.cpp b/src/GameData.cpp index a49490e53..976d3e058 100644 --- a/src/GameData.cpp +++ b/src/GameData.cpp @@ -5,7 +5,7 @@ #include GameData::GameData(SystemData* system, std::string path) - : mSystem(system), mPath(path), mBaseName(boost::filesystem::path(path).stem().string()), mMetaData(MetaDataList::getDefaultGameMDD()) + : mSystem(system), mPath(path), mBaseName(boost::filesystem::path(path).stem().string()), mMetaData(system->getGameMDD()) { if(mMetaData.get("name").empty()) mMetaData.set("name", mBaseName); diff --git a/src/Settings.cpp b/src/Settings.cpp index 7efd4ba7f..211679d12 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -3,10 +3,11 @@ #include "pugiXML/pugixml.hpp" #include "platform.h" #include +#include "scrapers/GamesDBScraper.h" Settings* Settings::sInstance = NULL; -Settings::Settings() +Settings::Settings() : mScraper(NULL) { setDefaults(); loadFile(); @@ -37,7 +38,10 @@ void Settings::setDefaults() mIntMap["GameListSortIndex"] = 0; - mScraper = NULL; //TODO + if(mScraper) + delete mScraper; + + mScraper = new GamesDBScraper(); //TODO } template diff --git a/src/SystemData.cpp b/src/SystemData.cpp index bdc7d2ecc..7e9d913e3 100644 --- a/src/SystemData.cpp +++ b/src/SystemData.cpp @@ -334,3 +334,8 @@ bool SystemData::hasGamelist() else return true; } + +std::vector SystemData::getGameMDD() +{ + return MetaDataList::getDefaultGameMDD(); +} diff --git a/src/SystemData.h b/src/SystemData.h index b9be59079..a087b8ba4 100644 --- a/src/SystemData.h +++ b/src/SystemData.h @@ -5,6 +5,7 @@ #include #include "FolderData.h" #include "Window.h" +#include "MetaData.h" class GameData; @@ -21,6 +22,7 @@ public: std::string getExtension(); std::string getGamelistPath(); bool hasGamelist(); + std::vector getGameMDD(); void launchGame(Window* window, GameData* game); diff --git a/src/XMLReader.cpp b/src/XMLReader.cpp index 22c9ed282..4cb5c6799 100644 --- a/src/XMLReader.cpp +++ b/src/XMLReader.cpp @@ -155,7 +155,7 @@ void parseGamelist(SystemData* system) game = createGameFromPath(path, system); //load the metadata - *(game->metadata()) = MetaDataList::createFromXML(MetaDataList::getDefaultGameMDD(), gameNode); + *(game->metadata()) = MetaDataList::createFromXML(system->getGameMDD(), gameNode); //make sure name gets set if one didn't exist if(game->metadata()->get("name").empty()) @@ -166,13 +166,13 @@ void parseGamelist(SystemData* system) } } -void addGameDataNode(pugi::xml_node& parent, const GameData* game) +void addGameDataNode(pugi::xml_node& parent, const GameData* game, SystemData* system) { //create game and add to parent node pugi::xml_node newGame = parent.append_child("game"); //write metadata - const_cast(game)->metadata()->appendToXML(newGame, MetaDataList::getDefaultGameMDD()); + const_cast(game)->metadata()->appendToXML(newGame, system->getGameMDD()); if(newGame.children().begin() == newGame.child("name") //first element is name && ++newGame.children().begin() == newGame.children().end() //theres only one element @@ -254,7 +254,7 @@ void updateGamelist(SystemData* system) //either the game content was removed, because it needs to be updated, //or didn't exist in the first place, so just add it - addGameDataNode(root, game); + addGameDataNode(root, game, system); } ++fit; } diff --git a/src/components/ButtonComponent.cpp b/src/components/ButtonComponent.cpp index 555b25eb6..19ad42939 100644 --- a/src/components/ButtonComponent.cpp +++ b/src/components/ButtonComponent.cpp @@ -22,7 +22,7 @@ void ButtonComponent::setPressedFunc(std::function f) bool ButtonComponent::input(InputConfig* config, Input input) { - if(config->isMappedTo("a", input)) + if(config->isMappedTo("a", input) && input.value != 0) { if(mPressedFunc) mPressedFunc(); diff --git a/src/components/ComponentListComponent.cpp b/src/components/ComponentListComponent.cpp index 6504e7b7f..5321a0cbe 100644 --- a/src/components/ComponentListComponent.cpp +++ b/src/components/ComponentListComponent.cpp @@ -13,6 +13,14 @@ ComponentListComponent::ComponentListComponent(Window* window, Eigen::Vector2i g makeCells(gridDimensions); } +ComponentListComponent::~ComponentListComponent() +{ + for(auto iter = mEntries.begin(); iter != mEntries.end(); iter++) + { + delete *iter; + } +} + void ComponentListComponent::makeCells(Eigen::Vector2i size) { if(mGrid) @@ -57,7 +65,7 @@ void ComponentListComponent::setEntry(Eigen::Vector2i pos, Eigen::Vector2i size, return; } - ComponentEntry entry(Eigen::Vector2i(pos.x(), pos.y()), Eigen::Vector2i(size.x(), size.y()), component, updateType, canFocus, align); + ComponentEntry* entry = new ComponentEntry(Eigen::Vector2i(pos.x(), pos.y()), Eigen::Vector2i(size.x(), size.y()), component, updateType, canFocus, align); mEntries.push_back(entry); @@ -65,7 +73,7 @@ void ComponentListComponent::setEntry(Eigen::Vector2i pos, Eigen::Vector2i size, { for(int x = pos.x(); x < pos.x() + size.x(); x++) { - setCell(x, y, &mEntries.back()); + setCell(x, y, mEntries.back()); } } @@ -81,13 +89,40 @@ void ComponentListComponent::setEntry(Eigen::Vector2i pos, Eigen::Vector2i size, // setColumnWidth(pos.x(), (unsigned int)component->getSize().x()); //if(autoFit.y() && (int)getRowHeight(pos.y()) < component->getSize().y()) // setRowHeight(pos.y(), (unsigned int)component->getSize().y()); - updateCellSize(&mEntries.back(), autoFit.x(), autoFit.y()); + updateCellSize(mEntries.back(), autoFit.x(), autoFit.y()); component->setPosition(getCellOffset(pos)); updateSize(); } +void ComponentListComponent::removeEntriesIn(Eigen::Vector2i pos, Eigen::Vector2i size) +{ + auto iter = mEntries.begin(); + while(iter != mEntries.end()) + { + if((*iter)->pos.x() >= pos.x() && (*iter)->pos.x() < pos.x() + size.x() + && (*iter)->pos.y() >= pos.y() && (*iter)->pos.y() < pos.y() + size.y()) + { + delete *iter; + iter = mEntries.erase(iter); + }else{ + iter++; + } + } + + for(int y = pos.y(); y < pos.y() + size.y(); y++) + { + for(int x = pos.x(); x < pos.x() + size.x(); x++) + { + setCell(x, y, NULL); + } + } + + if(!cursorValid()) + resetCursor(); +} + void ComponentListComponent::forceRowHeight(int row, unsigned int size) { mRowHeights[row] = size; @@ -99,7 +134,7 @@ void ComponentListComponent::forceRowHeight(int row, unsigned int size) void ComponentListComponent::forceColumnWidth(int col, unsigned int size) { mColumnWidths[col] = size; - mRowHeightForced[col] = true; + mColumnWidthForced[col] = true; updateSize(); updateComponentOffsets(); } @@ -174,7 +209,7 @@ void ComponentListComponent::updateComponentOffsets() { for(auto iter = mEntries.begin(); iter != mEntries.end(); iter++) { - iter->component->setPosition(getCellOffset(iter->pos)); + (*iter)->component->setPosition(getCellOffset((*iter)->pos)); } } @@ -229,9 +264,9 @@ void ComponentListComponent::updateComponent(GuiComponent* cmp) { for(auto iter = mEntries.begin(); iter != mEntries.end(); iter++) { - if(iter->component == cmp) + if((*iter)->component == cmp) { - updateCellSize(&(*iter)); + updateCellSize(*iter); } } } @@ -277,7 +312,7 @@ void ComponentListComponent::resetCursor() } const Eigen::Vector2i origCursor = mCursor; - mCursor << mEntries.at(0).pos[0], mEntries.at(0).pos[1]; + mCursor << mEntries.at(0)->pos[0], mEntries.at(0)->pos[1]; onCursorMoved(origCursor, mCursor); } @@ -356,15 +391,15 @@ void ComponentListComponent::update(int deltaTime) { for(auto iter = mEntries.begin(); iter != mEntries.end(); iter++) { - switch(iter->updateType) + switch((*iter)->updateType) { case UpdateAlways: - iter->component->update(deltaTime); + (*iter)->component->update(deltaTime); break; case UpdateFocused: - if(cursorValid() && getCell(mCursor.x(), mCursor.y())->component == iter->component) - iter->component->update(deltaTime); + if(cursorValid() && getCell(mCursor.x(), mCursor.y())->component == (*iter)->component) + (*iter)->component->update(deltaTime); break; } } @@ -373,13 +408,9 @@ void ComponentListComponent::update(int deltaTime) void ComponentListComponent::render(const Eigen::Affine3f& parentTrans) { Eigen::Affine3f trans = parentTrans * getTransform(); - Renderer::setMatrix(trans); - - Renderer::drawRect(0, 0, (int)getSize().x(), (int)getSize().y(), 0xFFFFFFAA); - for(auto iter = mEntries.begin(); iter != mEntries.end(); iter++) { - iter->component->render(trans); + (*iter)->component->render(trans); } diff --git a/src/components/ComponentListComponent.h b/src/components/ComponentListComponent.h index 0db561084..f5d226dad 100644 --- a/src/components/ComponentListComponent.h +++ b/src/components/ComponentListComponent.h @@ -6,6 +6,7 @@ class ComponentListComponent : public GuiComponent { public: ComponentListComponent(Window* window, Eigen::Vector2i gridDimensions); + virtual ~ComponentListComponent(); enum UpdateBehavior { @@ -21,6 +22,8 @@ public: void setEntry(Eigen::Vector2i pos, Eigen::Vector2i size, GuiComponent* component, bool canFocus, AlignmentType align, Eigen::Matrix autoFit = Eigen::Matrix(true, true), UpdateBehavior updateType = UpdateAlways); + void removeEntriesIn(Eigen::Vector2i pos, Eigen::Vector2i size); + void onPositionChanged() override; void textInput(const char* text) override; @@ -38,6 +41,8 @@ public: GuiComponent* getSelectedComponent(); + void moveCursor(Eigen::Vector2i dir); + private: class ComponentEntry { @@ -58,18 +63,16 @@ private: } }; - //Offset we render components by (for scrolling). + //Offset we render components by (for scrolling). [unimplemented] Eigen::Vector2f mComponentOffset; Eigen::Vector2i mGridSize; ComponentEntry** mGrid; - std::vector mEntries; + std::vector mEntries; void makeCells(Eigen::Vector2i size); void setCell(unsigned int x, unsigned int y, ComponentEntry* entry); ComponentEntry* getCell(unsigned int x, unsigned int y); - Eigen::Vector2i mSelectedCellIndex; - unsigned int getColumnWidth(int col); unsigned int getRowHeight(int row); @@ -81,7 +84,6 @@ private: Eigen::Vector3f getCellOffset(Eigen::Vector2i gridPos); void updateSize(); - void moveCursor(Eigen::Vector2i dir); void onCursorMoved(Eigen::Vector2i from, Eigen::Vector2i to); Eigen::Vector2i mCursor; @@ -100,43 +102,15 @@ private: // scroll to prev/next selectable component in grid Y // if input == left/right // scroll to prev/next selectable component in grid X -// if input == accept -// call registered function? //entry struct/class // GuiComponent* component - component to work with // bool canFocus - can we pass input to this? (necessary for labels to not be selectable) -// Function* selectFunc? // UpdateBehavior update - how to handle updates (all the time or only when focused) //update -//animate component offset to display selected component within the bounds //pass update to all entries with appropriate update behavior //render //clip rect to our size //render a "selected" effect behind component with focus somehow -// an edge filter would be cool, but we can't really do that without shader support -// a transparent rect will work for now, but it's kind of ugly... -//glTranslatef by our render offset -// doesn't handle getGlobalOffset for our components...would need parenting for that - -//methods -//List::setEntry(Vector2i gridPos, GuiComponent* component, bool canFocus, AlignmentType align, -// Function* selectFunc = NULL, UpdateBehavior updateType = UpdateAlways); - -//example of setting up the SettingsMenu list: -//ComponentListComponent list; -//int row = 0; -//TextComponent* label = new TextComponent(Vector2i(0, 0), "Debug:", font, lblColor, etc); -// -//list.setEntry(Vector2i(-1, row), label, false, AlignRight); -//list.setEntry(Vector2i(0, row++), &mDebugSwitch, true, AlignLeft); -//... -//list.setEntry(Rect(-1, row, 2, 1), &mSaveButton, true, AlignCenter); - -//example of setting up GameGrid list: -//ComponentListComponent list; -//for(int y = 0; y < yMax; y++) -// for(int x = 0; x < xMax; x++) -// list.setEntry(Vector2i(x, y), getGameImage(x, y), true, AlignCenter, &this->onSelectGame); diff --git a/src/components/GuiGameList.cpp b/src/components/GuiGameList.cpp index 97e6d21bb..138a5ebcf 100644 --- a/src/components/GuiGameList.cpp +++ b/src/components/GuiGameList.cpp @@ -132,7 +132,7 @@ bool GuiGameList::input(InputConfig* config, Input input) ScraperSearchParams searchParams; searchParams.game = game; searchParams.system = mSystem; - mWindow->pushGui(new GuiMetaDataEd(mWindow, game->metadata(), MetaDataList::getDefaultGameMDD(), searchParams, game->getBaseName(), + mWindow->pushGui(new GuiMetaDataEd(mWindow, game->metadata(), mSystem->getGameMDD(), searchParams, game->getBaseName(), [&] { updateDetailData(); }, [game, root, this] { root->removeFileRecursive(game); updateList(); } )); diff --git a/src/components/GuiGameScraper.cpp b/src/components/GuiGameScraper.cpp new file mode 100644 index 000000000..d63070dd6 --- /dev/null +++ b/src/components/GuiGameScraper.cpp @@ -0,0 +1,168 @@ +#include "GuiGameScraper.h" +#include "../Renderer.h" +#include "../Log.h" +#include "../scrapers/Scraper.h" +#include "../Settings.h" + +#define RESULT_COUNT 5 + +GuiGameScraper::GuiGameScraper(Window* window, ScraperSearchParams params, std::function doneFunc, std::function skipFunc) : GuiComponent(window), + mList(window, Eigen::Vector2i(2, 7 + RESULT_COUNT)), + mBox(window, ":/frame.png"), + mHeader(window, params.game->getBaseName(), Font::get(*window->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)), + mResultName(window, "", Font::get(*window->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_MEDIUM)), + mResultInfo(window), + mResultDesc(window, "", Font::get(*window->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_SMALL)), + + mSearchLabel(window, "Search for: ", Font::get(*window->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_SMALL)), + mSearchText(window), + + mSearchParams(params), + mDoneFunc(doneFunc), + mSkipFunc(skipFunc) +{ + // FILE NAME + //-------------------------------------- + //Name................. | + //Desc................. | PREVIEW + //..................... | IMAGE? + //....(autoscroll)..... | + //-------------------------------------- + //Search for: [_______________________] + //-------------------------------------- + //Result #1 Name + //Result #2 Name + //Result #3 Name + //Result #4 Name + //Result #5 Name + + addChild(&mBox); + addChild(&mList); + + float sw = (float)Renderer::getScreenWidth(); + float sh = (float)Renderer::getScreenHeight(); + + float colWidth = sw * 0.35f; + + mList.forceColumnWidth(0, (unsigned int)colWidth); + mList.forceColumnWidth(1, (unsigned int)colWidth); + + using namespace Eigen; + + mList.setEntry(Vector2i(0, 0), Vector2i(2, 1), &mHeader, false, ComponentListComponent::AlignCenter); + + //y = 1 is a spacer row + + mResultName.setText(params.game->getName()); + mResultName.setColor(0x3B56CCFF); + mList.setEntry(Vector2i(0, 1), Vector2i(1, 1), &mResultName, false, ComponentListComponent::AlignLeft); + + + mResultDesc.setText(params.game->metadata()->get("desc")); + mResultDesc.setSize(colWidth, 0); + mResultInfo.addChild(&mResultDesc); + mResultInfo.setSize(mResultDesc.getSize().x(), mResultDesc.getFont()->getHeight() * 3.0f); + mList.setEntry(Vector2i(0, 2), Vector2i(1, 1), &mResultInfo, false, ComponentListComponent::AlignLeft); + + //y = 3 is a spacer row + + mList.setEntry(Vector2i(0, 4), Vector2i(1, 1), &mSearchLabel, false, ComponentListComponent::AlignLeft); + mSearchText.setValue(!params.nameOverride.empty() ? params.nameOverride : params.game->getBaseName()); + mSearchText.setSize(colWidth * 2 - mSearchLabel.getSize().x() - 20, mSearchText.getSize().y()); + mList.setEntry(Vector2i(1, 4), Vector2i(1, 1), &mSearchText, true, ComponentListComponent::AlignRight); + + //y = 5 is a spacer row + + std::shared_ptr font = Font::get(*window->getResourceManager(), Font::getDefaultPath(), FONT_SIZE_SMALL); + mResultNames.reserve(RESULT_COUNT); + for(int i = 0; i < RESULT_COUNT; i ++) + { + mResultNames.push_back(TextComponent(mWindow, "RESULT...", font)); + mResultNames.at(i).setColor(0x111111FF); + mList.forceRowHeight(6 + i, (unsigned int)mResultNames.at(i).getSize().y()); + } + + mList.setPosition((sw - mList.getSize().x()) / 2, (sh - mList.getSize().y()) / 2); + + mBox.fitTo(mList.getSize(), mList.getPosition()); + + mResultInfo.setAutoScroll(2200, 0.015f); +} + +void GuiGameScraper::search() +{ + //update mSearchParams + mSearchParams.nameOverride = mSearchText.getValue(); + + Settings::getInstance()->getScraper()->getResultsAsync(mSearchParams, mWindow, std::bind(&GuiGameScraper::onSearchDone, this, std::placeholders::_1)); +} + +void GuiGameScraper::onSearchDone(std::vector results) +{ + mList.removeEntriesIn(Eigen::Vector2i(0, 6), Eigen::Vector2i(1, 5)); + + mScraperResults = results; + + const int end = results.size() > 5 ? 5 : results.size(); //at max display 5 + + if(end == 0) + { + mResultNames.at(0).setText("No games found!"); + mList.setEntry(Eigen::Vector2i(0, 6), Eigen::Vector2i(1, 1), &mResultNames.at(0), false, ComponentListComponent::AlignLeft); + }else{ + for(int i = 0; i < end; i++) + { + mResultNames.at(i).setText(results.at(i).get("name")); + mList.setEntry(Eigen::Vector2i(0, 6 + i), Eigen::Vector2i(1, 1), &mResultNames.at(i), true, ComponentListComponent::AlignLeft); + } + } +} + +int GuiGameScraper::getSelectedIndex() +{ + int index = 0; + for(auto iter = mResultNames.begin(); iter != mResultNames.end(); iter++, index++) + { + if(&(*iter) == mList.getSelectedComponent()) + return index; + } + + return -1; +} + +bool GuiGameScraper::input(InputConfig* config, Input input) +{ + if(config->isMappedTo("a", input) && input.value != 0) + { + //if you're on a result + if(getSelectedIndex()) + { + mDoneFunc(mScraperResults.at(getSelectedIndex())); + delete this; + return true; + } + }else if(config->isMappedTo("b", input) && input.value != 0) + { + if(mSkipFunc) + mSkipFunc(); + delete this; + return true; + } + + bool ret = GuiComponent::input(config, input); + + if(config->isMappedTo("up", input) || config->isMappedTo("down", input)) + { + //update game info pane + int i = getSelectedIndex(); + if(i != -1) + { + mResultName.setText(mScraperResults.at(i).get("name")); + mResultDesc.setText(mScraperResults.at(i).get("desc")); + mResultInfo.setScrollPos(Eigen::Vector2d(0, 0)); + mResultInfo.resetAutoScrollTimer(); + } + } + + return ret; +} diff --git a/src/components/GuiGameScraper.h b/src/components/GuiGameScraper.h new file mode 100644 index 000000000..1f29a5a6f --- /dev/null +++ b/src/components/GuiGameScraper.h @@ -0,0 +1,44 @@ +#pragma once + +#include "../GuiComponent.h" +#include "../scrapers/Scraper.h" +#include "ComponentListComponent.h" +#include "TextComponent.h" +#include "ScrollableContainer.h" +#include "TextEditComponent.h" +#include "NinePatchComponent.h" +#include "../Settings.h" + +class GuiGameScraper : public GuiComponent +{ +public: + GuiGameScraper(Window* window, ScraperSearchParams params, std::function doneFunc, std::function skipFunc = NULL); + + bool input(InputConfig* config, Input input) override; + + void search(); +private: + int getSelectedIndex(); + void onSearchDone(std::vector results); + + ComponentListComponent mList; + NinePatchComponent mBox; + + TextComponent mHeader; + + TextComponent mResultName; + ScrollableContainer mResultInfo; + TextComponent mResultDesc; + + TextComponent mSearchLabel; + TextEditComponent mSearchText; + + std::vector mResultNames; + + ScraperSearchParams mSearchParams; + + std::vector mScraperResults; + + std::function mDoneFunc; + std::function mSkipFunc; +}; diff --git a/src/components/GuiMetaDataEd.cpp b/src/components/GuiMetaDataEd.cpp index 2d183fdba..9b7226768 100644 --- a/src/components/GuiMetaDataEd.cpp +++ b/src/components/GuiMetaDataEd.cpp @@ -3,6 +3,7 @@ #include "../Log.h" #include "AsyncReqComponent.h" #include "../Settings.h" +#include "GuiGameScraper.h" #define MDED_RESERVED_ROWS 3 @@ -10,28 +11,19 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector const std::string& header, std::function saveCallback, std::function deleteFunc) : GuiComponent(window), mScraperParams(scraperParams), mBox(mWindow, ":/frame.png", 0xAAAAAAFF, 0xCCCCCCFF), - mList(window, Eigen::Vector2i(3, mdd.size() + MDED_RESERVED_ROWS)), + mList(window, Eigen::Vector2i(2, mdd.size() + MDED_RESERVED_ROWS)), mHeader(window), + mMetaDataDecl(mdd), mMetaData(md), mSavedCallback(saveCallback), mDeleteFunc(deleteFunc), mDeleteButton(window), mFetchButton(window), mSaveButton(window) { - LOG(LogInfo) << "Creating GuiMetaDataEd"; - - //set size to 80% by 80% of the window - mSize << Renderer::getScreenWidth() * 0.8f, Renderer::getScreenHeight() * 0.8f; - - //center us - mPosition << (Renderer::getScreenWidth() - mSize.x()) / 2, (Renderer::getScreenHeight() - mSize.y()) / 2, 0.0f; - + unsigned int sw = Renderer::getScreenWidth(); + unsigned int sh = Renderer::getScreenHeight(); + addChild(&mBox); - mBox.fitTo(mSize); - - //initialize path display + addChild(&mHeader); - mHeader.setPosition(0, 0); - mHeader.setSize(mSize.x(), 0); - mHeader.setCentered(true); mHeader.setText(header); //initialize buttons @@ -39,8 +31,8 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector if(mDeleteFunc) mDeleteButton.setPressedFunc([&] { mDeleteFunc(); delete this; }); - mFetchButton.setText("FETCH", 0x555555FF); - mFetchButton.setPressedFunc([&] { fetch(); }); + mFetchButton.setText("FETCH", 0x00FF00FF); + mFetchButton.setPressedFunc(std::bind(&GuiMetaDataEd::fetch, this)); mSaveButton.setText("SAVE", 0x0000FFFF); mSaveButton.setPressedFunc([&] { save(); delete this; }); @@ -48,12 +40,26 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector //initialize metadata list addChild(&mList); populateList(mdd); - mList.setPosition((mSize.x() - mList.getSize().x()) / 2, mHeader.getSize().y() + 4); + mList.setPosition((sw - mList.getSize().x()) / 2.0f, (sh - mList.getSize().y()) / 2.0f); //center it + mList.resetCursor(); + + mBox.fitTo(mList.getSize(), mList.getPosition(), Eigen::Vector2f(12, 12)); + + mHeader.setPosition(mList.getPosition()); + mHeader.setSize(mList.getSize().x(), 0); + mHeader.setCentered(true); } GuiMetaDataEd::~GuiMetaDataEd() { - LOG(LogInfo) << "Deleted GuiMetaDataEd"; + for(auto iter = mLabels.begin(); iter != mLabels.end(); iter++) + { + delete *iter; + } + for(auto iter = mEditors.begin(); iter != mEditors.end(); iter++) + { + delete *iter; + } } void GuiMetaDataEd::populateList(const std::vector& mdd) @@ -71,11 +77,11 @@ void GuiMetaDataEd::populateList(const std::vector& mdd) int y = 0; - //delete button - mList.setEntry(Vector2i(0, y), Vector2i(1, 1), &mDeleteButton, true, ComponentListComponent::AlignCenter); - //fetch button - mList.setEntry(Vector2i(1, y), Vector2i(1, 1), &mFetchButton, true, ComponentListComponent::AlignCenter); + mList.setEntry(Vector2i(0, y), Vector2i(1, 1), &mFetchButton, true, ComponentListComponent::AlignLeft); + + //delete button + mList.setEntry(Vector2i(1, y), Vector2i(1, 1), &mDeleteButton, true, ComponentListComponent::AlignRight); y++; @@ -87,7 +93,7 @@ void GuiMetaDataEd::populateList(const std::vector& mdd) mLabels.push_back(label); GuiComponent* ed = MetaDataList::makeEditor(mWindow, iter->type); - ed->setSize(mSize.x() / 2, ed->getSize().y()); + ed->setSize(Renderer::getScreenWidth() * 0.4f, ed->getSize().y()); ed->setValue(mMetaData->get(iter->key)); mList.setEntry(Vector2i(1, y), Vector2i(1, 1), ed, true, ComponentListComponent::AlignRight); mEditors.push_back(ed); @@ -112,11 +118,16 @@ void GuiMetaDataEd::save() void GuiMetaDataEd::fetch() { - Settings::getInstance()->getScraper()->getResultsAsync(mScraperParams, mWindow, std::bind(&GuiMetaDataEd::fetchDone, this, std::placeholders::_1)); + GuiGameScraper* scr = new GuiGameScraper(mWindow, mScraperParams, std::bind(&GuiMetaDataEd::fetchDone, this, std::placeholders::_1)); + mWindow->pushGui(scr); + scr->search(); } -void GuiMetaDataEd::fetchDone(std::vector results) +void GuiMetaDataEd::fetchDone(MetaDataList result) { - + for(unsigned int i = 0; i < mEditors.size(); i++) + { + const std::string key = mMetaDataDecl.at(i).key; + mEditors.at(i)->setValue(result.get(key)); + } } - diff --git a/src/components/GuiMetaDataEd.h b/src/components/GuiMetaDataEd.h index e59424941..7ce136ac1 100644 --- a/src/components/GuiMetaDataEd.h +++ b/src/components/GuiMetaDataEd.h @@ -20,7 +20,7 @@ public: private: void save(); void fetch(); - void fetchDone(std::vector results); + void fetchDone(MetaDataList result); void populateList(const std::vector& mdd); @@ -35,6 +35,7 @@ private: std::vector mLabels; std::vector mEditors; + std::vector mMetaDataDecl; MetaDataList* mMetaData; std::function mSavedCallback; std::function mDeleteFunc; diff --git a/src/components/TextComponent.cpp b/src/components/TextComponent.cpp index 188ef5803..e0484a53d 100644 --- a/src/components/TextComponent.cpp +++ b/src/components/TextComponent.cpp @@ -101,7 +101,7 @@ void TextComponent::onTextChanged() calculateExtent(); std::shared_ptr f = getFont(); - mTextCache = std::unique_ptr(f->buildTextCache(f->wrapText(mText, mSize.x()), 0, 0, (mColor >> 8 << 8) | mOpacity)); + mTextCache = std::shared_ptr(f->buildTextCache(f->wrapText(mText, mSize.x()), 0, 0, (mColor >> 8 << 8) | mOpacity)); } void TextComponent::setValue(const std::string& value) diff --git a/src/components/TextComponent.h b/src/components/TextComponent.h index 99892488f..b828db803 100644 --- a/src/components/TextComponent.h +++ b/src/components/TextComponent.h @@ -8,7 +8,7 @@ class TextComponent : public GuiComponent { public: TextComponent(Window* window); - TextComponent(Window* window, const std::string& text, std::shared_ptr font, Eigen::Vector3f pos, Eigen::Vector2f size); + TextComponent(Window* window, const std::string& text, std::shared_ptr font, Eigen::Vector3f pos = Eigen::Vector3f::Zero(), Eigen::Vector2f size = Eigen::Vector2f::Zero()); void setFont(std::shared_ptr font); void onSizeChanged() override; @@ -21,9 +21,9 @@ public: std::string getValue() const override; void setValue(const std::string& value) override; -private: std::shared_ptr getFont() const; - + +private: void calculateExtent(); void onTextChanged(); @@ -32,7 +32,7 @@ private: std::shared_ptr mFont; Eigen::Matrix mAutoCalcExtent; std::string mText; - std::unique_ptr mTextCache; + std::shared_ptr mTextCache; bool mCentered; }; diff --git a/src/scrapers/GamesDBScraper.cpp b/src/scrapers/GamesDBScraper.cpp index 102a7c9b9..0da2b3f8c 100644 --- a/src/scrapers/GamesDBScraper.cpp +++ b/src/scrapers/GamesDBScraper.cpp @@ -1,5 +1,6 @@ #include "GamesDBScraper.h" #include "../components/AsyncReqComponent.h" +#include "../Log.h" std::vector GamesDBScraper::getResults(ScraperSearchParams params) { @@ -18,6 +19,16 @@ std::vector GamesDBScraper::parseReq(ScraperSearchParams params, s { std::vector mdl; + MetaDataList md(params.system->getGameMDD()); + md.set("name", "JUNK RESULT #1"); + md.set("desc", "Black triangles"); + mdl.push_back(md); + + MetaDataList md2(params.system->getGameMDD()); + md2.set("name", "JUNK RESULT #2"); + md2.set("desc", "Test results are very exciting. Sort of. A little. If you squint. A lot."); + mdl.push_back(md2); + return mdl; } @@ -34,4 +45,3 @@ void GamesDBScraper::getResultsAsync(ScraperSearchParams params, Window* window, window->pushGui(req); } -