diff --git a/es-app/src/views/GamelistBase.cpp b/es-app/src/views/GamelistBase.cpp index d03e4bf99..5fd0dfbb4 100644 --- a/es-app/src/views/GamelistBase.cpp +++ b/es-app/src/views/GamelistBase.cpp @@ -698,6 +698,8 @@ void GamelistBase::populateList(const std::vector& files, FileData* f mTextList->addEntry(textListEntry); } } + if (mGrid != nullptr) + mGrid->calculateLayout(); } else { addPlaceholder(firstEntry); diff --git a/es-app/src/views/SystemView.cpp b/es-app/src/views/SystemView.cpp index 8973ac7a9..78797261d 100644 --- a/es-app/src/views/SystemView.cpp +++ b/es-app/src/views/SystemView.cpp @@ -727,6 +727,9 @@ void SystemView::populate() } } + if (mGrid != nullptr) + mGrid->calculateLayout(); + for (auto& elements : mSystemElements) { for (auto& text : elements.textComponents) { if (text->getThemeSystemdata() != "") { diff --git a/es-core/src/components/IList.h b/es-core/src/components/IList.h index 888a66042..d49213470 100644 --- a/es-core/src/components/IList.h +++ b/es-core/src/components/IList.h @@ -119,6 +119,7 @@ public: { mEntries.clear(); mCursor = 0; + mLastCursor = 0; listInput(0); onCursorChanged(CursorState::CURSOR_STOPPED); } diff --git a/es-core/src/components/primary/CarouselComponent.h b/es-core/src/components/primary/CarouselComponent.h index 3515a99d5..64238ce68 100644 --- a/es-core/src/components/primary/CarouselComponent.h +++ b/es-core/src/components/primary/CarouselComponent.h @@ -349,7 +349,7 @@ void CarouselComponent::updateEntry(Entry& entry, const std::shared_ptr void CarouselComponent::onDemandTextureLoad() { if constexpr (std::is_same_v) { - const int numEntries {static_cast(mEntries.size())}; + const int numEntries {size()}; const int center {getCursor()}; const bool isWheel {mType == CarouselType::VERTICAL_WHEEL || mType == CarouselType::HORIZONTAL_WHEEL}; diff --git a/es-core/src/components/primary/GridComponent.h b/es-core/src/components/primary/GridComponent.h index 0901634b1..95d67ae17 100644 --- a/es-core/src/components/primary/GridComponent.h +++ b/es-core/src/components/primary/GridComponent.h @@ -38,6 +38,7 @@ public: void addEntry(Entry& entry, const std::shared_ptr& theme); void updateEntry(Entry& entry, const std::shared_ptr& theme); void onDemandTextureLoad() override; + void calculateLayout(); void setCancelTransitionsCallback(const std::function& func) override { @@ -69,8 +70,6 @@ public: unsigned int properties) override; private: - void calculateLayout(); - void onCursorChanged(const CursorState& state) override; bool isScrolling() const override { return List::isScrolling(); } void stopScrolling() override { List::stopScrolling(); } @@ -98,7 +97,7 @@ private: int mRowCount; std::shared_ptr mFont; - unsigned int mColumns; + int mColumns; glm::vec2 mItemSize; float mItemScale; glm::vec2 mItemSpacing; @@ -119,6 +118,7 @@ private: bool mLayoutValid; bool mRowJump; bool mWasScrolling; + bool mJustCalculatedLayout; }; template @@ -153,6 +153,7 @@ GridComponent::GridComponent() , mLayoutValid {false} , mRowJump {false} , mWasScrolling {false} + , mJustCalculatedLayout {false} { } @@ -212,6 +213,7 @@ template void GridComponent::updateEntry(Entry& entry, const std::shared_ptr& theme) { if (entry.data.itemPath != "") { + const glm::vec3& calculatedItemPos {entry.data.item->getPosition()}; auto item = std::make_shared(false, true); item->setLinearInterpolation(true); item->setMipmapping(true); @@ -221,6 +223,7 @@ void GridComponent::updateEntry(Entry& entry, const std::shared_ptrsetOrigin(0.5f, 0.5f); item->setRotateByTargetSize(true); entry.data.item = item; + entry.data.item->setPosition(calculatedItemPos); } else { return; @@ -230,10 +233,22 @@ void GridComponent::updateEntry(Entry& entry, const std::shared_ptr void GridComponent::onDemandTextureLoad() { if constexpr (std::is_same_v) { - const int numEntries {static_cast(mEntries.size())}; + const int visibleRows {static_cast(std::ceil(mVisibleRows))}; + const int columnPos {mCursor % mColumns}; + const int loadItems {mColumns * visibleRows}; + const int numEntries {size()}; + int startPos {mCursor}; + int loadedItems {0}; - // TODO: Currently loads every item every time. - for (int i {0}; i < size(); ++i) { + if (mCursor / mColumns <= visibleRows - 1) + startPos = 0; + else + startPos = mCursor - (mColumns * (mVisibleRows - 1)) - 1 - columnPos; + + for (int i {startPos}; i < size(); ++i) { + if (loadedItems == loadItems) + break; + ++loadedItems; int cursor {i}; while (cursor < 0) @@ -274,6 +289,37 @@ template void GridComponent::onDemandTextureLoad() } } +template void GridComponent::calculateLayout() +{ + assert(!mEntries.empty()); + + int columnCount {0}; + mRowCount = 0; + + for (auto& entry : mEntries) { + entry.data.item->setPosition( + glm::vec3 {mHorizontalMargin + (mItemSize.x * columnCount) + (mItemSize.x * 0.5f) + + mItemSpacing.x * columnCount, + mVerticalMargin + (mItemSize.y * mRowCount) + (mItemSize.y * 0.5f) + + mItemSpacing.y * mRowCount, + 0.0f}); + if (columnCount == mColumns - 1) { + ++mRowCount; + columnCount = 0; + continue; + } + + ++columnCount; + } + + mVisibleRows = mSize.y / (mItemSize.y + mItemSpacing.y); + mVisibleRows -= (mVerticalMargin / mSize.y) * mVisibleRows * 2.0f; + mVisibleRows += (mItemSpacing.y / mSize.y) * mVisibleRows; + + mLayoutValid = true; + mJustCalculatedLayout = true; +} + template bool GridComponent::input(InputConfig* config, Input input) { if (size() > 0) { @@ -293,7 +339,7 @@ template bool GridComponent::input(InputConfig* config, Input in return true; } if (config->isMappedLike("up", input)) { - if (static_cast(mCursor) < mColumns) + if (mCursor < mColumns) return true; if (mCancelTransitionsCallback) mCancelTransitionsCallback(); @@ -302,8 +348,9 @@ template bool GridComponent::input(InputConfig* config, Input in return true; } if (config->isMappedLike("down", input)) { - if (static_cast(mCursor) >= (mColumns * mRowCount) - mColumns && - mEntries.size() - mCursor <= mColumns && mEntries.size() % mColumns == 0) + if (mCursor >= (mColumns * mRowCount) - mColumns && + static_cast(mEntries.size()) - mCursor <= mColumns && + mEntries.size() % mColumns == 0) return true; if (mCancelTransitionsCallback) mCancelTransitionsCallback(); @@ -350,9 +397,6 @@ template bool GridComponent::input(InputConfig* config, Input in template void GridComponent::update(int deltaTime) { - if (!mLayoutValid) - calculateLayout(); - List::listUpdate(deltaTime); GuiComponent::update(deltaTime); } @@ -528,8 +572,10 @@ template void GridComponent::onCursorChanged(const CursorState& return; } - if (mCursor == mLastCursor) + if (mCursor == mLastCursor && !mJustCalculatedLayout) return; + else + mJustCalculatedLayout = false; float startPos {mEntryOffset}; float posMax {static_cast(mEntries.size())}; @@ -635,34 +681,4 @@ template void GridComponent::onCursorChanged(const CursorState& mWasScrolling = (state == CursorState::CURSOR_SCROLLING); } -template void GridComponent::calculateLayout() -{ - assert(!mEntries.empty()); - - unsigned int columnCount {0}; - mRowCount = 0; - - for (auto& entry : mEntries) { - entry.data.item->setPosition( - glm::vec3 {mHorizontalMargin + (mItemSize.x * columnCount) + (mItemSize.x * 0.5f) + - mItemSpacing.x * columnCount, - mVerticalMargin + (mItemSize.y * mRowCount) + (mItemSize.y * 0.5f) + - mItemSpacing.y * mRowCount, - 0.0f}); - if (columnCount == mColumns - 1) { - ++mRowCount; - columnCount = 0; - continue; - } - - ++columnCount; - } - - mVisibleRows = mSize.y / (mItemSize.y + mItemSpacing.y); - mVisibleRows -= (mVerticalMargin / mSize.y) * mVisibleRows * 2.0f; - mVisibleRows += (mItemSpacing.y / mSize.y) * mVisibleRows; - - mLayoutValid = true; -} - #endif // ES_CORE_COMPONENTS_PRIMARY_GRID_COMPONENT_H