mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-30 01:55:39 +00:00
Fixed a sneaky crash.
Added metadata display to ScraperSearchComponent.
This commit is contained in:
parent
1e8b040f73
commit
8e5c910de3
|
@ -4,10 +4,13 @@
|
||||||
#include "TextComponent.h"
|
#include "TextComponent.h"
|
||||||
#include "ScrollableContainer.h"
|
#include "ScrollableContainer.h"
|
||||||
#include "ImageComponent.h"
|
#include "ImageComponent.h"
|
||||||
|
#include "RatingComponent.h"
|
||||||
|
#include "DateTimeComponent.h"
|
||||||
#include "ComponentList.h"
|
#include "ComponentList.h"
|
||||||
#include "../HttpReq.h"
|
#include "../HttpReq.h"
|
||||||
#include "../Settings.h"
|
#include "../Settings.h"
|
||||||
#include "../Log.h"
|
#include "../Log.h"
|
||||||
|
#include "../Util.h"
|
||||||
|
|
||||||
ScraperSearchComponent::ScraperSearchComponent(Window* window, SearchType type) : GuiComponent(window),
|
ScraperSearchComponent::ScraperSearchComponent(Window* window, SearchType type) : GuiComponent(window),
|
||||||
mGrid(window, Eigen::Vector2i(4, 3)),
|
mGrid(window, Eigen::Vector2i(4, 3)),
|
||||||
|
@ -36,6 +39,36 @@ ScraperSearchComponent::ScraperSearchComponent(Window* window, SearchType type)
|
||||||
mDescContainer->addChild(mResultDesc.get());
|
mDescContainer->addChild(mResultDesc.get());
|
||||||
mDescContainer->setAutoScroll(2200, 0.015f);
|
mDescContainer->setAutoScroll(2200, 0.015f);
|
||||||
|
|
||||||
|
// metadata
|
||||||
|
auto font = Font::get(FONT_SIZE_SMALL); // this gets replaced in onSizeChanged() so its just a placeholder
|
||||||
|
const unsigned int mdColor = 0x777777FF;
|
||||||
|
const unsigned int mdLblColor = 0x666666FF;
|
||||||
|
mMD_Rating = std::make_shared<RatingComponent>(mWindow);
|
||||||
|
mMD_ReleaseDate = std::make_shared<DateTimeComponent>(mWindow);
|
||||||
|
mMD_ReleaseDate->setColor(mdColor);
|
||||||
|
mMD_Developer = std::make_shared<TextComponent>(mWindow, "", font, mdColor);
|
||||||
|
mMD_Publisher = std::make_shared<TextComponent>(mWindow, "", font, mdColor);
|
||||||
|
mMD_Genre = std::make_shared<TextComponent>(mWindow, "", font, mdColor);
|
||||||
|
mMD_Players = std::make_shared<TextComponent>(mWindow, "", font, mdColor);
|
||||||
|
|
||||||
|
mMD_Pairs.push_back(MetaDataPair(std::make_shared<TextComponent>(mWindow, "RATING:", font, mdLblColor), mMD_Rating));
|
||||||
|
mMD_Pairs.push_back(MetaDataPair(std::make_shared<TextComponent>(mWindow, "RELEASED:", font, mdLblColor), mMD_ReleaseDate));
|
||||||
|
mMD_Pairs.push_back(MetaDataPair(std::make_shared<TextComponent>(mWindow, "DEVELOPER:", font, mdLblColor), mMD_Developer));
|
||||||
|
mMD_Pairs.push_back(MetaDataPair(std::make_shared<TextComponent>(mWindow, "PUBLISHER:", font, mdLblColor), mMD_Publisher));
|
||||||
|
mMD_Pairs.push_back(MetaDataPair(std::make_shared<TextComponent>(mWindow, "GENRE:", font, mdLblColor), mMD_Genre));
|
||||||
|
mMD_Pairs.push_back(MetaDataPair(std::make_shared<TextComponent>(mWindow, "PLAYERS:", font, mdLblColor), mMD_Players));
|
||||||
|
|
||||||
|
mMD_Grid = std::make_shared<ComponentGrid>(mWindow, Vector2i(2, mMD_Pairs.size()));
|
||||||
|
unsigned int i = 0;
|
||||||
|
for(auto it = mMD_Pairs.begin(); it != mMD_Pairs.end(); it++)
|
||||||
|
{
|
||||||
|
mMD_Grid->setEntry(it->first, Vector2i(0, i), false, true);
|
||||||
|
mMD_Grid->setEntry(it->second, Vector2i(1, i), false, true);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
mGrid.setEntry(mMD_Grid, Vector2i(2, 1), false, true);
|
||||||
|
|
||||||
// result list
|
// result list
|
||||||
mResultList = std::make_shared<ComponentList>(mWindow);
|
mResultList = std::make_shared<ComponentList>(mWindow);
|
||||||
|
|
||||||
|
@ -57,8 +90,36 @@ void ScraperSearchComponent::onSizeChanged()
|
||||||
mGrid.setRowHeightPerc(0, fontHeightPerc); // result name
|
mGrid.setRowHeightPerc(0, fontHeightPerc); // result name
|
||||||
mGrid.setRowHeightPerc(2, 0.375f); // description
|
mGrid.setRowHeightPerc(2, 0.375f); // description
|
||||||
|
|
||||||
mResultThumbnail->setMaxSize(mGrid.getColWidth(1), mGrid.getRowHeight(1));
|
// limit thumbnail size using setMaxHeight - we do this instead of letting mGrid call setSize because it maintains the aspect ratio
|
||||||
|
// we also pad a little so it doesn't rub up against the metadata labels
|
||||||
|
mResultThumbnail->setMaxSize(mGrid.getColWidth(1) - 16, mGrid.getRowHeight(1));
|
||||||
mResultDesc->setSize(mDescContainer->getSize().x(), 0); // make desc text wrap at edge of container
|
mResultDesc->setSize(mDescContainer->getSize().x(), 0); // make desc text wrap at edge of container
|
||||||
|
|
||||||
|
// metadata
|
||||||
|
// (mMD_Grid has already been resized by mGrid)
|
||||||
|
|
||||||
|
const int fontHeight = (int)(mMD_Grid->getSize().y() / mMD_Pairs.size() * 0.8f);
|
||||||
|
auto fontLbl = Font::get(fontHeight, FONT_PATH_REGULAR);
|
||||||
|
auto fontComp = Font::get(fontHeight, FONT_PATH_LIGHT);
|
||||||
|
|
||||||
|
// update label fonts
|
||||||
|
float maxLblWidth = 0;
|
||||||
|
for(auto it = mMD_Pairs.begin(); it != mMD_Pairs.end(); it++)
|
||||||
|
{
|
||||||
|
it->first->setFont(fontLbl);
|
||||||
|
it->first->setSize(0, 0);
|
||||||
|
if(it->first->getSize().x() > maxLblWidth)
|
||||||
|
maxLblWidth = it->first->getSize().x() + 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update component fonts
|
||||||
|
mMD_ReleaseDate->setFont(fontComp);
|
||||||
|
mMD_Developer->setFont(fontComp);
|
||||||
|
mMD_Publisher->setFont(fontComp);
|
||||||
|
mMD_Genre->setFont(fontComp);
|
||||||
|
mMD_Players->setFont(fontComp);
|
||||||
|
|
||||||
|
mMD_Grid->setColWidthPerc(0, maxLblWidth / mMD_Grid->getSize().x());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScraperSearchComponent::updateViewStyle()
|
void ScraperSearchComponent::updateViewStyle()
|
||||||
|
@ -171,10 +232,27 @@ void ScraperSearchComponent::updateInfoPane()
|
||||||
mThumbnailReq = std::unique_ptr<HttpReq>(new HttpReq(thumb));
|
mThumbnailReq = std::unique_ptr<HttpReq>(new HttpReq(thumb));
|
||||||
else
|
else
|
||||||
mThumbnailReq.reset();
|
mThumbnailReq.reset();
|
||||||
|
|
||||||
|
// metadata
|
||||||
|
mMD_Rating->setValue(strToUpper(mScraperResults.at(i).mdl.get("rating")));
|
||||||
|
mMD_ReleaseDate->setValue(strToUpper(mScraperResults.at(i).mdl.get("releasedate")));
|
||||||
|
mMD_Developer->setText(strToUpper(mScraperResults.at(i).mdl.get("developer")));
|
||||||
|
mMD_Publisher->setText(strToUpper(mScraperResults.at(i).mdl.get("publisher")));
|
||||||
|
mMD_Genre->setText(strToUpper(mScraperResults.at(i).mdl.get("genre")));
|
||||||
|
mMD_Players->setText(strToUpper(mScraperResults.at(i).mdl.get("players")));
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
mResultName->setText("");
|
mResultName->setText("");
|
||||||
mResultDesc->setText("");
|
mResultDesc->setText("");
|
||||||
mResultThumbnail->setImage("");
|
mResultThumbnail->setImage("");
|
||||||
|
|
||||||
|
// metadata
|
||||||
|
mMD_Rating->setValue("");
|
||||||
|
mMD_ReleaseDate->setValue("");
|
||||||
|
mMD_Developer->setText("");
|
||||||
|
mMD_Publisher->setText("");
|
||||||
|
mMD_Genre->setText("");
|
||||||
|
mMD_Players->setText("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,14 +285,14 @@ void ScraperSearchComponent::render(const Eigen::Affine3f& parentTrans)
|
||||||
{
|
{
|
||||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||||
|
|
||||||
|
renderChildren(trans);
|
||||||
|
|
||||||
if(mBlockAccept)
|
if(mBlockAccept)
|
||||||
{
|
{
|
||||||
Renderer::setMatrix(trans);
|
Renderer::setMatrix(trans);
|
||||||
Renderer::drawRect((int)mResultList->getPosition().x(), (int)mResultList->getPosition().y(),
|
Renderer::drawRect((int)mResultList->getPosition().x(), (int)mResultList->getPosition().y(),
|
||||||
(int)mResultList->getSize().x(), (int)mResultList->getSize().y(), 0x00000011);
|
(int)mResultList->getSize().x(), (int)mResultList->getSize().y(), 0x00000011);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderChildren(trans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScraperSearchComponent::returnResult(ScraperSearchResult result)
|
void ScraperSearchComponent::returnResult(ScraperSearchResult result)
|
||||||
|
@ -233,6 +311,8 @@ void ScraperSearchComponent::returnResult(ScraperSearchResult result)
|
||||||
|
|
||||||
void ScraperSearchComponent::update(int deltaTime)
|
void ScraperSearchComponent::update(int deltaTime)
|
||||||
{
|
{
|
||||||
|
GuiComponent::update(deltaTime);
|
||||||
|
|
||||||
if(mThumbnailReq && mThumbnailReq->status() != HttpReq::REQ_IN_PROGRESS)
|
if(mThumbnailReq && mThumbnailReq->status() != HttpReq::REQ_IN_PROGRESS)
|
||||||
{
|
{
|
||||||
updateThumbnail();
|
updateThumbnail();
|
||||||
|
@ -254,15 +334,14 @@ void ScraperSearchComponent::update(int deltaTime)
|
||||||
{
|
{
|
||||||
if(mMDResolveHandle->status() == ASYNC_DONE)
|
if(mMDResolveHandle->status() == ASYNC_DONE)
|
||||||
{
|
{
|
||||||
|
// this might end in us being deleted, depending on mAcceptCallback - so make sure this is the last thing we do in update()
|
||||||
returnResult(mMDResolveHandle->getResult());
|
returnResult(mMDResolveHandle->getResult());
|
||||||
}else if(mMDResolveHandle->status() == ASYNC_ERROR)
|
}else if(mMDResolveHandle->status() == ASYNC_ERROR)
|
||||||
{
|
{
|
||||||
onSearchError(mMDResolveHandle->getStatusString());
|
onSearchError(mMDResolveHandle->getStatusString());
|
||||||
}
|
|
||||||
mMDResolveHandle.reset();
|
mMDResolveHandle.reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
GuiComponent::update(deltaTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScraperSearchComponent::updateThumbnail()
|
void ScraperSearchComponent::updateThumbnail()
|
||||||
|
|
|
@ -8,11 +8,14 @@
|
||||||
#define MAX_SCRAPER_RESULTS 5
|
#define MAX_SCRAPER_RESULTS 5
|
||||||
|
|
||||||
class ComponentList;
|
class ComponentList;
|
||||||
class TextEditComponent;
|
|
||||||
class ImageComponent;
|
class ImageComponent;
|
||||||
|
class RatingComponent;
|
||||||
|
class TextComponent;
|
||||||
|
class DateTimeComponent;
|
||||||
class ScrollableContainer;
|
class ScrollableContainer;
|
||||||
class HttpReq;
|
class HttpReq;
|
||||||
|
|
||||||
|
|
||||||
class ScraperSearchComponent : public GuiComponent
|
class ScraperSearchComponent : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -61,6 +64,18 @@ private:
|
||||||
std::shared_ptr<ImageComponent> mResultThumbnail;
|
std::shared_ptr<ImageComponent> mResultThumbnail;
|
||||||
std::shared_ptr<ComponentList> mResultList;
|
std::shared_ptr<ComponentList> mResultList;
|
||||||
|
|
||||||
|
std::shared_ptr<ComponentGrid> mMD_Grid;
|
||||||
|
std::shared_ptr<RatingComponent> mMD_Rating;
|
||||||
|
std::shared_ptr<DateTimeComponent> mMD_ReleaseDate;
|
||||||
|
std::shared_ptr<TextComponent> mMD_Developer;
|
||||||
|
std::shared_ptr<TextComponent> mMD_Publisher;
|
||||||
|
std::shared_ptr<TextComponent> mMD_Genre;
|
||||||
|
std::shared_ptr<TextComponent> mMD_Players;
|
||||||
|
|
||||||
|
// label-component pair
|
||||||
|
typedef std::pair< std::shared_ptr<TextComponent>, std::shared_ptr<GuiComponent> > MetaDataPair;
|
||||||
|
std::vector<MetaDataPair> mMD_Pairs;
|
||||||
|
|
||||||
SearchType mSearchType;
|
SearchType mSearchType;
|
||||||
ScraperSearchParams mLastSearch;
|
ScraperSearchParams mLastSearch;
|
||||||
std::function<void(const ScraperSearchResult&)> mAcceptCallback;
|
std::function<void(const ScraperSearchResult&)> mAcceptCallback;
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
GuiGameScraper::GuiGameScraper(Window* window, ScraperSearchParams params, std::function<void(const ScraperSearchResult&)> doneFunc) : GuiComponent(window),
|
GuiGameScraper::GuiGameScraper(Window* window, ScraperSearchParams params, std::function<void(const ScraperSearchResult&)> doneFunc) : GuiComponent(window),
|
||||||
mGrid(window, Eigen::Vector2i(1, 3)),
|
mGrid(window, Eigen::Vector2i(1, 3)),
|
||||||
mBox(window, ":/frame.png"),
|
mBox(window, ":/frame.png"),
|
||||||
mSearchParams(params)
|
mSearchParams(params),
|
||||||
|
mClose(false)
|
||||||
{
|
{
|
||||||
addChild(&mBox);
|
addChild(&mBox);
|
||||||
addChild(&mGrid);
|
addChild(&mGrid);
|
||||||
|
@ -45,7 +46,29 @@ GuiGameScraper::GuiGameScraper(Window* window, ScraperSearchParams params, std::
|
||||||
mGrid.setPosition((mSize.x() - mGrid.getSize().x()) / 2, (mSize.y() - mGrid.getSize().y()) / 2);
|
mGrid.setPosition((mSize.x() - mGrid.getSize().x()) / 2, (mSize.y() - mGrid.getSize().y()) / 2);
|
||||||
mBox.fitTo(mGrid.getSize(), mGrid.getPosition(), Eigen::Vector2f(-32, -32));
|
mBox.fitTo(mGrid.getSize(), mGrid.getPosition(), Eigen::Vector2f(-32, -32));
|
||||||
|
|
||||||
mSearch->setAcceptCallback([this, doneFunc](const ScraperSearchResult& result) { doneFunc(result); delete this; });
|
// we call this->close() instead of just delete this; in the accept callback:
|
||||||
|
// this is because of how GuiComponent::update works. if it was just delete this, this would happen when the metadata resolver is done:
|
||||||
|
// GuiGameScraper::update()
|
||||||
|
// GuiComponent::update()
|
||||||
|
// it = mChildren.begin();
|
||||||
|
// mBox::update()
|
||||||
|
// it++;
|
||||||
|
// mSearchComponent::update()
|
||||||
|
// acceptCallback -> delete this
|
||||||
|
// it++; // error, mChildren has been deleted because it was part of this
|
||||||
|
|
||||||
|
// so instead we do this:
|
||||||
|
// GuiGameScraper::update()
|
||||||
|
// GuiComponent::update()
|
||||||
|
// it = mChildren.begin();
|
||||||
|
// mBox::update()
|
||||||
|
// it++;
|
||||||
|
// mSearchComponent::update()
|
||||||
|
// acceptCallback -> close() -> mClose = true
|
||||||
|
// it++; // ok
|
||||||
|
// if(mClose)
|
||||||
|
// delete this;
|
||||||
|
mSearch->setAcceptCallback([this, doneFunc](const ScraperSearchResult& result) { doneFunc(result); close(); });
|
||||||
mSearch->setCancelCallback([&] { delete this; });
|
mSearch->setCancelCallback([&] { delete this; });
|
||||||
|
|
||||||
mGrid.resetCursor();
|
mGrid.resetCursor();
|
||||||
|
@ -63,7 +86,20 @@ bool GuiGameScraper::input(InputConfig* config, Input input)
|
||||||
return GuiComponent::input(config, input);
|
return GuiComponent::input(config, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiGameScraper::update(int deltaTime)
|
||||||
|
{
|
||||||
|
GuiComponent::update(deltaTime);
|
||||||
|
|
||||||
|
if(mClose)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<HelpPrompt> GuiGameScraper::getHelpPrompts()
|
std::vector<HelpPrompt> GuiGameScraper::getHelpPrompts()
|
||||||
{
|
{
|
||||||
return mGrid.getHelpPrompts();
|
return mGrid.getHelpPrompts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiGameScraper::close()
|
||||||
|
{
|
||||||
|
mClose = true;
|
||||||
|
}
|
|
@ -10,10 +10,13 @@ public:
|
||||||
GuiGameScraper(Window* window, ScraperSearchParams params, std::function<void(const ScraperSearchResult&)> doneFunc);
|
GuiGameScraper(Window* window, ScraperSearchParams params, std::function<void(const ScraperSearchResult&)> doneFunc);
|
||||||
|
|
||||||
bool input(InputConfig* config, Input input) override;
|
bool input(InputConfig* config, Input input) override;
|
||||||
|
void update(int deltaTime);
|
||||||
virtual std::vector<HelpPrompt> getHelpPrompts() override;
|
virtual std::vector<HelpPrompt> getHelpPrompts() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool mClose;
|
||||||
|
void close();
|
||||||
|
|
||||||
ComponentGrid mGrid;
|
ComponentGrid mGrid;
|
||||||
NinePatchComponent mBox;
|
NinePatchComponent mBox;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ void MDResolveHandle::update()
|
||||||
setStatus(ASYNC_DONE);
|
setStatus(ASYNC_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<AsyncHandle> downloadImageAsync(const std::string& url, const std::string& saveAs)
|
std::unique_ptr<ImageDownloadHandle> downloadImageAsync(const std::string& url, const std::string& saveAs)
|
||||||
{
|
{
|
||||||
return std::unique_ptr<ImageDownloadHandle>(new ImageDownloadHandle(url, saveAs,
|
return std::unique_ptr<ImageDownloadHandle>(new ImageDownloadHandle(url, saveAs,
|
||||||
Settings::getInstance()->getInt("ScraperResizeWidth"), Settings::getInstance()->getInt("ScraperResizeHeight")));
|
Settings::getInstance()->getInt("ScraperResizeWidth"), Settings::getInstance()->getInt("ScraperResizeHeight")));
|
||||||
|
|
|
@ -84,7 +84,7 @@ private:
|
||||||
std::string getSaveAsPath(const ScraperSearchParams& params, const std::string& suffix, const std::string& url);
|
std::string getSaveAsPath(const ScraperSearchParams& params, const std::string& suffix, const std::string& url);
|
||||||
|
|
||||||
//Will resize according to Settings::getInt("ScraperResizeWidth") and Settings::getInt("ScraperResizeHeight").
|
//Will resize according to Settings::getInt("ScraperResizeWidth") and Settings::getInt("ScraperResizeHeight").
|
||||||
std::unique_ptr<AsyncHandle> downloadImageAsync(const std::string& url, const std::string& saveAs);
|
std::unique_ptr<ImageDownloadHandle> downloadImageAsync(const std::string& url, const std::string& saveAs);
|
||||||
|
|
||||||
// Resolves all metadata assets that need to be downloaded.
|
// Resolves all metadata assets that need to be downloaded.
|
||||||
std::unique_ptr<MDResolveHandle> resolveMetaDataAssets(const ScraperSearchResult& result, const ScraperSearchParams& search);
|
std::unique_ptr<MDResolveHandle> resolveMetaDataAssets(const ScraperSearchResult& result, const ScraperSearchParams& search);
|
||||||
|
|
Loading…
Reference in a new issue