ES-DE/es-core/src/components/ScrollableContainer.cpp

130 lines
3.2 KiB
C++
Raw Normal View History

#include "components/ScrollableContainer.h"
2017-11-01 22:21:10 +00:00
#include "Renderer.h"
#define AUTO_SCROLL_RESET_DELAY 3000 // ms to reset to top after we reach the bottom
#define AUTO_SCROLL_DELAY 1000 // ms to wait before we start to scroll
#define AUTO_SCROLL_SPEED 50 // ms between scrolls
ScrollableContainer::ScrollableContainer(Window* window) : GuiComponent(window),
mAutoScrollDelay(0), mAutoScrollSpeed(0), mAutoScrollAccumulator(0), mScrollPos(0, 0), mScrollDir(0, 0), mAutoScrollResetAccumulator(0)
{
}
void ScrollableContainer::render(const Transform4x4f& parentTrans)
{
Transform4x4f trans = parentTrans * getTransform();
Vector2i clipPos((int)trans.translation().x(), (int)trans.translation().y());
Vector3f dimScaled = trans * Vector3f(mSize.x(), mSize.y(), 0);
2017-11-17 14:58:52 +00:00
Vector2i clipDim((int)(dimScaled.x() - trans.translation().x()), (int)(dimScaled.y() - trans.translation().y()));
Renderer::pushClipRect(clipPos, clipDim);
trans.translate(-Vector3f(mScrollPos.x(), mScrollPos.y(), 0));
Renderer::setMatrix(trans);
GuiComponent::renderChildren(trans);
Renderer::popClipRect();
}
void ScrollableContainer::setAutoScroll(bool autoScroll)
{
if(autoScroll)
{
mScrollDir = Vector2f(0, 1);
mAutoScrollDelay = AUTO_SCROLL_DELAY;
mAutoScrollSpeed = AUTO_SCROLL_SPEED;
reset();
}else{
mScrollDir = Vector2f(0, 0);
mAutoScrollDelay = 0;
mAutoScrollSpeed = 0;
mAutoScrollAccumulator = 0;
}
}
Vector2f ScrollableContainer::getScrollPos() const
{
return mScrollPos;
}
void ScrollableContainer::setScrollPos(const Vector2f& pos)
{
mScrollPos = pos;
}
void ScrollableContainer::update(int deltaTime)
{
if(mAutoScrollSpeed != 0)
{
mAutoScrollAccumulator += deltaTime;
//scale speed by our width! more text per line = slower scrolling
const float widthMod = (680.0f / getSize().x());
while(mAutoScrollAccumulator >= mAutoScrollSpeed)
{
mScrollPos += mScrollDir;
mAutoScrollAccumulator -= mAutoScrollSpeed;
}
}
//clip scrolling within bounds
if(mScrollPos.x() < 0)
mScrollPos[0] = 0;
if(mScrollPos.y() < 0)
mScrollPos[1] = 0;
const Vector2f contentSize = getContentSize();
if(mScrollPos.x() + getSize().x() > contentSize.x())
{
mScrollPos[0] = contentSize.x() - getSize().x();
mAtEnd = true;
}
if(contentSize.y() < getSize().y())
{
mScrollPos[1] = 0;
}else if(mScrollPos.y() + getSize().y() > contentSize.y())
{
mScrollPos[1] = contentSize.y() - getSize().y();
mAtEnd = true;
}
if(mAtEnd)
{
mAutoScrollResetAccumulator += deltaTime;
if(mAutoScrollResetAccumulator >= AUTO_SCROLL_RESET_DELAY)
reset();
}
GuiComponent::update(deltaTime);
}
//this should probably return a box to allow for when controls don't start at 0,0
Vector2f ScrollableContainer::getContentSize()
{
Vector2f max(0, 0);
for(unsigned int i = 0; i < mChildren.size(); i++)
{
Vector2f pos(mChildren.at(i)->getPosition()[0], mChildren.at(i)->getPosition()[1]);
Vector2f bottomRight = mChildren.at(i)->getSize() + pos;
if(bottomRight.x() > max.x())
max.x() = bottomRight.x();
if(bottomRight.y() > max.y())
max.y() = bottomRight.y();
}
return max;
}
void ScrollableContainer::reset()
{
mScrollPos = Vector2f(0, 0);
mAutoScrollResetAccumulator = 0;
mAutoScrollAccumulator = -mAutoScrollDelay + mAutoScrollSpeed;
mAtEnd = false;
}