diff --git a/es-core/src/components/ScrollableContainer.cpp b/es-core/src/components/ScrollableContainer.cpp index 218b7cd3a..51f33f917 100644 --- a/es-core/src/components/ScrollableContainer.cpp +++ b/es-core/src/components/ScrollableContainer.cpp @@ -18,6 +18,7 @@ ScrollableContainer::ScrollableContainer(Window* window) : GuiComponent{window} , mScrollPos{0.0f, 0.0f} , mScrollDir{0.0f, 0.0f} + , mClipSpacing{0.0f} , mAutoScrollDelay{0} , mAutoScrollSpeed{0} , mAutoScrollAccumulator{0} @@ -81,6 +82,11 @@ void ScrollableContainer::update(int deltaTime) float lineSpacing{mChildren.front()->getLineSpacing()}; float combinedHeight{mChildren.front()->getFont()->getHeight(lineSpacing)}; + // Calculate the line spacing which will be used to clip the container. + if (mClipSpacing == 0.0f) + mClipSpacing = + std::round((combinedHeight - mChildren.front()->getFont()->getLetterHeight()) / 2.0f); + // Resize container to font height boundary to avoid rendering a fraction of the last line. if (!mUpdatedSize && contentSize.y > mSize.y) { float numLines{mSize.y / combinedHeight}; @@ -173,6 +179,11 @@ void ScrollableContainer::render(const glm::mat4& parentTrans) glm::ivec2 clipDim{static_cast(dimScaled.x - trans[3].x), static_cast(dimScaled.y - trans[3].y)}; + // By effectively clipping the upper and lower boundaries of the container we mostly avoid + // scrolling outside the vertical starting and ending positions. + clipPos.y += mClipSpacing; + clipDim.y -= mClipSpacing * 0.9f; + Renderer::pushClipRect(clipPos, clipDim); trans = glm::translate(trans, -glm::vec3{mScrollPos.x, mScrollPos.y, 0.0f}); diff --git a/es-core/src/components/ScrollableContainer.h b/es-core/src/components/ScrollableContainer.h index 27b63f459..fb80b7eea 100644 --- a/es-core/src/components/ScrollableContainer.h +++ b/es-core/src/components/ScrollableContainer.h @@ -44,6 +44,7 @@ private: float mAutoScrollDelayConstant; float mAutoScrollSpeedConstant; float mResolutionModifier; + float mClipSpacing; int mAutoScrollDelay; int mAutoScrollSpeed;