mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-28 17:15:38 +00:00
Added horizontal scrolling of long game names to the scraper GUI.
This commit is contained in:
parent
ccc3cae46b
commit
484606fb6f
|
@ -327,6 +327,7 @@ void GuiScraperSearch::search(const ScraperSearchParams& params)
|
||||||
mScrapeResult = {};
|
mScrapeResult = {};
|
||||||
|
|
||||||
mResultList->clear();
|
mResultList->clear();
|
||||||
|
mResultList->setLoopRows(false);
|
||||||
mScraperResults.clear();
|
mScraperResults.clear();
|
||||||
mMDRetrieveURLsHandle.reset();
|
mMDRetrieveURLsHandle.reset();
|
||||||
mThumbnailReqMap.clear();
|
mThumbnailReqMap.clear();
|
||||||
|
@ -355,6 +356,7 @@ void GuiScraperSearch::onSearchDone(const std::vector<ScraperSearchResult>& resu
|
||||||
mResultList->clear();
|
mResultList->clear();
|
||||||
|
|
||||||
mScraperResults = results;
|
mScraperResults = results;
|
||||||
|
mResultList->setLoopRows(true);
|
||||||
|
|
||||||
auto font = Font::get(FONT_SIZE_MEDIUM);
|
auto font = Font::get(FONT_SIZE_MEDIUM);
|
||||||
unsigned int color = 0x777777FF;
|
unsigned int color = 0x777777FF;
|
||||||
|
@ -389,7 +391,7 @@ void GuiScraperSearch::onSearchDone(const std::vector<ScraperSearchResult>& resu
|
||||||
row.addElement(
|
row.addElement(
|
||||||
std::make_shared<TextComponent>(
|
std::make_shared<TextComponent>(
|
||||||
mWindow, Utils::String::toUpper(results.at(i).mdl.get("name")), font, color),
|
mWindow, Utils::String::toUpper(results.at(i).mdl.get("name")), font, color),
|
||||||
true);
|
false);
|
||||||
row.makeAcceptInputHandler([this, i] { returnResult(mScraperResults.at(i)); });
|
row.makeAcceptInputHandler([this, i] { returnResult(mScraperResults.at(i)); });
|
||||||
mResultList->addRow(row);
|
mResultList->addRow(row);
|
||||||
}
|
}
|
||||||
|
@ -562,8 +564,10 @@ bool GuiScraperSearch::input(InputConfig* config, Input input)
|
||||||
else if (mSearchType == ACCEPT_SINGLE_MATCHES && !mFoundGame)
|
else if (mSearchType == ACCEPT_SINGLE_MATCHES && !mFoundGame)
|
||||||
allowRefine = true;
|
allowRefine = true;
|
||||||
|
|
||||||
if (allowRefine)
|
if (allowRefine) {
|
||||||
|
mResultList->stopLooping();
|
||||||
openInputScreen(mLastSearch);
|
openInputScreen(mLastSearch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If multi-scraping, skip game unless the result has already been accepted.
|
// If multi-scraping, skip game unless the result has already been accepted.
|
||||||
|
@ -589,6 +593,7 @@ void GuiScraperSearch::render(const glm::mat4& parentTrans)
|
||||||
|
|
||||||
void GuiScraperSearch::returnResult(ScraperSearchResult result)
|
void GuiScraperSearch::returnResult(ScraperSearchResult result)
|
||||||
{
|
{
|
||||||
|
mResultList->setLoopRows(false);
|
||||||
|
|
||||||
mBlockAccept = true;
|
mBlockAccept = true;
|
||||||
mAcceptedResult = true;
|
mAcceptedResult = true;
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include "components/ComponentList.h"
|
#include "components/ComponentList.h"
|
||||||
|
|
||||||
|
#include "resources/Font.h"
|
||||||
|
|
||||||
#define TOTAL_HORIZONTAL_PADDING_PX 20.0f
|
#define TOTAL_HORIZONTAL_PADDING_PX 20.0f
|
||||||
|
|
||||||
ComponentList::ComponentList(Window* window)
|
ComponentList::ComponentList(Window* window)
|
||||||
|
@ -18,6 +20,11 @@ ComponentList::ComponentList(Window* window)
|
||||||
, mSingleRowScroll{false}
|
, mSingleRowScroll{false}
|
||||||
, mSelectorBarOffset{0.0f}
|
, mSelectorBarOffset{0.0f}
|
||||||
, mCameraOffset{0.0f}
|
, mCameraOffset{0.0f}
|
||||||
|
, mLoopRows{false}
|
||||||
|
, mLoopScroll{false}
|
||||||
|
, mLoopOffset{0}
|
||||||
|
, mLoopOffset2{0}
|
||||||
|
, mLoopTime{0}
|
||||||
, mScrollIndicatorStatus{SCROLL_NONE}
|
, mScrollIndicatorStatus{SCROLL_NONE}
|
||||||
{
|
{
|
||||||
// Adjust the padding relative to the aspect ratio and screen resolution to make it look
|
// Adjust the padding relative to the aspect ratio and screen resolution to make it look
|
||||||
|
@ -120,6 +127,12 @@ bool ComponentList::input(InputConfig* config, Input input)
|
||||||
|
|
||||||
void ComponentList::update(int deltaTime)
|
void ComponentList::update(int deltaTime)
|
||||||
{
|
{
|
||||||
|
if (!mFocused && mLoopRows) {
|
||||||
|
mLoopOffset = 0;
|
||||||
|
mLoopOffset2 = 0;
|
||||||
|
mLoopTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
const float totalHeight = getTotalRowHeight();
|
const float totalHeight = getTotalRowHeight();
|
||||||
|
|
||||||
// Scroll indicator logic, used by ScrollIndicatorComponent.
|
// Scroll indicator logic, used by ScrollIndicatorComponent.
|
||||||
|
@ -152,10 +165,39 @@ void ComponentList::update(int deltaTime)
|
||||||
listUpdate(deltaTime);
|
listUpdate(deltaTime);
|
||||||
|
|
||||||
if (size()) {
|
if (size()) {
|
||||||
|
float rowWidth{0.0f};
|
||||||
|
|
||||||
// Update our currently selected row.
|
// Update our currently selected row.
|
||||||
for (auto it = mEntries.at(mCursor).data.elements.cbegin();
|
for (auto it = mEntries.at(mCursor).data.elements.cbegin();
|
||||||
it != mEntries.at(mCursor).data.elements.cend(); it++)
|
it != mEntries.at(mCursor).data.elements.cend(); it++) {
|
||||||
it->component->update(deltaTime);
|
it->component->update(deltaTime);
|
||||||
|
rowWidth += it->component->getSize().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mLoopRows && rowWidth + mHorizontalPadding / 2.0f > mSize.x) {
|
||||||
|
// Loop the text.
|
||||||
|
const float speed{
|
||||||
|
Font::get(FONT_SIZE_MEDIUM)->sizeText("ABCDEFGHIJKLMNOPQRSTUVWXYZ").x * 0.247f};
|
||||||
|
const float delay{1300.0f};
|
||||||
|
const float scrollLength{rowWidth};
|
||||||
|
const float returnLength{speed * 1.5f};
|
||||||
|
const float scrollTime{(scrollLength * 1000.0f) / speed};
|
||||||
|
const float returnTime{(returnLength * 1000.0f) / speed};
|
||||||
|
const int maxTime{static_cast<int>(delay + scrollTime + returnTime)};
|
||||||
|
|
||||||
|
mLoopTime += deltaTime;
|
||||||
|
while (mLoopTime > maxTime)
|
||||||
|
mLoopTime -= maxTime;
|
||||||
|
|
||||||
|
mLoopOffset = static_cast<int>(Utils::Math::loop(delay, scrollTime + returnTime,
|
||||||
|
static_cast<float>(mLoopTime),
|
||||||
|
scrollLength + returnLength));
|
||||||
|
|
||||||
|
if (mLoopOffset > (scrollLength - (mSize.x - returnLength)))
|
||||||
|
mLoopOffset2 = static_cast<int>(mLoopOffset - (scrollLength + returnLength));
|
||||||
|
else if (mLoopOffset2 < 0)
|
||||||
|
mLoopOffset2 = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,6 +205,12 @@ void ComponentList::onCursorChanged(const CursorState& state)
|
||||||
{
|
{
|
||||||
mSetupCompleted = true;
|
mSetupCompleted = true;
|
||||||
|
|
||||||
|
if (mLoopRows) {
|
||||||
|
mLoopOffset = 0;
|
||||||
|
mLoopOffset2 = 0;
|
||||||
|
mLoopTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Update the selector bar position.
|
// Update the selector bar position.
|
||||||
// In the future this might be animated.
|
// In the future this might be animated.
|
||||||
mSelectorBarOffset = 0;
|
mSelectorBarOffset = 0;
|
||||||
|
@ -233,22 +281,47 @@ void ComponentList::render(const glm::mat4& parentTrans)
|
||||||
dim.x = (trans[0].x * dim.x + trans[3].x) - trans[3].x;
|
dim.x = (trans[0].x * dim.x + trans[3].x) - trans[3].x;
|
||||||
dim.y = (trans[1].y * dim.y + trans[3].y) - trans[3].y;
|
dim.y = (trans[1].y * dim.y + trans[3].y) - trans[3].y;
|
||||||
|
|
||||||
Renderer::pushClipRect(
|
const int clipRectPosX{static_cast<int>(std::round(trans[3].x))};
|
||||||
glm::ivec2{static_cast<int>(std::round(trans[3].x)),
|
const int clipRectPosY{static_cast<int>(std::round(trans[3].y))};
|
||||||
static_cast<int>(std::round(trans[3].y))},
|
const int clipRectSizeX{static_cast<int>(std::round(dim.x))};
|
||||||
glm::ivec2{static_cast<int>(std::round(dim.x)), static_cast<int>(std::round(dim.y))});
|
const int clipRectSizeY{static_cast<int>(std::round(dim.y))};
|
||||||
|
|
||||||
|
Renderer::pushClipRect(glm::ivec2{clipRectPosX, clipRectPosY},
|
||||||
|
glm::ivec2{clipRectSizeX, clipRectSizeY});
|
||||||
|
|
||||||
// Scroll the camera.
|
// Scroll the camera.
|
||||||
trans = glm::translate(trans, glm::vec3{0.0f, -mCameraOffset, 0.0f});
|
trans = glm::translate(trans, glm::vec3{0.0f, -mCameraOffset, 0.0f});
|
||||||
|
|
||||||
|
glm::mat4 loopTrans{trans};
|
||||||
|
|
||||||
// Draw our entries.
|
// Draw our entries.
|
||||||
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++) {
|
||||||
|
|
||||||
|
if (mLoopRows && mFocused && mLoopOffset > 0) {
|
||||||
|
loopTrans =
|
||||||
|
glm::translate(trans, glm::vec3{static_cast<float>(-mLoopOffset), 0.0f, 0.0f});
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
auto renderLoopFunc = [&]() {
|
||||||
|
// Needed to avoid flickering when returning to the start position.
|
||||||
|
if (mLoopOffset == 0 && mLoopOffset2 == 0)
|
||||||
|
mLoopScroll = false;
|
||||||
|
it->component->render(loopTrans);
|
||||||
|
// Render row again if text is moved far enough for it to repeat.
|
||||||
|
if (mLoopOffset2 < 0 || mLoopScroll) {
|
||||||
|
mLoopScroll = true;
|
||||||
|
loopTrans = glm::translate(
|
||||||
|
trans, glm::vec3{static_cast<float>(-mLoopOffset2), 0.0f, 0.0f});
|
||||||
|
it->component->render(loopTrans);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// For the row where the cursor is at, we want to remove any hue from the
|
// For the row where the cursor is at, we want to remove any hue from the
|
||||||
// font or image before inverting, as it would otherwise lead to an ugly
|
// font or image before inverting, as it would otherwise lead to an ugly
|
||||||
// inverted color (e.g. red inverting to a green hue).
|
// inverted color (e.g. red inverting to a green hue).
|
||||||
|
@ -267,15 +340,14 @@ void ComponentList::render(const glm::mat4& parentTrans)
|
||||||
unsigned char byteBlue = origColor >> 8 & 0xFF;
|
unsigned char byteBlue = origColor >> 8 & 0xFF;
|
||||||
// If it's neutral, just proceed with normal rendering.
|
// If it's neutral, just proceed with normal rendering.
|
||||||
if (byteRed == byteGreen && byteGreen == byteBlue) {
|
if (byteRed == byteGreen && byteGreen == byteBlue) {
|
||||||
it->component->render(trans);
|
renderLoopFunc();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isTextComponent)
|
if (isTextComponent)
|
||||||
it->component->setColor(DEFAULT_INVERTED_TEXTCOLOR);
|
it->component->setColor(DEFAULT_INVERTED_TEXTCOLOR);
|
||||||
else
|
else
|
||||||
it->component->setColorShift(DEFAULT_INVERTED_IMAGECOLOR);
|
it->component->setColorShift(DEFAULT_INVERTED_IMAGECOLOR);
|
||||||
|
renderLoopFunc();
|
||||||
it->component->render(trans);
|
|
||||||
// Revert to the original color after rendering.
|
// Revert to the original color after rendering.
|
||||||
if (isTextComponent)
|
if (isTextComponent)
|
||||||
it->component->setColor(origColor);
|
it->component->setColor(origColor);
|
||||||
|
|
|
@ -86,6 +86,15 @@ public:
|
||||||
float getTotalRowHeight() const;
|
float getTotalRowHeight() const;
|
||||||
float getRowHeight(int row) const { return getRowHeight(mEntries.at(row).data); }
|
float getRowHeight(int row) const { return getRowHeight(mEntries.at(row).data); }
|
||||||
|
|
||||||
|
// Horizontal looping for row content that doesn't fit on-screen.
|
||||||
|
void setLoopRows(bool state) { mLoopRows = state; }
|
||||||
|
void stopLooping()
|
||||||
|
{
|
||||||
|
mLoopOffset = 0;
|
||||||
|
mLoopOffset2 = 0;
|
||||||
|
mLoopTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void resetScrollIndicatorStatus()
|
void resetScrollIndicatorStatus()
|
||||||
{
|
{
|
||||||
mScrollIndicatorStatus = SCROLL_NONE;
|
mScrollIndicatorStatus = SCROLL_NONE;
|
||||||
|
@ -126,6 +135,12 @@ private:
|
||||||
float mSelectorBarOffset;
|
float mSelectorBarOffset;
|
||||||
float mCameraOffset;
|
float mCameraOffset;
|
||||||
|
|
||||||
|
bool mLoopRows;
|
||||||
|
bool mLoopScroll;
|
||||||
|
int mLoopOffset;
|
||||||
|
int mLoopOffset2;
|
||||||
|
int mLoopTime;
|
||||||
|
|
||||||
std::function<void(CursorState state)> mCursorChangedCallback;
|
std::function<void(CursorState state)> mCursorChangedCallback;
|
||||||
std::function<void(ScrollIndicator state, bool singleRowScroll)>
|
std::function<void(ScrollIndicator state, bool singleRowScroll)>
|
||||||
mScrollIndicatorChangedCallback;
|
mScrollIndicatorChangedCallback;
|
||||||
|
|
Loading…
Reference in a new issue