Merge pull request #212 from jrassa/carousel-enhancements

carousel enhancements
This commit is contained in:
John Rassa 2017-08-19 09:25:52 -04:00 committed by GitHub
commit 230c6e4a97
14 changed files with 223 additions and 87 deletions

View file

@ -673,17 +673,32 @@ EmulationStation borrows the concept of "nine patches" from Android (or "9-Slice
#### carousel
* `type` - type: STRING.
- Accepted values are "horizontal" or "vertical". Sets the scoll direction of the carousel.
- Default is "horizontal".
- Sets the scoll direction of the carousel.
- Accepted values are "horizontal", "vertical" or "vertical_wheel".
- Default is "horizontal".
* `size` - type: NORMALIZED_PAIR. Default is "1 0.2325"
* `pos` - type: NORMALIZED_PAIR. Default is "0 0.38375".
* `origin` - type: NORMALIZED_PAIR.
- Where on the carousel `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the carousel exactly in the middle of the screen. If the "POSITION" and "SIZE" attributes are themable, "ORIGIN" is implied.
* `color` - type: COLOR.
- Controls the color of the carousel background.
- Default is FFFFFFD8
* `logoSize` - type: NORMALIZED_PAIR. Default is "0.25 0.155"
* `logoScale` - type: FLOAT.
* Selected logo is increased in size by this scale
* Default is 1.2
- Selected logo is increased in size by this scale
- Default is 1.2
* `logoRotation` - type: FLOAT.
- Angle in degrees that the logos should be rotated. Value should be positive.
- Default is 7.5
- This property only applies when `type` is "vertical_wheel".
* `logoRotationOrigin` - type: NORMALIZED_PAIR.
- Point around which the logos will be rotated. Defaults to `-5 0.5`.
- This property only applies when `type` is "vertical_wheel".
* `logoAlignment` - type: STRING.
- Sets the alignment of the logos relative to the carousel.
- Accepted values are "top", "bottom" or "center" when `type` is "horizontal".
- Accepted values are "left", "right" or "center" when `type` is "vertical" or "vertical_wheel".
- Default is "center"
* `maxLogoCount` - type: FLOAT.
- Sets the number of logos to display in the carousel.
- Default is 3

View file

@ -19,14 +19,14 @@ GuiFastSelect::GuiFastSelect(Window* window, IGameListView* gamelist) : GuiCompo
addChild(&mBackground);
mLetterText.setSize(mSize.x(), mSize.y() * 0.75f);
mLetterText.setAlignment(ALIGN_CENTER);
mLetterText.setHorizontalAlignment(ALIGN_CENTER);
mLetterText.applyTheme(theme, "fastSelect", "letter", FONT_PATH | COLOR);
// TODO - set font size
addChild(&mLetterText);
mSortText.setPosition(0, mSize.y() * 0.75f);
mSortText.setSize(mSize.x(), mSize.y() * 0.25f);
mSortText.setAlignment(ALIGN_CENTER);
mSortText.setHorizontalAlignment(ALIGN_CENTER);
mSortText.applyTheme(theme, "fastSelect", "subtext", FONT_PATH | COLOR);
// TODO - set font size
addChild(&mSortText);

View file

@ -421,7 +421,7 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
mVersion.setFont(Font::get(FONT_SIZE_SMALL));
mVersion.setColor(0x5E5E5EFF);
mVersion.setText("EMULATIONSTATION V" + strToUpper(PROGRAM_VERSION_STRING));
mVersion.setAlignment(ALIGN_CENTER);
mVersion.setHorizontalAlignment(ALIGN_CENTER);
addChild(&mMenu);
addChild(&mVersion);

View file

@ -49,18 +49,10 @@ void SystemView::populate()
if(!path.empty() && ResourceManager::getInstance()->fileExists(path))
{
ImageComponent* logo = new ImageComponent(mWindow, false, false);
logo->setMaxSize(Eigen::Vector2f(mCarousel.logoSize.x(), mCarousel.logoSize.y()));
logo->setMaxSize(mCarousel.logoSize * mCarousel.logoScale);
logo->applyTheme((*it)->getTheme(), "system", "logo", ThemeFlags::PATH | ThemeFlags::COLOR);
logo->setPosition((mCarousel.logoSize.x() - logo->getSize().x()) / 2,
(mCarousel.logoSize.y() - logo->getSize().y()) / 2); // center
e.data.logo = std::shared_ptr<GuiComponent>(logo);
ImageComponent* logoSelected = new ImageComponent(mWindow, false, false);
logoSelected->setMaxSize(Eigen::Vector2f(mCarousel.logoSize.x() * mCarousel.logoScale, mCarousel.logoSize.y() * mCarousel.logoScale));
logoSelected->applyTheme((*it)->getTheme(), "system", "logo", ThemeFlags::PATH | ThemeFlags::COLOR);
logoSelected->setPosition((mCarousel.logoSize.x() - logoSelected->getSize().x()) / 2,
(mCarousel.logoSize.y() - logoSelected->getSize().y()) / 2); // center
e.data.logoSelected = std::shared_ptr<GuiComponent>(logoSelected);
e.data.logo = std::shared_ptr<GuiComponent>(logo);
}
}
if (!e.data.logo)
@ -71,20 +63,36 @@ void SystemView::populate()
Font::get(FONT_SIZE_LARGE),
0x000000FF,
ALIGN_CENTER);
text->setSize(mCarousel.logoSize);
text->applyTheme((*it)->getTheme(), "system", "logoText", ThemeFlags::FONT_PATH | ThemeFlags::COLOR | ThemeFlags::FORCE_UPPERCASE);
text->setSize(mCarousel.logoSize * mCarousel.logoScale);
text->applyTheme((*it)->getTheme(), "system", "logoText", ThemeFlags::FONT_PATH | ThemeFlags::FONT_SIZE | ThemeFlags::COLOR | ThemeFlags::FORCE_UPPERCASE);
e.data.logo = std::shared_ptr<GuiComponent>(text);
TextComponent* textSelected = new TextComponent(mWindow,
(*it)->getName(),
Font::get((int)(FONT_SIZE_LARGE * mCarousel.logoScale)),
0x000000FF,
ALIGN_CENTER);
textSelected->setSize(mCarousel.logoSize);
textSelected->applyTheme((*it)->getTheme(), "system", "logoText", ThemeFlags::FONT_PATH | ThemeFlags::COLOR | ThemeFlags::FORCE_UPPERCASE);
e.data.logoSelected = std::shared_ptr<GuiComponent>(textSelected);
if (mCarousel.type == VERTICAL || mCarousel.type == VERTICAL_WHEEL)
text->setHorizontalAlignment(mCarousel.logoAlignment);
else
text->setVerticalAlignment(mCarousel.logoAlignment);
}
if (mCarousel.type == VERTICAL || mCarousel.type == VERTICAL_WHEEL)
{
if (mCarousel.logoAlignment == ALIGN_LEFT)
e.data.logo->setOrigin(0, 0.5);
else if (mCarousel.logoAlignment == ALIGN_RIGHT)
e.data.logo->setOrigin(1.0, 0.5);
else
e.data.logo->setOrigin(0.5, 0.5);
} else {
if (mCarousel.logoAlignment == ALIGN_TOP)
e.data.logo->setOrigin(0.5, 0);
else if (mCarousel.logoAlignment == ALIGN_BOTTOM)
e.data.logo->setOrigin(0.5, 1);
else
e.data.logo->setOrigin(0.5, 0.5);
}
Eigen::Vector2f denormalized = mCarousel.logoSize.cwiseProduct(e.data.logo->getOrigin());
e.data.logo->setPosition(denormalized.x(), denormalized.y(), 0.0);
// delete any existing extras
for (auto extra : e.data.backgroundExtras)
delete extra;
@ -94,7 +102,7 @@ void SystemView::populate()
e.data.backgroundExtras = ThemeData::makeExtras((*it)->getTheme(), "system", mWindow);
// sort the extras by z-index
std:stable_sort(e.data.backgroundExtras.begin(), e.data.backgroundExtras.end(), [](GuiComponent* a, GuiComponent* b) {
std::stable_sort(e.data.backgroundExtras.begin(), e.data.backgroundExtras.end(), [](GuiComponent* a, GuiComponent* b) {
return b->getZIndex() > a->getZIndex();
});
@ -124,6 +132,7 @@ bool SystemView::input(InputConfig* config, Input input)
switch (mCarousel.type)
{
case VERTICAL:
case VERTICAL_WHEEL:
if (config->isMappedTo("up", input))
{
listInput(-1);
@ -400,14 +409,16 @@ void SystemView::getViewElements(const std::shared_ptr<ThemeData>& theme)
// Render system carousel
void SystemView::renderCarousel(const Eigen::Affine3f& trans)
{
Eigen::Vector2i clipPos((int)mCarousel.pos.x(), (int)mCarousel.pos.y());
Eigen::Vector2i clipSize((int)mCarousel.size.x(), (int)mCarousel.size.y());
Renderer::pushClipRect(clipPos, clipSize);
// background box behind logos
Renderer::setMatrix(trans);
Renderer::drawRect(mCarousel.pos.x(), mCarousel.pos.y(), mCarousel.size.x(), mCarousel.size.y(), mCarousel.color);
Eigen::Affine3f carouselTrans = trans;
carouselTrans.translate(Eigen::Vector3f(mCarousel.pos.x(), mCarousel.pos.y(), 0.0));
carouselTrans.translate(Eigen::Vector3f(mCarousel.origin.x() * mCarousel.size.x() * -1, mCarousel.origin.y() * mCarousel.size.y() * -1, 0.0f));
Eigen::Vector2f clipPos(carouselTrans.translation().x(), carouselTrans.translation().y());
Renderer::pushClipRect(clipPos.cast<int>(), mCarousel.size.cast<int>());
Renderer::setMatrix(carouselTrans);
Renderer::drawRect(0.0, 0.0, mCarousel.size.x(), mCarousel.size.y(), mCarousel.color);
// draw logos
Eigen::Vector2f logoSpacing(0.0, 0.0); // NB: logoSpacing will include the size of the logo itself as well!
@ -416,20 +427,40 @@ void SystemView::renderCarousel(const Eigen::Affine3f& trans)
switch (mCarousel.type)
{
case VERTICAL_WHEEL:
yOff = (mCarousel.size.y() - mCarousel.logoSize.y()) / 2 - (mCamOffset * logoSpacing[1]);
if (mCarousel.logoAlignment == ALIGN_LEFT)
xOff = mCarousel.logoSize.x() / 10;
else if (mCarousel.logoAlignment == ALIGN_RIGHT)
xOff = mCarousel.size.x() - (mCarousel.logoSize.x() * 1.1);
else
xOff = (mCarousel.size.x() - mCarousel.logoSize.x()) / 2;
break;
case VERTICAL:
logoSpacing[1] = ((mCarousel.size.y() - (mCarousel.logoSize.y() * mCarousel.maxLogoCount)) / (mCarousel.maxLogoCount)) + mCarousel.logoSize.y();
xOff = mCarousel.pos.x() + (mCarousel.size.x() / 2) - (mCarousel.logoSize.x() / 2);
yOff = mCarousel.pos.y() + (mCarousel.size.y() - mCarousel.logoSize.y()) / 2 - (mCamOffset * logoSpacing[1]);
yOff = (mCarousel.size.y() - mCarousel.logoSize.y()) / 2 - (mCamOffset * logoSpacing[1]);
if (mCarousel.logoAlignment == ALIGN_LEFT)
xOff = mCarousel.logoSize.x() / 10;
else if (mCarousel.logoAlignment == ALIGN_RIGHT)
xOff = mCarousel.size.x() - (mCarousel.logoSize.x() * 1.1);
else
xOff = (mCarousel.size.x() - mCarousel.logoSize.x()) / 2;
break;
case HORIZONTAL:
default:
logoSpacing[0] = ((mCarousel.size.x() - (mCarousel.logoSize.x() * mCarousel.maxLogoCount)) / (mCarousel.maxLogoCount)) + mCarousel.logoSize.x();
xOff = mCarousel.pos.x() + (mCarousel.size.x() - mCarousel.logoSize.x()) / 2 - (mCamOffset * logoSpacing[0]);
yOff = mCarousel.pos.y() + (mCarousel.size.y() / 2) - (mCarousel.logoSize.y() / 2);
xOff = (mCarousel.size.x() - mCarousel.logoSize.x()) / 2 - (mCamOffset * logoSpacing[0]);
if (mCarousel.logoAlignment == ALIGN_TOP)
yOff = mCarousel.logoSize.y() / 10;
else if (mCarousel.logoAlignment == ALIGN_BOTTOM)
yOff = mCarousel.size.y() - (mCarousel.logoSize.y() * 1.1);
else
yOff = (mCarousel.size.y() - mCarousel.logoSize.y()) / 2;
break;
}
Eigen::Affine3f logoTrans = trans;
int center = (int)(mCamOffset);
int logoCount = std::min(mCarousel.maxLogoCount, (int)mEntries.size());
@ -444,19 +475,26 @@ void SystemView::renderCarousel(const Eigen::Affine3f& trans)
while (index >= (int)mEntries.size())
index -= mEntries.size();
logoTrans.translation() = trans.translation() + Eigen::Vector3f(i * logoSpacing[0] + xOff, i * logoSpacing [1] + yOff, 0);
Eigen::Affine3f logoTrans = carouselTrans;
logoTrans.translate(Eigen::Vector3f(i * logoSpacing[0] + xOff, i * logoSpacing[1] + yOff, 0));
if (index == mCursor) //Selected System
{
const std::shared_ptr<GuiComponent>& comp = mEntries.at(index).data.logoSelected;
comp->setOpacity(0xFF);
comp->render(logoTrans);
}
else { // not selected systems
const std::shared_ptr<GuiComponent>& comp = mEntries.at(index).data.logo;
comp->setOpacity(0x80);
comp->render(logoTrans);
float distance = i - mCamOffset;
float scale = 1.0 + ((mCarousel.logoScale - 1.0) * (1 - fabs(distance)));
scale = std::min(mCarousel.logoScale, std::max(1.0f, scale));
scale /= mCarousel.logoScale;
int opacity = round(0x80 + ((0xFF - 0x80) * (1 - fabs(distance))));
opacity = std::max((int) 0x80, opacity);
const std::shared_ptr<GuiComponent> &comp = mEntries.at(index).data.logo;
if (mCarousel.type == VERTICAL_WHEEL) {
comp->setRotationDegrees(mCarousel.logoRotation * distance);
comp->setRotationOrigin(mCarousel.logoRotationOrigin);
}
comp->setScale(scale);
comp->setOpacity(opacity);
comp->render(logoTrans);
}
Renderer::popClipRect();
}
@ -475,7 +513,7 @@ void SystemView::renderExtras(const Eigen::Affine3f& trans, float lower, float u
// Adding texture loading buffers depending on scrolling speed and status
int bufferIndex = getScrollingVelocity() + 1;
Renderer::pushClipRect(Eigen::Vector2i(0, 0), mSize.cast<int>());
Renderer::pushClipRect(Eigen::Vector2i::Zero(), mSize.cast<int>());
for (int i = extrasCenter + logoBuffersLeft[bufferIndex]; i <= extrasCenter + logoBuffersRight[bufferIndex]; i++)
{
@ -485,22 +523,26 @@ void SystemView::renderExtras(const Eigen::Affine3f& trans, float lower, float u
while (index >= (int)mEntries.size())
index -= mEntries.size();
Eigen::Affine3f extrasTrans = trans;
if (mCarousel.type == HORIZONTAL)
extrasTrans.translate(Eigen::Vector3f((i - mExtrasCamOffset) * mSize.x(), 0, 0));
else
extrasTrans.translate(Eigen::Vector3f(0, (i - mExtrasCamOffset) * mSize.y(), 0));
Renderer::pushClipRect(Eigen::Vector2i(extrasTrans.translation()[0], extrasTrans.translation()[1]), mSize.cast<int>());
SystemViewData data = mEntries.at(index).data;
for(unsigned int j = 0; j < data.backgroundExtras.size(); j++)
//Only render selected system when not showing
if (mShowing || index == mCursor)
{
GuiComponent* extra = data.backgroundExtras[j];
if (extra->getZIndex() >= lower && extra->getZIndex() < upper) {
extra->render(extrasTrans);
Eigen::Affine3f extrasTrans = trans;
if (mCarousel.type == HORIZONTAL)
extrasTrans.translate(Eigen::Vector3f((i - mExtrasCamOffset) * mSize.x(), 0, 0));
else
extrasTrans.translate(Eigen::Vector3f(0, (i - mExtrasCamOffset) * mSize.y(), 0));
Renderer::pushClipRect(Eigen::Vector2i(extrasTrans.translation()[0], extrasTrans.translation()[1]),
mSize.cast<int>());
SystemViewData data = mEntries.at(index).data;
for (unsigned int j = 0; j < data.backgroundExtras.size(); j++) {
GuiComponent *extra = data.backgroundExtras[j];
if (extra->getZIndex() >= lower && extra->getZIndex() < upper) {
extra->render(extrasTrans);
}
}
Renderer::popClipRect();
}
Renderer::popClipRect();
}
Renderer::popClipRect();
}
@ -520,12 +562,18 @@ void SystemView::getDefaultElements(void)
{
// Carousel
mCarousel.type = HORIZONTAL;
mCarousel.logoAlignment = ALIGN_CENTER;
mCarousel.size.x() = mSize.x();
mCarousel.size.y() = 0.2325f * mSize.y();
mCarousel.pos.x() = 0.0f;
mCarousel.pos.y() = 0.5f * (mSize.y() - mCarousel.size.y());
mCarousel.origin.x() = 0.0f;
mCarousel.origin.y() = 0.0f;
mCarousel.color = 0xFFFFFFD8;
mCarousel.logoScale = 1.2f;
mCarousel.logoRotation = 7.5;
mCarousel.logoRotationOrigin.x() = -5;
mCarousel.logoRotationOrigin.y() = 0.5;
mCarousel.logoSize.x() = 0.25f * mSize.x();
mCarousel.logoSize.y() = 0.155f * mSize.y();
mCarousel.maxLogoCount = 3;
@ -545,11 +593,20 @@ void SystemView::getDefaultElements(void)
void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem)
{
if (elem->has("type"))
mCarousel.type = !(elem->get<std::string>("type").compare("vertical")) ? VERTICAL : HORIZONTAL;
{
if (!(elem->get<std::string>("type").compare("vertical")))
mCarousel.type = VERTICAL;
else if (!(elem->get<std::string>("type").compare("vertical_wheel")))
mCarousel.type = VERTICAL_WHEEL;
else
mCarousel.type = HORIZONTAL;
}
if (elem->has("size"))
mCarousel.size = elem->get<Eigen::Vector2f>("size").cwiseProduct(mSize);
if (elem->has("pos"))
mCarousel.pos = elem->get<Eigen::Vector2f>("pos").cwiseProduct(mSize);
if (elem->has("origin"))
mCarousel.origin = elem->get<Eigen::Vector2f>("origin");
if (elem->has("color"))
mCarousel.color = elem->get<unsigned int>("color");
if (elem->has("logoScale"))
@ -560,4 +617,31 @@ void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem)
mCarousel.maxLogoCount = std::round(elem->get<float>("maxLogoCount"));
if (elem->has("zIndex"))
mCarousel.zIndex = elem->get<float>("zIndex");
if (elem->has("logoRotation"))
mCarousel.logoRotation = elem->get<float>("logoRotation");
if (elem->has("logoRotationOrigin"))
mCarousel.logoRotationOrigin = elem->get<Eigen::Vector2f>("logoRotationOrigin");
if (elem->has("logoAlignment"))
{
if (!(elem->get<std::string>("logoAlignment").compare("left")))
mCarousel.logoAlignment = ALIGN_LEFT;
else if (!(elem->get<std::string>("logoAlignment").compare("right")))
mCarousel.logoAlignment = ALIGN_RIGHT;
else if (!(elem->get<std::string>("logoAlignment").compare("top")))
mCarousel.logoAlignment = ALIGN_TOP;
else if (!(elem->get<std::string>("logoAlignment").compare("bottom")))
mCarousel.logoAlignment = ALIGN_BOTTOM;
else
mCarousel.logoAlignment = ALIGN_CENTER;
}
}
void SystemView::onShow()
{
mShowing = true;
}
void SystemView::onHide()
{
mShowing = false;
}

View file

@ -13,13 +13,13 @@ class AnimatedImageComponent;
enum CarouselType : unsigned int
{
HORIZONTAL = 0,
VERTICAL = 1
VERTICAL = 1,
VERTICAL_WHEEL = 2
};
struct SystemViewData
{
std::shared_ptr<GuiComponent> logo;
std::shared_ptr<GuiComponent> logoSelected;
std::vector<GuiComponent*> backgroundExtras;
};
@ -28,8 +28,11 @@ struct SystemViewCarousel
CarouselType type;
Eigen::Vector2f pos;
Eigen::Vector2f size;
Eigen::Vector2f origin;
float logoScale;
Eigen::Vector2f logoSpacing;
float logoRotation;
Eigen::Vector2f logoRotationOrigin;
Alignment logoAlignment;
unsigned int color;
int maxLogoCount; // number of logos shown on the carousel
Eigen::Vector2f logoSize;
@ -41,6 +44,9 @@ class SystemView : public IList<SystemViewData, SystemData*>
public:
SystemView(Window* window);
virtual void onShow() override;
virtual void onHide() override;
void goToSystem(SystemData* system, bool animate);
bool input(InputConfig* config, Input input) override;
@ -76,4 +82,5 @@ private:
float mExtrasFadeOpacity;
bool mViewNeedsReload;
bool mShowing;
};

View file

@ -72,6 +72,7 @@ void ViewController::goToSystemView(SystemData* system)
systemList->goToSystem(system, false);
mCurrentView = systemList;
mCurrentView->onShow();
PowerSaver::setState(true);
playViewTransition();

View file

@ -13,7 +13,7 @@ ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) : IGame
mHeaderText.setText("Logo Text");
mHeaderText.setSize(mSize.x(), 0);
mHeaderText.setPosition(0, 0);
mHeaderText.setAlignment(ALIGN_CENTER);
mHeaderText.setHorizontalAlignment(ALIGN_CENTER);
mHeaderText.setDefaultZIndex(50);
mHeaderImage.setResize(0, mSize.y() * 0.185f);

View file

@ -132,7 +132,6 @@ float GuiComponent::getScale() const
void GuiComponent::setScale(float scale)
{
mScale = scale;
onSizeChanged();
}
float GuiComponent::getZIndex() const

View file

@ -127,9 +127,13 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("type", STRING)
("size", NORMALIZED_PAIR)
("pos", NORMALIZED_PAIR)
("origin", NORMALIZED_PAIR)
("color", COLOR)
("logoScale", FLOAT)
("logoRotation", FLOAT)
("logoRotationOrigin", NORMALIZED_PAIR)
("logoSize", NORMALIZED_PAIR)
("logoAlignment", STRING)
("maxLogoCount", FLOAT)
("zIndex", FLOAT)));

View file

@ -18,7 +18,7 @@ MenuComponent::MenuComponent(Window* window, const char* title, const std::share
// set up title
mTitle = std::make_shared<TextComponent>(mWindow);
mTitle->setAlignment(ALIGN_CENTER);
mTitle->setHorizontalAlignment(ALIGN_CENTER);
mTitle->setColor(0x555555FF);
setTitle(title, titleFont);
mGrid.setEntry(mTitle, Vector2i(0, 0), false);

View file

@ -144,7 +144,7 @@ public:
auto font = Font::get(FONT_SIZE_MEDIUM, FONT_PATH_LIGHT);
mText.setFont(font);
mText.setColor(0x777777FF);
mText.setAlignment(ALIGN_CENTER);
mText.setHorizontalAlignment(ALIGN_CENTER);
addChild(&mText);
if(mMultiSelect)

View file

@ -8,13 +8,17 @@
#include "Settings.h"
TextComponent::TextComponent(Window* window) : GuiComponent(window),
mFont(Font::get(FONT_SIZE_MEDIUM)), mUppercase(false), mColor(0x000000FF), mAutoCalcExtent(true, true), mAlignment(ALIGN_LEFT), mLineSpacing(1.5f), mBgColor(0), mRenderBackground(false)
mFont(Font::get(FONT_SIZE_MEDIUM)), mUppercase(false), mColor(0x000000FF), mAutoCalcExtent(true, true),
mHorizontalAlignment(ALIGN_LEFT), mVerticalAlignment(ALIGN_CENTER), mLineSpacing(1.5f), mBgColor(0),
mRenderBackground(false)
{
}
TextComponent::TextComponent(Window* window, const std::string& text, const std::shared_ptr<Font>& font, unsigned int color, Alignment align,
Eigen::Vector3f pos, Eigen::Vector2f size, unsigned int bgcolor) : GuiComponent(window),
mFont(NULL), mUppercase(false), mColor(0x000000FF), mAutoCalcExtent(true, true), mAlignment(align), mLineSpacing(1.5f), mBgColor(0), mRenderBackground(false)
mFont(NULL), mUppercase(false), mColor(0x000000FF), mAutoCalcExtent(true, true),
mHorizontalAlignment(align), mVerticalAlignment(ALIGN_CENTER), mLineSpacing(1.5f), mBgColor(0),
mRenderBackground(false)
{
setFont(font);
setColor(color);
@ -104,7 +108,20 @@ void TextComponent::render(const Eigen::Affine3f& parentTrans)
if(mTextCache)
{
const Eigen::Vector2f& textSize = mTextCache->metrics.size;
Eigen::Vector3f off(0, (getSize().y() - textSize.y()) / 2.0f, 0);
float yOff;
switch(mVerticalAlignment)
{
case ALIGN_TOP:
yOff = 0;
break;
case ALIGN_BOTTOM:
yOff = (getSize().y() - textSize.y());
break;
case ALIGN_CENTER:
yOff = (getSize().y() - textSize.y()) / 2.0f;
break;
}
Eigen::Vector3f off(0, yOff, 0);
if(Settings::getInstance()->getBool("DebugText"))
{
@ -120,7 +137,7 @@ void TextComponent::render(const Eigen::Affine3f& parentTrans)
// draw the text area, where the text actually is going
if(Settings::getInstance()->getBool("DebugText"))
{
switch(mAlignment)
switch(mHorizontalAlignment)
{
case ALIGN_LEFT:
Renderer::drawRect(0.0f, 0.0f, mTextCache->metrics.size.x(), mTextCache->metrics.size.y(), 0x00000033);
@ -189,9 +206,9 @@ void TextComponent::onTextChanged()
text.append(abbrev);
mTextCache = std::shared_ptr<TextCache>(f->buildTextCache(text, Eigen::Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(), mAlignment, mLineSpacing));
mTextCache = std::shared_ptr<TextCache>(f->buildTextCache(text, Eigen::Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(), mHorizontalAlignment, mLineSpacing));
}else{
mTextCache = std::shared_ptr<TextCache>(f->buildTextCache(f->wrapText(text, mSize.x()), Eigen::Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(), mAlignment, mLineSpacing));
mTextCache = std::shared_ptr<TextCache>(f->buildTextCache(f->wrapText(text, mSize.x()), Eigen::Vector2f(0, 0), (mColor >> 8 << 8) | mOpacity, mSize.x(), mHorizontalAlignment, mLineSpacing));
}
}
@ -203,12 +220,17 @@ void TextComponent::onColorChanged()
}
}
void TextComponent::setAlignment(Alignment align)
void TextComponent::setHorizontalAlignment(Alignment align)
{
mAlignment = align;
mHorizontalAlignment = align;
onTextChanged();
}
void TextComponent::setVerticalAlignment(Alignment align)
{
mVerticalAlignment = align;
}
void TextComponent::setLineSpacing(float spacing)
{
mLineSpacing = spacing;
@ -248,11 +270,11 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const st
{
std::string str = elem->get<std::string>("alignment");
if(str == "left")
setAlignment(ALIGN_LEFT);
setHorizontalAlignment(ALIGN_LEFT);
else if(str == "center")
setAlignment(ALIGN_CENTER);
setHorizontalAlignment(ALIGN_CENTER);
else if(str == "right")
setAlignment(ALIGN_RIGHT);
setHorizontalAlignment(ALIGN_RIGHT);
else
LOG(LogError) << "Unknown text alignment string: " << str;
}

View file

@ -23,7 +23,8 @@ public:
void onSizeChanged() override;
void setText(const std::string& text);
void setColor(unsigned int color);
void setAlignment(Alignment align);
void setHorizontalAlignment(Alignment align);
void setVerticalAlignment(Alignment align);
void setLineSpacing(float spacing);
void setBackgroundColor(unsigned int color);
void setRenderBackground(bool render);
@ -57,7 +58,8 @@ private:
Eigen::Matrix<bool, 1, 2> mAutoCalcExtent;
std::string mText;
std::shared_ptr<TextCache> mTextCache;
Alignment mAlignment;
Alignment mHorizontalAlignment;
Alignment mVerticalAlignment;
float mLineSpacing;
};

View file

@ -25,7 +25,9 @@ enum Alignment
{
ALIGN_LEFT,
ALIGN_CENTER, // centers both horizontally and vertically
ALIGN_RIGHT
ALIGN_RIGHT,
ALIGN_TOP,
ALIGN_BOTTOM
};
//A TrueType Font renderer that uses FreeType and OpenGL.