mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
updateGamelist now creates a gamelist.xml if one does not exist.
Added GuiMsgBoxOk and GuiMsgBoxYesNo, basic message boxes. Added rating scraping to TheGamesDB scraper. Added warning if platform ID is not set for a system the user has selected to scrape.
This commit is contained in:
parent
12dd8b028d
commit
56b04aec4c
|
@ -178,6 +178,7 @@ set(ES_HEADERS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMetaDataEd.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMetaDataEd.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMsgBoxOk.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMsgBoxOk.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMsgBoxYesNo.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameScraper.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameScraper.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.h
|
||||||
|
@ -236,6 +237,7 @@ set(ES_SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiFastSelect.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMetaDataEd.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMetaDataEd.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMsgBoxOk.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMsgBoxOk.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiMsgBoxYesNo.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameList.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameScraper.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiGameScraper.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/GuiInputConfig.cpp
|
||||||
|
|
|
@ -34,9 +34,10 @@ void Settings::setDefaults()
|
||||||
mBoolMap["WINDOWED"] = false;
|
mBoolMap["WINDOWED"] = false;
|
||||||
mBoolMap["DISABLESOUNDS"] = false;
|
mBoolMap["DISABLESOUNDS"] = false;
|
||||||
mBoolMap["DisableGamelistWrites"] = false;
|
mBoolMap["DisableGamelistWrites"] = false;
|
||||||
|
mBoolMap["ScrapeRatings"] = true;
|
||||||
|
|
||||||
mIntMap["DIMTIME"] = 30*1000;
|
mIntMap["DIMTIME"] = 30*1000;
|
||||||
mIntMap["ScraperResizeWidth"] = 450;
|
mIntMap["ScraperResizeWidth"] = 400;
|
||||||
mIntMap["ScraperResizeHeight"] = 0;
|
mIntMap["ScraperResizeHeight"] = 0;
|
||||||
|
|
||||||
mIntMap["GameListSortIndex"] = 0;
|
mIntMap["GameListSortIndex"] = 0;
|
||||||
|
|
|
@ -198,20 +198,26 @@ void updateGamelist(SystemData* system)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string xmlpath = system->getGamelistPath();
|
std::string xmlpath = system->getGamelistPath();
|
||||||
if(!boost::filesystem::exists(xmlpath))
|
|
||||||
return;
|
|
||||||
|
|
||||||
LOG(LogInfo) << "Parsing XML file \"" << xmlpath << "\" before writing...";
|
|
||||||
|
|
||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
pugi::xml_parse_result result = doc.load_file(xmlpath.c_str());
|
|
||||||
|
|
||||||
if(!result)
|
if(boost::filesystem::exists(xmlpath))
|
||||||
{
|
{
|
||||||
LOG(LogError) << "Error parsing XML file \"" << xmlpath << "\"!\n " << result.description();
|
//parse an existing file first
|
||||||
return;
|
LOG(LogInfo) << "Parsing XML file \"" << xmlpath << "\" before writing...";
|
||||||
|
|
||||||
|
pugi::xml_parse_result result = doc.load_file(xmlpath.c_str());
|
||||||
|
if(!result)
|
||||||
|
{
|
||||||
|
LOG(LogError) << "Error parsing XML file \"" << xmlpath << "\"!\n " << result.description();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//set up an empty gamelist to append to
|
||||||
|
doc.append_child("gameList");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pugi::xml_node root = doc.child("gameList");
|
pugi::xml_node root = doc.child("gameList");
|
||||||
if(!root)
|
if(!root)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "GuiMsgBoxOk.h"
|
#include "GuiMsgBoxOk.h"
|
||||||
#include "../Renderer.h"
|
#include "../Renderer.h"
|
||||||
|
|
||||||
|
#define MSG_WIDTH 0.8f
|
||||||
|
#define MSG_PADDING ((1 - MSG_WIDTH) / 2)
|
||||||
|
|
||||||
GuiMsgBoxOk::GuiMsgBoxOk(Window* window, const std::string& text, std::function<void()> callback) : GuiComponent(window),
|
GuiMsgBoxOk::GuiMsgBoxOk(Window* window, const std::string& text, std::function<void()> callback) : GuiComponent(window),
|
||||||
mCallback(callback),
|
mCallback(callback),
|
||||||
mText(window),
|
mText(window),
|
||||||
|
@ -8,17 +11,17 @@ GuiMsgBoxOk::GuiMsgBoxOk(Window* window, const std::string& text, std::function<
|
||||||
{
|
{
|
||||||
mText.setCentered(true);
|
mText.setCentered(true);
|
||||||
mText.setColor(0x00BB00FF);
|
mText.setColor(0x00BB00FF);
|
||||||
mText.setSize((float)Renderer::getScreenWidth(), 0);
|
mText.setSize(Renderer::getScreenWidth() * MSG_WIDTH, 0);
|
||||||
mText.setText(text);
|
mText.setText(text);
|
||||||
|
|
||||||
mOkText.setCentered(true);
|
mOkText.setCentered(true);
|
||||||
mOkText.setColor(0x0044BBFF);
|
mOkText.setColor(0x0044BBFF);
|
||||||
mOkText.setFont(Font::get(FONT_SIZE_SMALL));
|
mOkText.setFont(Font::get(FONT_SIZE_SMALL));
|
||||||
mOkText.setSize((float)Renderer::getScreenWidth(), 0);
|
mOkText.setSize(Renderer::getScreenWidth() * MSG_WIDTH, 0);
|
||||||
mOkText.setText("[A]");
|
mOkText.setText("[A]");
|
||||||
|
|
||||||
mText.setPosition(0, (Renderer::getScreenHeight() - mText.getSize().y() - mOkText.getSize().y()) / 2);
|
mText.setPosition(Renderer::getScreenWidth() * MSG_PADDING, (Renderer::getScreenHeight() - mText.getSize().y() - mOkText.getSize().y()) / 2);
|
||||||
mOkText.setPosition(0, mText.getPosition().y() + mText.getSize().y());
|
mOkText.setPosition(Renderer::getScreenWidth() * MSG_PADDING, mText.getPosition().y() + mText.getSize().y());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiMsgBoxOk::input(InputConfig* config, Input input)
|
bool GuiMsgBoxOk::input(InputConfig* config, Input input)
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "TextComponent.h"
|
#include "TextComponent.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
//A simple popup message box with callbacks for when the user dismisses it.
|
||||||
|
//Make sure you remember to push it onto the window!
|
||||||
class GuiMsgBoxOk : public GuiComponent
|
class GuiMsgBoxOk : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
59
src/components/GuiMsgBoxYesNo.cpp
Normal file
59
src/components/GuiMsgBoxYesNo.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include "GuiMsgBoxYesNo.h"
|
||||||
|
#include "../Renderer.h"
|
||||||
|
|
||||||
|
#define MSG_WIDTH 0.8f
|
||||||
|
#define MSG_PADDING ((1 - MSG_WIDTH) / 2)
|
||||||
|
|
||||||
|
GuiMsgBoxYesNo::GuiMsgBoxYesNo(Window* window, const std::string& text, std::function<void()> yesCallback, std::function<void()> noCallback) : GuiComponent(window),
|
||||||
|
mYesCallback(yesCallback),
|
||||||
|
mNoCallback(noCallback),
|
||||||
|
mText(window),
|
||||||
|
mInputText(window)
|
||||||
|
{
|
||||||
|
mText.setCentered(true);
|
||||||
|
mText.setColor(0x00BB00FF);
|
||||||
|
mText.setSize(Renderer::getScreenWidth() * MSG_WIDTH, 0);
|
||||||
|
mText.setText(text);
|
||||||
|
|
||||||
|
mInputText.setCentered(true);
|
||||||
|
mInputText.setColor(0x0044BBFF);
|
||||||
|
mInputText.setFont(Font::get(FONT_SIZE_SMALL));
|
||||||
|
mInputText.setSize(Renderer::getScreenWidth() * MSG_WIDTH, 0);
|
||||||
|
mInputText.setText("[A - yes] [B - no]");
|
||||||
|
|
||||||
|
mText.setPosition(Renderer::getScreenWidth() * MSG_PADDING, (Renderer::getScreenHeight() - mText.getSize().y() - mInputText.getSize().y()) / 2);
|
||||||
|
mInputText.setPosition(Renderer::getScreenWidth() * MSG_PADDING, mText.getPosition().y() + mText.getSize().y());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GuiMsgBoxYesNo::input(InputConfig* config, Input input)
|
||||||
|
{
|
||||||
|
if(input.value != 0)
|
||||||
|
{
|
||||||
|
if(config->isMappedTo("a", input))
|
||||||
|
{
|
||||||
|
if(mYesCallback)
|
||||||
|
mYesCallback();
|
||||||
|
|
||||||
|
delete this;
|
||||||
|
return true;
|
||||||
|
}else if(config->isMappedTo("b", input))
|
||||||
|
{
|
||||||
|
if(mNoCallback)
|
||||||
|
mNoCallback();
|
||||||
|
|
||||||
|
delete this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiMsgBoxYesNo::render(const Eigen::Affine3f& parentTrans)
|
||||||
|
{
|
||||||
|
float height = mText.getSize().y() + mInputText.getSize().y();
|
||||||
|
Renderer::setMatrix(parentTrans);
|
||||||
|
Renderer::drawRect(0, (int)((Renderer::getScreenHeight() - height) / 2), Renderer::getScreenWidth(), (int)height, 0x111111FF);
|
||||||
|
mText.render(parentTrans);
|
||||||
|
mInputText.render(parentTrans);
|
||||||
|
}
|
22
src/components/GuiMsgBoxYesNo.h
Normal file
22
src/components/GuiMsgBoxYesNo.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../GuiComponent.h"
|
||||||
|
#include "TextComponent.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
//A simple "yes or no" popup box with callbacks for yes or no.
|
||||||
|
//Make sure you remember to push it onto the window!
|
||||||
|
class GuiMsgBoxYesNo : public GuiComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GuiMsgBoxYesNo(Window* window, const std::string& msg, std::function<void()> yesCallback = nullptr, std::function<void()> noCallback = nullptr);
|
||||||
|
|
||||||
|
bool input(InputConfig* config, Input input) override;
|
||||||
|
void render(const Eigen::Affine3f& parentTrans) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::function<void()> mYesCallback, mNoCallback;
|
||||||
|
|
||||||
|
TextComponent mText;
|
||||||
|
TextComponent mInputText;
|
||||||
|
};
|
|
@ -7,6 +7,8 @@
|
||||||
#include <boost/circular_buffer.hpp>
|
#include <boost/circular_buffer.hpp>
|
||||||
#include "TextComponent.h"
|
#include "TextComponent.h"
|
||||||
|
|
||||||
|
//A "terminal" of sorts for scraping.
|
||||||
|
//Doesn't accept input, but renders log-style messages and handles the callback chain for multi-game scraping.
|
||||||
class GuiScraperLog : public GuiComponent
|
class GuiScraperLog : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "GuiScraperStart.h"
|
#include "GuiScraperStart.h"
|
||||||
#include "GuiScraperLog.h"
|
#include "GuiScraperLog.h"
|
||||||
|
#include "GuiMsgBoxYesNo.h"
|
||||||
|
|
||||||
GuiScraperStart::GuiScraperStart(Window* window) : GuiComponent(window),
|
GuiScraperStart::GuiScraperStart(Window* window) : GuiComponent(window),
|
||||||
mBox(window, ":/frame.png"),
|
mBox(window, ":/frame.png"),
|
||||||
|
@ -44,7 +45,7 @@ GuiScraperStart::GuiScraperStart(Window* window) : GuiComponent(window),
|
||||||
mList.setEntry(Vector2i(1, 2), Vector2i(1, 1), &mManualSwitch, true, ComponentListComponent::AlignLeft);
|
mList.setEntry(Vector2i(1, 2), Vector2i(1, 1), &mManualSwitch, true, ComponentListComponent::AlignLeft);
|
||||||
|
|
||||||
mStartButton.setText("GO GO GO GO", 0x00FF00FF);
|
mStartButton.setText("GO GO GO GO", 0x00FF00FF);
|
||||||
mStartButton.setPressedFunc(std::bind(&GuiScraperStart::start, this));
|
mStartButton.setPressedFunc(std::bind(&GuiScraperStart::pressedStart, this));
|
||||||
mList.setEntry(Vector2i(0, 3), Vector2i(2, 1), &mStartButton, true, ComponentListComponent::AlignCenter);
|
mList.setEntry(Vector2i(0, 3), Vector2i(2, 1), &mStartButton, true, ComponentListComponent::AlignCenter);
|
||||||
|
|
||||||
mList.setPosition(Renderer::getScreenWidth() / 2 - mList.getSize().x() / 2, Renderer::getScreenHeight() / 2 - mList.getSize().y() / 2);
|
mList.setPosition(Renderer::getScreenWidth() / 2 - mList.getSize().x() / 2, Renderer::getScreenHeight() / 2 - mList.getSize().y() / 2);
|
||||||
|
@ -53,6 +54,22 @@ GuiScraperStart::GuiScraperStart(Window* window) : GuiComponent(window),
|
||||||
mBox.fitTo(mList.getSize(), mList.getPosition(), Eigen::Vector2f(8, 8));
|
mBox.fitTo(mList.getSize(), mList.getPosition(), Eigen::Vector2f(8, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiScraperStart::pressedStart()
|
||||||
|
{
|
||||||
|
std::vector<SystemData*> sys = mSystemsOpt.getSelectedObjects();
|
||||||
|
for(auto it = sys.begin(); it != sys.end(); it++)
|
||||||
|
{
|
||||||
|
if((*it)->getPlatformId() == PlatformIds::PLATFORM_UNKNOWN)
|
||||||
|
{
|
||||||
|
mWindow->pushGui(new GuiMsgBoxYesNo(mWindow, "Warning: some of your selected systems do not have a platform ID set. Results may be even more inaccurate than usual!\nContinue anyway?",
|
||||||
|
std::bind(&GuiScraperStart::start, this)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
void GuiScraperStart::start()
|
void GuiScraperStart::start()
|
||||||
{
|
{
|
||||||
std::queue<ScraperSearchParams> searches = getSearches(mSystemsOpt.getSelectedObjects(), mFiltersOpt.getSelectedObjects()[0]);
|
std::queue<ScraperSearchParams> searches = getSearches(mSystemsOpt.getSelectedObjects(), mFiltersOpt.getSelectedObjects()[0]);
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
|
|
||||||
typedef std::function<bool(SystemData*, GameData*)> GameFilterFunc;
|
typedef std::function<bool(SystemData*, GameData*)> GameFilterFunc;
|
||||||
|
|
||||||
|
//The starting point for a multi-game scrape.
|
||||||
|
//Allows the user to set various parameters (to set filters, to set which systems to scrape, to enable manual mode).
|
||||||
|
//Generates a list of "searches" that will be carried out by GuiScraperLog.
|
||||||
class GuiScraperStart : public GuiComponent
|
class GuiScraperStart : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -20,6 +23,7 @@ public:
|
||||||
bool input(InputConfig* config, Input input) override;
|
bool input(InputConfig* config, Input input) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void pressedStart();
|
||||||
void start();
|
void start();
|
||||||
std::queue<ScraperSearchParams> getSearches(std::vector<SystemData*> systems, GameFilterFunc selector);
|
std::queue<ScraperSearchParams> getSearches(std::vector<SystemData*> systems, GameFilterFunc selector);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,12 @@ RatingComponent::RatingComponent(Window* window) : GuiComponent(window)
|
||||||
|
|
||||||
void RatingComponent::setValue(const std::string& value)
|
void RatingComponent::setValue(const std::string& value)
|
||||||
{
|
{
|
||||||
|
if(value.empty())
|
||||||
|
{
|
||||||
|
mValue = 0.0f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mValue = stof(value);
|
mValue = stof(value);
|
||||||
if(mValue > 1.0f)
|
if(mValue > 1.0f)
|
||||||
mValue = 1.0f;
|
mValue = 1.0f;
|
||||||
|
|
|
@ -106,6 +106,14 @@ std::vector<MetaDataList> GamesDBScraper::parseReq(ScraperSearchParams params, s
|
||||||
boost::posix_time::ptime rd = string_to_ptime(game.child("ReleaseDate").text().get(), "%m/%d/%Y");
|
boost::posix_time::ptime rd = string_to_ptime(game.child("ReleaseDate").text().get(), "%m/%d/%Y");
|
||||||
mdl.back().setTime("releasedate", rd);
|
mdl.back().setTime("releasedate", rd);
|
||||||
|
|
||||||
|
if(Settings::getInstance()->getBool("ScrapeRatings") && game.child("Rating"))
|
||||||
|
{
|
||||||
|
float ratingVal = (game.child("Rating").text().as_int() / 10.0f);
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << ratingVal;
|
||||||
|
mdl.back().set("rating", ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
pugi::xml_node images = game.child("Images");
|
pugi::xml_node images = game.child("Images");
|
||||||
|
|
||||||
if(images)
|
if(images)
|
||||||
|
|
|
@ -47,7 +47,9 @@ std::vector<MetaDataList> TheArchiveScraper::parseReq(ScraperSearchParams params
|
||||||
mdl.push_back(MetaDataList(params.system->getGameMDD()));
|
mdl.push_back(MetaDataList(params.system->getGameMDD()));
|
||||||
mdl.back().set("name", game.child("title").text().get());
|
mdl.back().set("name", game.child("title").text().get());
|
||||||
mdl.back().set("desc", game.child("description").text().get());
|
mdl.back().set("desc", game.child("description").text().get());
|
||||||
|
|
||||||
|
//Archive.search does not return ratings
|
||||||
|
|
||||||
pugi::xml_node image = game.child("box_front");
|
pugi::xml_node image = game.child("box_front");
|
||||||
pugi::xml_node thumbnail = game.child("box_front_small");
|
pugi::xml_node thumbnail = game.child("box_front_small");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue