diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index b43d567e6..76e935db1 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -209,7 +209,7 @@ void Window::update(int deltaTime) // vram float textureVramUsageMb = TextureResource::getTotalMemUsage() / 1000.0f / 1000.0f; float textureTotalUsageMb = TextureResource::getTotalTextureSize() / 1000.0f / 1000.0f; - float fontVramUsageMb = Font::getTotalMemUsage() / 1000.0f / 1000.0f;; + float fontVramUsageMb = Font::getTotalMemUsage() / 1000.0f / 1000.0f; ss << "\nFont VRAM: " << fontVramUsageMb << " Tex VRAM: " << textureVramUsageMb << " Tex Max: " << textureTotalUsageMb; diff --git a/es-core/src/components/ImageGridComponent.h b/es-core/src/components/ImageGridComponent.h index d43b16e34..7d8272899 100644 --- a/es-core/src/components/ImageGridComponent.h +++ b/es-core/src/components/ImageGridComponent.h @@ -23,6 +23,7 @@ class ImageGridComponent : public IList { protected: using IList::mEntries; + using IList::mScrollTier; using IList::listUpdate; using IList::listInput; using IList::listRenderTitleOverlay; @@ -47,7 +48,6 @@ public: virtual void applyTheme(const std::shared_ptr& theme, const std::string& view, const std::string& element, unsigned int properties) override; void onSizeChanged() override; - inline void setCursorChangedCallback(const std::function& func) { mCursorChangedCallback = func; } protected: @@ -57,11 +57,15 @@ private: // TILES void buildTiles(); void updateTiles(); + void updateTileAtPos(int tilePos, int imgPos, int bufferTop, int bufferBot); int getStartPosition() const; void calcGridDimension(); // IMAGES & ENTRIES + const int texBuffersBehind[4] = { 1, 1, 1, 1 }; + const int texBuffersForward[4] = { 1, 2, 3, 3 }; bool mEntriesDirty; + int mLastCursor; std::shared_ptr mDefaultGameTexture; std::shared_ptr mDefaultFolderTexture; @@ -84,6 +88,7 @@ ImageGridComponent::ImageGridComponent(Window* window) : IList::render(const Transform4x4f& parentTrans) Renderer::pushClipRect(pos, size); // Render all the tiles but the selected one - std::shared_ptr selectedTile = NULL; for(auto it = mTiles.begin(); it != mTiles.end(); it++) { @@ -198,6 +202,8 @@ void ImageGridComponent::render(const Transform4x4f& parentTrans) if (selectedTile != NULL) selectedTile->render(trans); + listRenderTitleOverlay(trans); + GuiComponent::renderChildren(trans); } @@ -306,8 +312,8 @@ void ImageGridComponent::buildTiles() calcGridDimension(); - Vector2f startPosition = mTileSize / 2; Vector2f tileDistance = mTileSize + mMargin; + Vector2f startPosition = mTileSize / 2 - Vector2f(0, tileDistance.y() * texBuffersForward[3]); int X, Y; @@ -342,26 +348,69 @@ void ImageGridComponent::updateTiles() if (!mTiles.size()) return; - int img = getStartPosition(); - - for(int ti = 0; ti < mTiles.size(); ti++) + // Stop updating the tiles at highest scroll speed + if (mScrollTier == 3) { - std::shared_ptr tile = mTiles.at(ti); - - // If we have more tiles than we have to display images on screen, hide them - if(img >= size()) + for (int ti = 0; ti < mTiles.size(); ti++) { + std::shared_ptr tile = mTiles.at(ti); + tile->setSelected(false); - tile->setImage(""); + tile->setImage(mDefaultGameTexture); tile->setVisible(false); - continue; } + return; + } - tile->setSelected(img == mCursor); - tile->setImage(mEntries.at(img).data.texture); + // 1 if scrolling down, -1 if scrolling up + int scrollDirection = mCursor >= mLastCursor ? 1 : -1; + + // If going down, update from top to bottom + // If going up, update from bottom to top + int ti = scrollDirection == 1 ? 0 : mTiles.size() - 1; + int end = scrollDirection == 1 ? mTiles.size() : -1; + + int img = getStartPosition(); + if (scrollDirection == -1) + img += mTiles.size() - 1; + + // Calculate buffer size depending on scroll speed and direction + int bufferBehind = (texBuffersForward[3] - texBuffersBehind[mScrollTier]) * mGridDimension.x(); + int bufferForward = (texBuffersForward[3] - texBuffersForward[mScrollTier]) * mGridDimension.x(); + + int bufferTop = scrollDirection == 1 ? bufferBehind : bufferForward; + int bufferBot = scrollDirection == 1 ? bufferForward : bufferBehind; + + // Update the tiles + while (ti != end) + { + updateTileAtPos(ti, img, bufferTop, bufferBot); + + ti += scrollDirection; + img += scrollDirection; + } + + mLastCursor = mCursor; +} + +template +void ImageGridComponent::updateTileAtPos(int tilePos, int imgPos, int bufferTop, int bufferBot) +{ + std::shared_ptr tile = mTiles.at(tilePos); + + // If we have more tiles than we have to display images on screen, hide them + if(imgPos < 0 || imgPos >= size() + || tilePos < bufferTop || tilePos >= mTiles.size() - bufferBot) // Same for tiles out of the buffer + { + tile->setSelected(false); + tile->setImage(""); + tile->setVisible(false); + } + else + { + tile->setSelected(imgPos == mCursor); + tile->setImage(mEntries.at(imgPos).data.texture); tile->setVisible(true); - - img++; } } @@ -373,23 +422,28 @@ int ImageGridComponent::getStartPosition() const // case, whenever we have an integer number of rows or not (the last partial row is ignored when // calculating position and the cursor shouldn't end up in this row when close to the end) int partialRow = (int)mLastRowPartial; - if ((int)mEntries.size() < mGridDimension.x() * (mGridDimension.y() - (int)mLastRowPartial)) - partialRow = 0; int cursorRow = mCursor / mGridDimension.x(); int start = (cursorRow - ((mGridDimension.y() - partialRow) / 2)) * mGridDimension.x(); - // If we are at the end put the row as close as we can and no higher, using the following formula - // Where E is the nb of entries, X the grid x dim (nb of column), Y the grid y dim (nb of line) - // start = first tile of last row - nb column * (nb line - 1) - // = (E - 1) / X * X - X * (Y - 1) - // = X * ((E - 1) / X - Y + 1) - if(start + (mGridDimension.x() * (mGridDimension.y() - partialRow)) >= (int)mEntries.size()) - start = mGridDimension.x() * (((int)mEntries.size() - 1) / mGridDimension.x() - mGridDimension.y() + 1 + partialRow); + // Number of tiles which are just used as a buffer for texture loading + int bufferSize = texBuffersForward[3] * mGridDimension.x(); - if(start < 0) - start = 0; + if(start + (mGridDimension.x() * (mGridDimension.y() - partialRow)) >= (int)mEntries.size() + bufferSize) + { + // If we are at the end put the row as close as we can and no higher, using the following formula + // Where E is the nb of entries, X the grid x dim (nb of column), Y the grid y dim (nb of line) + // start = first tile of last row - nb column * (nb line - 1) + // = (E - 1) / X * X - X * (Y - 1) + // = X * ((E - 1) / X - Y + 1) + start = mGridDimension.x() * (((int)mEntries.size() - 1) / mGridDimension.x() - mGridDimension.y() + 1 + partialRow) + bufferSize; + } + + if(start < -bufferSize) + { + start = -bufferSize; + } return start; } @@ -416,6 +470,9 @@ void ImageGridComponent::calcGridDimension() LOG(LogError) << "Theme defined grid X dimension below 1"; if (mGridDimension.y() < 1) LOG(LogError) << "Theme defined grid Y dimension below 1"; + + // Add extra tiles to both side depending on max texture buffer + mGridDimension.y() += texBuffersForward[3] * 2; };