mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-01-17 22:55:38 +00:00
Finally added scrolling description text. :)
This commit is contained in:
parent
3971fdc674
commit
ec7ad28fdc
|
@ -43,6 +43,7 @@ namespace Renderer
|
|||
void drawText(std::string text, int x, int y, unsigned int color, Font* font);
|
||||
void drawCenteredText(std::string text, int xOffset, int y, unsigned int color, Font* font);
|
||||
void drawWrappedText(std::string text, int xStart, int yStart, int xLen, unsigned int color, Font* font);
|
||||
void sizeWrappedText(std::string text, int xLen, Font* font, int* xOut, int* yOut);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -252,4 +252,61 @@ namespace Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
void sizeWrappedText(std::string text, int xLen, Font* font, int* xOut, int* yOut)
|
||||
{
|
||||
*xOut = xLen;
|
||||
|
||||
int y = 0;
|
||||
|
||||
std::string line, word, temp;
|
||||
int w, h;
|
||||
size_t space, newline;
|
||||
|
||||
while(text.length() > 0 || !line.empty()) //while there's text or we still have text to render
|
||||
{
|
||||
space = text.find(' ', 0);
|
||||
if(space == std::string::npos)
|
||||
space = text.length() - 1;
|
||||
|
||||
word = text.substr(0, space + 1);
|
||||
|
||||
//check if the next word contains a newline
|
||||
newline = word.find('\n', 0);
|
||||
if(newline != std::string::npos)
|
||||
{
|
||||
word = word.substr(0, newline);
|
||||
text.erase(0, newline + 1);
|
||||
}else{
|
||||
text.erase(0, space + 1);
|
||||
}
|
||||
|
||||
temp = line + word;
|
||||
|
||||
font->sizeText(temp, &w, &h);
|
||||
|
||||
//if we're on the last word and it'll fit on the line, just add it to the line
|
||||
if((w <= xLen && text.length() == 0) || newline != std::string::npos)
|
||||
{
|
||||
line = temp;
|
||||
word = "";
|
||||
}
|
||||
|
||||
//if the next line will be too long or we're on the last of the text, render it
|
||||
if(w > xLen || text.length() == 0 || newline != std::string::npos)
|
||||
{
|
||||
//increment y by height and some extra padding for the next line
|
||||
y += h + 4;
|
||||
|
||||
//move the word we skipped to the next line
|
||||
line = word;
|
||||
}else{
|
||||
//there's still space, continue building the line
|
||||
line = temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*yOut = y;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -93,6 +93,7 @@ bool operator !=(const Vector2<T>& left, const Vector2<T>& right)
|
|||
typedef Vector2<int> Vector2i;
|
||||
typedef Vector2<unsigned int> Vector2u;
|
||||
typedef Vector2<float> Vector2f;
|
||||
typedef Vector2<double> Vector2d;
|
||||
|
||||
class Rect
|
||||
{
|
||||
|
|
|
@ -36,9 +36,11 @@ GuiGameList::GuiGameList(Window* window, bool useDetail) : GuiComponent(window),
|
|||
|
||||
mScreenshot->setOrigin(mTheme->getFloat("gameImageOriginX"), mTheme->getFloat("gameImageOriginY"));
|
||||
|
||||
mDescription.setOffset(Vector2i((int)(Renderer::getScreenWidth() * 0.03), mScreenshot->getOffset().y + mScreenshot->getSize().y + 12));
|
||||
mDescription.setExtent(Vector2u((int)(Renderer::getScreenWidth() * (mTheme->getFloat("listOffsetX") - 0.03)), 0));
|
||||
|
||||
mDescription.setOffset(Vector2i((int)(Renderer::getScreenWidth() * 0.03), getImagePos().y + mScreenshot->getSize().y + 12));
|
||||
//scale delay with screen width (higher width = more text per line)
|
||||
//the scroll speed is automatically scrolled by component size
|
||||
mDescription.setAutoScroll((int)(1500 + (Renderer::getScreenWidth() * 0.5)), 0.025f);
|
||||
|
||||
mTransitionImage.setOffset(Renderer::getScreenWidth(), 0);
|
||||
mTransitionImage.setOrigin(0, 0);
|
||||
mTransitionAnimation.addChild(&mTransitionImage);
|
||||
|
@ -307,7 +309,8 @@ void GuiGameList::updateDetailData()
|
|||
mImageAnimation->fadeIn(35);
|
||||
mImageAnimation->move(imgOffset.x, imgOffset.y, 20);
|
||||
|
||||
mDescription.setOffset(Vector2i((int)(Renderer::getScreenWidth() * 0.03), mScreenshot->getOffset().y + mScreenshot->getSize().y + 12));
|
||||
mDescription.setOffset(Vector2i((int)(Renderer::getScreenWidth() * 0.03), getImagePos().y + mScreenshot->getSize().y + 12));
|
||||
mDescription.setExtent(Vector2u((int)(Renderer::getScreenWidth() * (mTheme->getFloat("listOffsetX") - 0.03)), Renderer::getScreenHeight() - mDescription.getOffset().y));
|
||||
mDescription.setText(((GameData*)mList->getSelectedObject())->getDescription());
|
||||
}else{
|
||||
mScreenshot->setImage("");
|
||||
|
@ -373,6 +376,8 @@ void GuiGameList::update(int deltaTime)
|
|||
mTransitionAnimation.update(deltaTime);
|
||||
|
||||
mList->update(deltaTime);
|
||||
|
||||
mDescription.update(deltaTime);
|
||||
}
|
||||
|
||||
void GuiGameList::doTransition(int dir)
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
#include "../Renderer.h"
|
||||
#include "../Log.h"
|
||||
|
||||
TextComponent::TextComponent(Window* window) : GuiComponent(window), mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true)
|
||||
TextComponent::TextComponent(Window* window) : GuiComponent(window),
|
||||
mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true), mAutoScrollDelay(0), mAutoScrollSpeed(0), mAutoScrollTimer(0)
|
||||
{
|
||||
}
|
||||
|
||||
TextComponent::TextComponent(Window* window, const std::string& text, Font* font, Vector2i pos, Vector2u size) : GuiComponent(window),
|
||||
mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true)
|
||||
mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true), mAutoScrollDelay(0), mAutoScrollSpeed(0), mAutoScrollTimer(0)
|
||||
{
|
||||
setText(text);
|
||||
setFont(font);
|
||||
|
@ -51,11 +52,20 @@ void TextComponent::setText(const std::string& text)
|
|||
|
||||
if(mAutoCalcExtent)
|
||||
calculateExtent();
|
||||
|
||||
mScrollPos = Vector2d(0, 0);
|
||||
mScrollDir = Vector2d(0, 0);
|
||||
resetAutoScrollTimer();
|
||||
}
|
||||
|
||||
Font* TextComponent::getFont() const
|
||||
{
|
||||
return (mFont ? mFont : Renderer::getDefaultFont(Renderer::MEDIUM));;
|
||||
}
|
||||
|
||||
void TextComponent::onRender()
|
||||
{
|
||||
Font* font = (mFont ? mFont : Renderer::getDefaultFont(Renderer::MEDIUM));
|
||||
Font* font = getFont();
|
||||
if(font == NULL)
|
||||
{
|
||||
LOG(LogError) << "TextComponent can't get a valid font!";
|
||||
|
@ -64,7 +74,7 @@ void TextComponent::onRender()
|
|||
|
||||
Renderer::pushClipRect(getGlobalOffset(), getSize());
|
||||
|
||||
Renderer::drawWrappedText(mText, 0, 0, mSize.x, mColor, font);
|
||||
Renderer::drawWrappedText(mText, (int)-mScrollPos.x, (int)-mScrollPos.y, mSize.x, mColor, font);
|
||||
|
||||
Renderer::popClipRect();
|
||||
|
||||
|
@ -73,7 +83,7 @@ void TextComponent::onRender()
|
|||
|
||||
void TextComponent::calculateExtent()
|
||||
{
|
||||
Font* font = (mFont ? mFont : Renderer::getDefaultFont(Renderer::MEDIUM));
|
||||
Font* font = getFont();
|
||||
if(font == NULL)
|
||||
{
|
||||
LOG(LogError) << "TextComponent can't get a valid font!";
|
||||
|
@ -82,3 +92,73 @@ void TextComponent::calculateExtent()
|
|||
|
||||
font->sizeText(mText, (int*)&mSize.x, (int*)&mSize.y);
|
||||
}
|
||||
|
||||
void TextComponent::setAutoScroll(int delay, double speed)
|
||||
{
|
||||
mAutoScrollDelay = delay;
|
||||
mAutoScrollSpeed = speed;
|
||||
resetAutoScrollTimer();
|
||||
}
|
||||
|
||||
void TextComponent::resetAutoScrollTimer()
|
||||
{
|
||||
mAutoScrollTimer = 0;
|
||||
}
|
||||
|
||||
Vector2d TextComponent::getScrollPos() const
|
||||
{
|
||||
return mScrollPos;
|
||||
}
|
||||
|
||||
void TextComponent::setScrollPos(const Vector2d& pos)
|
||||
{
|
||||
mScrollPos = pos;
|
||||
}
|
||||
|
||||
void TextComponent::update(int deltaTime)
|
||||
{
|
||||
double scrollAmt = (double)deltaTime;
|
||||
|
||||
if(mAutoScrollSpeed != 0)
|
||||
{
|
||||
mAutoScrollTimer += deltaTime;
|
||||
|
||||
scrollAmt = (float)(mAutoScrollTimer - mAutoScrollDelay);
|
||||
|
||||
if(scrollAmt > 0)
|
||||
{
|
||||
//scroll the amount of time left over from the delay
|
||||
mAutoScrollTimer = mAutoScrollDelay;
|
||||
|
||||
//scale speed by our width! more text per line = slower scrolling
|
||||
const double widthMod = (680.0 / getSize().x);
|
||||
mScrollDir = Vector2d(0, mAutoScrollSpeed * widthMod);
|
||||
}else{
|
||||
//not enough to pass the delay, do nothing
|
||||
scrollAmt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2d scroll = mScrollDir * scrollAmt;
|
||||
mScrollPos += scroll;
|
||||
|
||||
//clip scrolling within bounds
|
||||
if(mScrollPos.x < 0)
|
||||
mScrollPos.x = 0;
|
||||
if(mScrollPos.y < 0)
|
||||
mScrollPos.y = 0;
|
||||
|
||||
Font* font = getFont();
|
||||
if(font != NULL)
|
||||
{
|
||||
Vector2i textSize;
|
||||
Renderer::sizeWrappedText(mText, getSize().x, getFont(), &textSize.x, &textSize.y);
|
||||
|
||||
if(mScrollPos.x + getSize().x > textSize.x)
|
||||
mScrollPos.x = (double)textSize.x - getSize().x;
|
||||
if(mScrollPos.y + getSize().y > textSize.y)
|
||||
mScrollPos.y = (double)textSize.y - getSize().y;
|
||||
}
|
||||
|
||||
GuiComponent::update(deltaTime);
|
||||
}
|
||||
|
|
|
@ -16,15 +16,29 @@ public:
|
|||
void setText(const std::string& text);
|
||||
void setColor(unsigned int color);
|
||||
|
||||
void onRender();
|
||||
Vector2d getScrollPos() const;
|
||||
void setScrollPos(const Vector2d& pos);
|
||||
void setAutoScroll(int delay, double speed); //Use 0 for speed to disable.
|
||||
void resetAutoScrollTimer();
|
||||
|
||||
void update(int deltaTime) override;
|
||||
void onRender() override;
|
||||
|
||||
private:
|
||||
Font* getFont() const;
|
||||
void calculateExtent();
|
||||
|
||||
unsigned int mColor;
|
||||
Font* mFont;
|
||||
bool mAutoCalcExtent;
|
||||
std::string mText;
|
||||
|
||||
//scrolling
|
||||
Vector2d mScrollPos;
|
||||
Vector2d mScrollDir;
|
||||
int mAutoScrollDelay;
|
||||
double mAutoScrollSpeed;
|
||||
int mAutoScrollTimer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue