mirror of
https://github.com/FunKey-Project/RetroFE.git
synced 2026-01-27 02:05:06 +01:00
Added support for scrolling text via the scrollingText tag. It uses the following extra attributes:
direction: horizontal | vertical horizontal scrolling will scroll over a single line. vertical scrolling will scroll multiple lines if the text does not fit inside the box. alignment: left | right | centered | justified Defines the alignment of the vertical scrolling text inside the box. scrollingSpeed: Defines the scrolling speed in pixels per second. startPosition: Defines the horizontal starting position of the text compared to the left of the box. Defines the vertical starting position of the text compared to the top of the box. startTime: Defines how many seconds the text will wait before it starts scrolling. endTime: Defines how many seconds the text will take to reappear after it's done scrolling.
This commit is contained in:
parent
ad93b0a93d
commit
6a2ab3d2af
@ -115,6 +115,7 @@ set(RETROFE_HEADERS
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ImageBuilder.h"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ReloadableMedia.h"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ReloadableText.h"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ScrollingText.h"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ScrollingList.h"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/Text.h"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/VideoComponent.h"
|
||||
@ -171,6 +172,7 @@ set(RETROFE_SOURCES
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/Text.cpp"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ReloadableMedia.cpp"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ReloadableText.cpp"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ScrollingText.cpp"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/ScrollingList.cpp"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/VideoBuilder.cpp"
|
||||
"${RETROFE_DIR}/Source/Graphics/Component/VideoComponent.cpp"
|
||||
|
||||
594
RetroFE/Source/Graphics/Component/ScrollingText.cpp
Normal file
594
RetroFE/Source/Graphics/Component/ScrollingText.cpp
Normal file
@ -0,0 +1,594 @@
|
||||
/* This file is part of RetroFE.
|
||||
*
|
||||
* RetroFE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RetroFE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ScrollingText.h"
|
||||
#include "../ViewInfo.h"
|
||||
#include "../../Database/Configuration.h"
|
||||
#include "../../Utility/Log.h"
|
||||
#include "../../Utility/Utils.h"
|
||||
#include "../../SDL.h"
|
||||
#include "../Font.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
ScrollingText::ScrollingText(Configuration &config, bool systemMode, bool layoutMode, std::string type, std::string textFormat, std::string alignment, Page &p, int displayOffset, Font *font, float scaleX, float scaleY, std::string direction, float scrollingSpeed, float startPosition, float startTime, float endTime )
|
||||
: Component(p)
|
||||
, config_(config)
|
||||
, systemMode_(systemMode)
|
||||
, layoutMode_(layoutMode)
|
||||
, fontInst_(font)
|
||||
, type_(type)
|
||||
, textFormat_(textFormat)
|
||||
, alignment_(alignment)
|
||||
, scaleX_(scaleX)
|
||||
, scaleY_(scaleY)
|
||||
, direction_(direction)
|
||||
, scrollingSpeed_(scrollingSpeed)
|
||||
, startPosition_(startPosition)
|
||||
, currentPosition_(-startPosition)
|
||||
, startTime_(startTime)
|
||||
, waitStartTime_(startTime)
|
||||
, endTime_(endTime)
|
||||
, waitEndTime_(0.0f)
|
||||
, currentCollection_("")
|
||||
, page_(NULL)
|
||||
, displayOffset_(displayOffset)
|
||||
|
||||
{
|
||||
text_.clear( );
|
||||
}
|
||||
|
||||
|
||||
ScrollingText::~ScrollingText( )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ScrollingText::update(float dt)
|
||||
{
|
||||
|
||||
if (waitEndTime_ > 0)
|
||||
{
|
||||
waitEndTime_ -= dt;
|
||||
}
|
||||
else if (waitStartTime_ > 0)
|
||||
{
|
||||
waitStartTime_ -= dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (direction_ == "horizontal")
|
||||
{
|
||||
currentPosition_ += scrollingSpeed_ * dt * scaleX_;
|
||||
}
|
||||
else if (direction_ == "vertical")
|
||||
{
|
||||
currentPosition_ += scrollingSpeed_ * dt * scaleY_;
|
||||
}
|
||||
}
|
||||
|
||||
if (newItemSelected)
|
||||
{
|
||||
reloadTexture( );
|
||||
newItemSelected = false;
|
||||
}
|
||||
|
||||
Component::update(dt);
|
||||
}
|
||||
|
||||
|
||||
void ScrollingText::freeGraphicsMemory( )
|
||||
{
|
||||
Component::freeGraphicsMemory( );
|
||||
text_.clear( );
|
||||
}
|
||||
|
||||
|
||||
void ScrollingText::reloadTexture( )
|
||||
{
|
||||
|
||||
currentPosition_ = -startPosition_ * scaleX_;
|
||||
waitStartTime_ = startTime_;
|
||||
waitEndTime_ = 0.0f;
|
||||
|
||||
text_.clear( );
|
||||
|
||||
Item *selectedItem = page.getSelectedItem( displayOffset_ );
|
||||
if (!selectedItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
config_.getProperty( "currentCollection", currentCollection_ );
|
||||
|
||||
// build clone list
|
||||
std::vector<std::string> names;
|
||||
|
||||
names.push_back( selectedItem->name );
|
||||
names.push_back( selectedItem->fullTitle );
|
||||
|
||||
if (selectedItem->cloneof.length( ) > 0)
|
||||
{
|
||||
names.push_back( selectedItem->cloneof );
|
||||
}
|
||||
|
||||
// Check for corresponding .txt files
|
||||
for (unsigned int n = 0; n < names.size( ) && text_.empty( ); ++n)
|
||||
{
|
||||
|
||||
std::string basename = names[n];
|
||||
|
||||
Utils::replaceSlashesWithUnderscores( basename );
|
||||
|
||||
if (systemMode_)
|
||||
{
|
||||
|
||||
// check the master collection for the system artifact
|
||||
loadText( collectionName, type_, type_, true );
|
||||
|
||||
// check collection for the system artifact
|
||||
if (text_.empty( ))
|
||||
{
|
||||
loadText( selectedItem->collectionInfo->name, type_, type_, true );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// are we looking at a leaf or a submenu
|
||||
if (selectedItem->leaf) // item is a leaf
|
||||
{
|
||||
|
||||
// check the master collection for the artifact
|
||||
loadText( collectionName, type_, basename, false );
|
||||
|
||||
// check the collection for the artifact
|
||||
if (text_.empty( ))
|
||||
{
|
||||
loadText( selectedItem->collectionInfo->name, type_, basename, false );
|
||||
}
|
||||
|
||||
}
|
||||
else // item is a submenu
|
||||
{
|
||||
|
||||
// check the master collection for the artifact
|
||||
loadText( collectionName, type_, basename, false );
|
||||
|
||||
// check the collection for the artifact
|
||||
if (text_.empty( ))
|
||||
{
|
||||
loadText( selectedItem->collectionInfo->name, type_, basename, false );
|
||||
}
|
||||
|
||||
// check the submenu collection for the system artifact
|
||||
if (text_.empty( ))
|
||||
{
|
||||
loadText( selectedItem->name, type_, type_, true );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ScrollingText::loadText( std::string collection, std::string type, std::string basename, bool systemMode )
|
||||
{
|
||||
|
||||
std::string textPath = "";
|
||||
|
||||
// check the system folder
|
||||
if (layoutMode_)
|
||||
{
|
||||
std::string layoutName;
|
||||
config_.getProperty("layout", layoutName);
|
||||
textPath = Utils::combinePath(Configuration::absolutePath, "layouts", layoutName, "collections", collection);
|
||||
if (systemMode)
|
||||
textPath = Utils::combinePath(textPath, "system_artwork");
|
||||
else
|
||||
textPath = Utils::combinePath(textPath, "medium_artwork", type);
|
||||
}
|
||||
else
|
||||
{
|
||||
config_.getMediaPropertyAbsolutePath( collection, type, systemMode, textPath );
|
||||
}
|
||||
|
||||
textPath = Utils::combinePath( textPath, basename );
|
||||
|
||||
textPath += ".txt";
|
||||
|
||||
std::ifstream includeStream( textPath.c_str( ) );
|
||||
|
||||
if (!includeStream.good( ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
|
||||
while(std::getline(includeStream, line))
|
||||
{
|
||||
|
||||
// In horizontal scrolling direction, add a space before every line except the first.
|
||||
if (direction_ == "horizontal" && !text_.empty( ))
|
||||
{
|
||||
line = " " + line;
|
||||
}
|
||||
|
||||
// Reformat lines to uppercase or lowercase
|
||||
if (textFormat_ == "uppercase")
|
||||
{
|
||||
std::transform(line.begin(), line.end(), line.begin(), ::toupper);
|
||||
}
|
||||
if (textFormat_ == "lowercase")
|
||||
{
|
||||
std::transform(line.begin(), line.end(), line.begin(), ::tolower);
|
||||
}
|
||||
|
||||
text_.push_back( line );
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ScrollingText::draw( )
|
||||
{
|
||||
Component::draw( );
|
||||
|
||||
if (!text_.empty( ) && waitEndTime_ <= 0.0f)
|
||||
{
|
||||
|
||||
Font *font;
|
||||
if (baseViewInfo.font) // Use font of this specific item if available
|
||||
font = baseViewInfo.font;
|
||||
else // If not, use the general font settings
|
||||
font = fontInst_;
|
||||
|
||||
SDL_Texture *t = font->getTexture( );
|
||||
|
||||
float imageWidth = 0;
|
||||
float imageMaxWidth = 0;
|
||||
float imageMaxHeight = 0;
|
||||
if (baseViewInfo.Width < baseViewInfo.MaxWidth && baseViewInfo.Width > 0)
|
||||
{
|
||||
imageMaxWidth = baseViewInfo.Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageMaxWidth = baseViewInfo.MaxWidth;
|
||||
}
|
||||
if (baseViewInfo.Height < baseViewInfo.MaxHeight && baseViewInfo.Height > 0)
|
||||
{
|
||||
imageMaxHeight = baseViewInfo.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageMaxHeight = baseViewInfo.MaxHeight;
|
||||
}
|
||||
|
||||
float scale = (float)baseViewInfo.FontSize / (float)font->getHeight( );
|
||||
|
||||
float xOrigin = baseViewInfo.XRelativeToOrigin( );
|
||||
float yOrigin = baseViewInfo.YRelativeToOrigin( );
|
||||
|
||||
SDL_Rect rect;
|
||||
|
||||
float position = 0.0f;
|
||||
|
||||
if (direction_ == "horizontal")
|
||||
{
|
||||
|
||||
rect.x = static_cast<int>( xOrigin );
|
||||
|
||||
if (currentPosition_ < 0)
|
||||
{
|
||||
rect.x -= static_cast<int>( currentPosition_ );
|
||||
}
|
||||
|
||||
for (unsigned int l = 0; l < text_.size( ); ++l)
|
||||
{
|
||||
for (unsigned int i = 0; i < text_[l].size( ); ++i)
|
||||
{
|
||||
|
||||
// Do not print outside the box
|
||||
if (rect.x >= (static_cast<int>( xOrigin ) + imageMaxWidth))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Font::GlyphInfo glyph;
|
||||
|
||||
if (font->getRect( text_[l][i], glyph) && glyph.rect.h > 0)
|
||||
{
|
||||
SDL_Rect charRect = glyph.rect;
|
||||
rect.h = static_cast<int>( charRect.h * scale * scaleY_ );
|
||||
rect.w = static_cast<int>( charRect.w * scale * scaleX_ );
|
||||
rect.y = static_cast<int>( yOrigin );
|
||||
|
||||
if (font->getAscent( ) < glyph.maxY)
|
||||
{
|
||||
rect.y += static_cast<int>( (font->getAscent( ) - glyph.maxY) * scale * scaleY_ );
|
||||
}
|
||||
|
||||
// Check if glyph falls partially outside the box at the back end
|
||||
if ((rect.x + static_cast<int>( glyph.advance * scale * scaleX_ )) >= (static_cast<int>( xOrigin ) + imageMaxWidth))
|
||||
{
|
||||
rect.w = static_cast<int>( xOrigin ) + imageMaxWidth - rect.x;
|
||||
charRect.w = static_cast<int>( rect.w / scale / scaleX_ );
|
||||
}
|
||||
|
||||
// Print the glyph if it falls (partially) within the box
|
||||
if ( position + glyph.advance * scale * scaleX_ > currentPosition_ )
|
||||
{
|
||||
// Check if glyph falls partially outside the box at the front end
|
||||
if ( position < currentPosition_ )
|
||||
{
|
||||
rect.w = static_cast<int>( glyph.advance * scale * scaleX_ + position - currentPosition_ );
|
||||
charRect.x = static_cast<int>( charRect.x + charRect.w - rect.w / scale / scaleX_ );
|
||||
charRect.w = static_cast<int>( rect.w / scale / scaleX_ );
|
||||
}
|
||||
if (rect.w > 0)
|
||||
{
|
||||
SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo.Angle, baseViewInfo.Reflection, baseViewInfo.ReflectionDistance, baseViewInfo.ReflectionScale, baseViewInfo.ReflectionAlpha);
|
||||
}
|
||||
rect.x += rect.w;
|
||||
}
|
||||
position += glyph.advance * scale * scaleX_;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine image width
|
||||
for (unsigned int l = 0; l < text_.size( ); ++l)
|
||||
{
|
||||
for (unsigned int i = 0; i < text_[l].size( ); ++i)
|
||||
{
|
||||
Font::GlyphInfo glyph;
|
||||
if (font->getRect( text_[l][i], glyph ))
|
||||
{
|
||||
imageWidth += glyph.advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset scrolling position when we're done
|
||||
if (currentPosition_ > imageWidth * scale * scaleX_)
|
||||
{
|
||||
waitStartTime_ = startTime_;
|
||||
waitEndTime_ = endTime_;
|
||||
currentPosition_ = -startPosition_ * scaleX_;
|
||||
}
|
||||
|
||||
}
|
||||
else if (direction_ == "vertical")
|
||||
{
|
||||
|
||||
unsigned int spaceWidth = 0;
|
||||
{
|
||||
Font::GlyphInfo glyph;
|
||||
if (font->getRect( ' ', glyph) )
|
||||
{
|
||||
spaceWidth = static_cast<int>( glyph.advance * scale * scaleX_);
|
||||
}
|
||||
}
|
||||
|
||||
// Reformat the text based on the image width
|
||||
std::vector<std::string> text;
|
||||
std::vector<unsigned int> textWords;
|
||||
std::vector<unsigned int> textWidth;
|
||||
std::vector<bool> textLast;
|
||||
for (unsigned int l = 0; l < text_.size( ); ++l)
|
||||
{
|
||||
std::string line = "";
|
||||
std::istringstream iss(text_[l]);
|
||||
std::string word;
|
||||
unsigned int width = 0;
|
||||
unsigned int lineWidth = 0;
|
||||
unsigned int wordCount = 0;
|
||||
while (iss >> word)
|
||||
{
|
||||
|
||||
// Determine word image width
|
||||
unsigned int wordWidth = 0;
|
||||
for (unsigned int i = 0; i < word.size( ); ++i)
|
||||
{
|
||||
Font::GlyphInfo glyph;
|
||||
if (font->getRect( word[i], glyph) )
|
||||
{
|
||||
wordWidth += static_cast<int>( glyph.advance * scale * scaleX_ );
|
||||
}
|
||||
}
|
||||
// Determine if the word will fit on the line
|
||||
if (width > 0 && (width + spaceWidth + wordWidth > imageMaxWidth))
|
||||
{
|
||||
text.push_back( line );
|
||||
textWords.push_back( wordCount );
|
||||
textWidth.push_back( lineWidth );
|
||||
textLast.push_back( false );
|
||||
line = word;
|
||||
width = wordWidth;
|
||||
lineWidth = wordWidth;
|
||||
wordCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (width == 0)
|
||||
{
|
||||
line += word;
|
||||
width += wordWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
line += " " + word;
|
||||
width += spaceWidth + wordWidth;
|
||||
}
|
||||
lineWidth += wordWidth;
|
||||
wordCount += 1;
|
||||
}
|
||||
}
|
||||
if (text_[l] == "" || line != "")
|
||||
{
|
||||
text.push_back( line );
|
||||
textWords.push_back( wordCount );
|
||||
textWidth.push_back( lineWidth );
|
||||
textLast.push_back( true );
|
||||
width = 0;
|
||||
lineWidth = 0;
|
||||
wordCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print reformatted text
|
||||
rect.y = static_cast<int>( yOrigin );
|
||||
|
||||
// Do not scroll if the text fits fully inside the box, and start position is 0
|
||||
if (text.size() * font->getHeight( ) * scale * scaleY_ <= imageMaxHeight && startPosition_ == 0.0f)
|
||||
{
|
||||
currentPosition_ = 0.0f;
|
||||
startTime_ = 0.0f;
|
||||
endTime_ = 0.0f;
|
||||
}
|
||||
|
||||
for (unsigned int l = 0; l < text.size( ); ++l)
|
||||
{
|
||||
|
||||
// Do not print outside the box
|
||||
if (rect.y >= (static_cast<int>( yOrigin ) + imageMaxHeight))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Define x coordinate
|
||||
rect.x = static_cast<int>( xOrigin );
|
||||
if (alignment_ == "right")
|
||||
{
|
||||
rect.x = static_cast<int>( xOrigin + imageMaxWidth - textWidth[l] - (textWords[l] - 1) * spaceWidth * scale * scaleX_ );
|
||||
}
|
||||
if (alignment_ == "centered")
|
||||
{
|
||||
rect.x = static_cast<int>( xOrigin + imageMaxWidth / 2 - textWidth[l] / 2 - (textWords[l] - 1) * spaceWidth * scale * scaleX_ / 2 );
|
||||
}
|
||||
|
||||
std::istringstream iss(text[l]);
|
||||
std::string word;
|
||||
unsigned int wordCount = textWords[l];
|
||||
unsigned int spaceFill = imageMaxWidth - textWidth[l];
|
||||
unsigned int yAdvance = font->getHeight( ) * scale * scaleY_;
|
||||
while (iss >> word)
|
||||
{
|
||||
|
||||
for (unsigned int i = 0; i < word.size( ); ++i)
|
||||
{
|
||||
Font::GlyphInfo glyph;
|
||||
|
||||
if (font->getRect( word[i], glyph) && glyph.rect.h > 0)
|
||||
{
|
||||
SDL_Rect charRect = glyph.rect;
|
||||
rect.h = static_cast<int>( charRect.h * scale * scaleY_ );
|
||||
rect.w = static_cast<int>( charRect.w * scale * scaleX_ );
|
||||
yAdvance = font->getHeight( ) * scale * scaleY_;
|
||||
|
||||
// Check if glyph falls partially outside the box at the bottom end
|
||||
if ((rect.y + rect.h) >= (static_cast<int>( yOrigin ) + imageMaxHeight))
|
||||
{
|
||||
rect.h = static_cast<int>( yOrigin ) + imageMaxHeight - rect.y;
|
||||
charRect.h = static_cast<int>( rect.h / scale / scaleY_ );
|
||||
}
|
||||
|
||||
// Print the glyph if it falls (partially) within the box
|
||||
if ( position + font->getHeight( ) * scale * scaleY_ > currentPosition_ )
|
||||
{
|
||||
// Check if glyph falls partially outside the box at the front end
|
||||
if ( position < currentPosition_ )
|
||||
{
|
||||
yAdvance -= rect.h - static_cast<int>( font->getHeight( ) * scale * scaleX_ + position - currentPosition_ );
|
||||
rect.h = static_cast<int>( font->getHeight( ) * scale * scaleX_ + position - currentPosition_ );
|
||||
charRect.y = static_cast<int>( charRect.y + charRect.h - rect.h / scale / scaleX_ );
|
||||
charRect.h = static_cast<int>( rect.h / scale / scaleX_ );
|
||||
}
|
||||
if (rect.h > 0)
|
||||
{
|
||||
SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo.Angle, baseViewInfo.Reflection, baseViewInfo.ReflectionDistance, baseViewInfo.ReflectionScale, baseViewInfo.ReflectionAlpha);
|
||||
}
|
||||
}
|
||||
rect.x += static_cast<int>( glyph.advance * scale * scaleX_ );
|
||||
}
|
||||
}
|
||||
|
||||
// Print justified
|
||||
wordCount -= 1;
|
||||
if (wordCount > 0 && !textLast[l] && alignment_ == "justified")
|
||||
{
|
||||
unsigned int advance = static_cast<int>( spaceFill / wordCount );
|
||||
spaceFill -= advance;
|
||||
rect.x += advance;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.x += static_cast<int>( spaceWidth * scale * scaleX_ );
|
||||
}
|
||||
}
|
||||
|
||||
// Handle scrolling of empty lines
|
||||
if (text[l] == "")
|
||||
{
|
||||
Font::GlyphInfo glyph;
|
||||
|
||||
if (font->getRect( ' ', glyph) && glyph.rect.h > 0)
|
||||
{
|
||||
rect.h = static_cast<int>( glyph.rect.h * scale * scaleY_ );
|
||||
|
||||
// Check if the glyph falls (partially) within the box at the front end
|
||||
if ((position + font->getHeight( ) * scale * scaleY_ > currentPosition_) &&
|
||||
(position < currentPosition_))
|
||||
{
|
||||
yAdvance -= rect.h - static_cast<int>( font->getHeight( ) * scale * scaleX_ + position - currentPosition_ );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( position + font->getHeight( ) * scale * scaleY_ > currentPosition_ )
|
||||
{
|
||||
rect.y += yAdvance;
|
||||
}
|
||||
position += font->getHeight( ) * scale * scaleY_;
|
||||
|
||||
}
|
||||
|
||||
// Reset scrolling position when we're done
|
||||
if (currentPosition_ > text.size( ) * font->getHeight( ) * scale * scaleX_)
|
||||
{
|
||||
waitStartTime_ = startTime_;
|
||||
waitEndTime_ = endTime_;
|
||||
currentPosition_ = -startPosition_ * scaleY_;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
57
RetroFE/Source/Graphics/Component/ScrollingText.h
Normal file
57
RetroFE/Source/Graphics/Component/ScrollingText.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* This file is part of RetroFE.
|
||||
*
|
||||
* RetroFE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RetroFE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "Component.h"
|
||||
#include "../../Collection/Item.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
class ScrollingText : public Component
|
||||
{
|
||||
public:
|
||||
ScrollingText(Configuration &config, bool systemMode, bool layoutMode, std::string type, std::string textFormat, std::string alignment, Page &page, int displayOffset, Font *font, float scaleX, float scaleY, std::string direction, float scrollingSpeed, float startPosition, float startTime, float endTime );
|
||||
virtual ~ScrollingText( );
|
||||
void update(float dt);
|
||||
void draw( );
|
||||
void freeGraphicsMemory( );
|
||||
|
||||
private:
|
||||
void reloadTexture( );
|
||||
void loadText( std::string collection, std::string type, std::string basename, bool systemMode );
|
||||
Configuration &config_;
|
||||
bool systemMode_;
|
||||
bool layoutMode_;
|
||||
Font *fontInst_;
|
||||
std::string type_;
|
||||
std::string textFormat_;
|
||||
std::string alignment_;
|
||||
std::vector<std::string> text_;
|
||||
float scaleX_;
|
||||
float scaleY_;
|
||||
std::string direction_;
|
||||
float scrollingSpeed_;
|
||||
float startPosition_;
|
||||
float currentPosition_;
|
||||
float startTime_;
|
||||
float waitStartTime_;
|
||||
float endTime_;
|
||||
float waitEndTime_;
|
||||
std::string currentCollection_;
|
||||
Page *page_;
|
||||
int displayOffset_;
|
||||
};
|
||||
@ -22,6 +22,7 @@
|
||||
#include "Component/Text.h"
|
||||
#include "Component/ReloadableText.h"
|
||||
#include "Component/ReloadableMedia.h"
|
||||
#include "Component/ScrollingText.h"
|
||||
#include "Component/ScrollingList.h"
|
||||
#include "Component/Video.h"
|
||||
#include "Animate/AnimationEvents.h"
|
||||
@ -432,7 +433,8 @@ bool PageBuilder::buildComponents(xml_node<> *layout, Page *page)
|
||||
|
||||
loadReloadableImages(layout, "reloadableImage", page);
|
||||
loadReloadableImages(layout, "reloadableVideo", page);
|
||||
loadReloadableImages(layout, "reloadableText", page);
|
||||
loadReloadableImages(layout, "reloadableText", page);
|
||||
loadReloadableImages(layout, "scrollingText", page);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -453,6 +455,12 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
|
||||
xml_attribute<> *pluralPrefixXml = componentXml->first_attribute("pluralPrefix");
|
||||
xml_attribute<> *pluralPostfixXml = componentXml->first_attribute("pluralPostfix");
|
||||
xml_attribute<> *selectedOffsetXml = componentXml->first_attribute("selectedOffset");
|
||||
xml_attribute<> *directionXml = componentXml->first_attribute("direction");
|
||||
xml_attribute<> *scrollingSpeedXml = componentXml->first_attribute("scrollingSpeed");
|
||||
xml_attribute<> *startPositionXml = componentXml->first_attribute("startPosition");
|
||||
xml_attribute<> *startTimeXml = componentXml->first_attribute("startTime");
|
||||
xml_attribute<> *endTimeXml = componentXml->first_attribute("endTime");
|
||||
xml_attribute<> *alignmentXml = componentXml->first_attribute("alignment");
|
||||
bool systemMode = false;
|
||||
bool layoutMode = false;
|
||||
int selectedOffset = 0;
|
||||
@ -470,6 +478,10 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
|
||||
{
|
||||
Logger::write(Logger::ZONE_ERROR, "Layout", "Image component in layout does not specify a source image file");
|
||||
}
|
||||
if(!type && tagName == "scrollingText")
|
||||
{
|
||||
Logger::write(Logger::ZONE_ERROR, "Layout", "Scroling Text component in layout does not specify a type");
|
||||
}
|
||||
|
||||
|
||||
if(mode)
|
||||
@ -538,6 +550,49 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
|
||||
c = new ReloadableText(type->value(), *page, config_, font, layoutKey, timeFormat, textFormat, singlePrefix, singlePostfix, pluralPrefix, pluralPostfix, scaleX_, scaleY_);
|
||||
}
|
||||
}
|
||||
else if(tagName == "scrollingText")
|
||||
{
|
||||
if(type)
|
||||
{
|
||||
Font *font = addFont(componentXml, NULL);
|
||||
std::string direction = "horizontal";
|
||||
std::string textFormat = "";
|
||||
if (textFormatXml)
|
||||
{
|
||||
textFormat = textFormatXml->value();
|
||||
}
|
||||
if (directionXml)
|
||||
{
|
||||
direction = directionXml->value();
|
||||
}
|
||||
float scrollingSpeed = 1.0f;
|
||||
if (scrollingSpeedXml)
|
||||
{
|
||||
scrollingSpeed = Utils::convertFloat(scrollingSpeedXml->value());
|
||||
}
|
||||
float startPosition = 0.0f;
|
||||
if (startPositionXml)
|
||||
{
|
||||
startPosition = Utils::convertFloat(startPositionXml->value());
|
||||
}
|
||||
float startTime = 0.0f;
|
||||
if (startTimeXml)
|
||||
{
|
||||
startTime = Utils::convertFloat(startTimeXml->value());
|
||||
}
|
||||
float endTime = 0.0f;
|
||||
if (endTimeXml)
|
||||
{
|
||||
endTime = Utils::convertFloat(endTimeXml->value());
|
||||
}
|
||||
std::string alignment = "";
|
||||
if (alignmentXml)
|
||||
{
|
||||
alignment = alignmentXml->value();
|
||||
}
|
||||
c = new ScrollingText(config_, systemMode, layoutMode, type->value(), textFormat, alignment, *page, selectedOffset, font, scaleX_, scaleY_, direction, scrollingSpeed, startPosition, startTime, endTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Font *font = addFont(componentXml, NULL);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user