System Carousel feature, now with only a single commit!

This commit is contained in:
D. Polders 2017-03-13 22:11:07 +01:00
parent 6cb81ab1af
commit ac5e3ad95f
9 changed files with 325 additions and 133 deletions

3
.gitignore vendored
View file

@ -34,6 +34,3 @@ Makefile
.cproject
.project
.settings/
# WinMerge
.bak

View file

@ -400,8 +400,12 @@ Reference
#### system
* `helpsystem name="help"` - ALL
- The help system style for this view.
* `carousel name="systemcarousel"` -ALL
- The system logo carousel
* `image name="logo"` - PATH
- A logo image, to be displayed in the system logo carousel.
* `text name="systemInfo"` - ALL
- Displays details of the system currently selected in the carousel.
* You can use extra elements (elements with `extra="true"`) to add your own backgrounds, etc. They will be displayed behind the carousel, and scroll relative to the carousel.
@ -468,6 +472,7 @@ Can be created as an extra.
- `w h` - works like a "text box." If `h` is non-zero and `h` <= `fontSize` (implying it should be a single line of text), text that goes beyond `w` will be truncated with an elipses (...).
* `text` - type: STRING.
* `color` - type: COLOR.
* `backgroundColor` - type: COLOR;
* `fontPath` - type: PATH.
- Path to a truetype font (.ttf).
* `fontSize` - type: FLOAT.
@ -541,6 +546,24 @@ EmulationStation borrows the concept of "nine patches" from Android (or "9-Slice
* `fontPath` - type: PATH.
* `fontSize` - type: FLOAT.
#### carousel
* `type` - type: STRING.
* Accepted values are "HORIZONTAL" or "VERTICAL". Sets the scoll direction of the carousel.
* Default is "HORIZONTAL".
* `size` - type: NORMALIZED_PAIR. Default is "1 0.2325"
* `pos` - type: NORMALIZED_PAIR. Default is "0 0.38375".
* `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.5
* `maxLogoCount` - type: FLOAT.
* Sets the number of logos to display in the carousel.
* Default is 3
The help system is a special element that displays a context-sensitive list of actions the user can take at any time. You should try and keep the position constant throughout every screen. Keep in mind the "default" settings (including position) are used whenever the user opens a menu.
[*Check out the "official" themes for some more examples!*](http://aloshi.com/emulationstation#themes)

View file

@ -9,11 +9,8 @@
#include "Settings.h"
#include "Util.h"
#define SELECTED_SCALE 1.5f
#define LOGO_PADDING ((logoSize().x() * (SELECTED_SCALE - 1)/2) + (mSize.x() * 0.06f))
#define BAND_HEIGHT (logoSize().y() * SELECTED_SCALE)
SystemView::SystemView(Window* window) : IList<SystemViewData, SystemData*>(window, LIST_SCROLL_STYLE_SLOW, LIST_ALWAYS_LOOP),
mViewNeedsReload(true),
mSystemInfo(window, "SYSTEM INFO", Font::get(FONT_SIZE_SMALL), 0x33333300, ALIGN_CENTER)
{
mCamOffset = 0;
@ -21,10 +18,6 @@ SystemView::SystemView(Window* window) : IList<SystemViewData, SystemData*>(wind
mExtrasFadeOpacity = 0.0f;
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
mSystemInfo.setSize(mSize.x(), mSystemInfo.getSize().y() * 1.333f);
mSystemInfo.setPosition(0, (mSize.y() + BAND_HEIGHT) / 2);
populate();
}
@ -36,6 +29,9 @@ void SystemView::populate()
{
const std::shared_ptr<ThemeData>& theme = (*it)->getTheme();
if(mViewNeedsReload)
getViewElements(theme);
Entry e;
e.name = (*it)->getName();
e.object = *it;
@ -43,18 +39,20 @@ void SystemView::populate()
// make logo
if(theme->getElement("system", "logo", "image"))
{
ImageComponent* logo = new ImageComponent(mWindow, false, false);
logo->setMaxSize(Eigen::Vector2f(logoSize().x(), logoSize().y()));
ImageComponent* logo = new ImageComponent(mWindow);
logo->setMaxSize(Eigen::Vector2f(mCarousel.logoSize.x(), mCarousel.logoSize.y()));
logo->applyTheme((*it)->getTheme(), "system", "logo", ThemeFlags::PATH);
logo->setPosition((logoSize().x() - logo->getSize().x()) / 2, (logoSize().y() - logo->getSize().y()) / 2); // center
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(logoSize().x() * SELECTED_SCALE, logoSize().y() * SELECTED_SCALE * 0.70f));
logoSelected->applyTheme((*it)->getTheme(), "system", "logo", ThemeFlags::PATH);
logoSelected->setPosition((logoSize().x() - logoSelected->getSize().x()) / 2,
(logoSize().y() - logoSelected->getSize().y()) / 2); // center
ImageComponent* logoSelected = new ImageComponent(mWindow);
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);
}else{
// no logo in theme; use text
TextComponent* text = new TextComponent(mWindow,
@ -62,15 +60,15 @@ void SystemView::populate()
Font::get(FONT_SIZE_LARGE),
0x000000FF,
ALIGN_CENTER);
text->setSize(logoSize());
text->setSize(mCarousel.logoSize);
e.data.logo = std::shared_ptr<GuiComponent>(text);
TextComponent* textSelected = new TextComponent(mWindow,
(*it)->getName(),
Font::get((int)(FONT_SIZE_LARGE * SELECTED_SCALE)),
Font::get((int)(FONT_SIZE_LARGE * 1.5)),
0x000000FF,
ALIGN_CENTER);
textSelected->setSize(logoSize());
textSelected->setSize(mCarousel.logoSize);
e.data.logoSelected = std::shared_ptr<GuiComponent>(textSelected);
}
@ -96,26 +94,40 @@ bool SystemView::input(InputConfig* config, Input input)
{
if(config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_r && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug"))
{
LOG(LogInfo) << " Reloading SystemList view";
// reload themes
for(auto it = mEntries.begin(); it != mEntries.end(); it++)
it->object->loadTheme();
populate();
updateHelpPrompts();
LOG(LogInfo) << " Reloading all";
ViewController::get()->reloadAll();
return true;
}
if(config->isMappedTo("left", input))
switch (mCarousel.type)
{
case VERTICAL:
if (config->isMappedTo("up", input))
{
listInput(-1);
return true;
}
if(config->isMappedTo("right", input))
if (config->isMappedTo("down", input))
{
listInput(1);
return true;
}
break;
case HORIZONTAL:
default:
if (config->isMappedTo("left", input))
{
listInput(-1);
return true;
}
if (config->isMappedTo("right", input))
{
listInput(1);
return true;
}
break;
}
if(config->isMappedTo("a", input))
{
stopScrolling();
@ -123,7 +135,10 @@ bool SystemView::input(InputConfig* config, Input input)
return true;
}
}else{
if(config->isMappedTo("left", input) || config->isMappedTo("right", input))
if(config->isMappedTo("left", input) ||
config->isMappedTo("right", input) ||
config->isMappedTo("up", input) ||
config->isMappedTo("down", input))
listInput(0);
}
@ -254,86 +269,21 @@ void SystemView::onCursorChanged(const CursorState& state)
void SystemView::render(const Eigen::Affine3f& parentTrans)
{
if(size() == 0)
return;
return; // nothing to render
Eigen::Affine3f trans = getTransform() * parentTrans;
// draw the list elements (titles, backgrounds, logos)
const float logoSizeX = logoSize().x() + LOGO_PADDING;
int logoCount = (int)(mSize.x() / logoSizeX) + 2; // how many logos we need to draw
int center = (int)(mCamOffset);
if(mEntries.size() == 1)
logoCount = 1;
// draw background extras
Eigen::Affine3f extrasTrans = trans;
int extrasCenter = (int)mExtrasCamOffset;
for(int i = extrasCenter - 1; i < extrasCenter + 2; i++)
{
int index = i;
while(index < 0)
index += mEntries.size();
while(index >= (int)mEntries.size())
index -= mEntries.size();
extrasTrans.translation() = trans.translation() + Eigen::Vector3f((i - mExtrasCamOffset) * mSize.x(), 0, 0);
Eigen::Vector2i clipRect = Eigen::Vector2i((int)((i - mExtrasCamOffset) * mSize.x()), 0);
Renderer::pushClipRect(clipRect, mSize.cast<int>());
mEntries.at(index).data.backgroundExtras->render(extrasTrans);
Renderer::popClipRect();
}
// fade extras if necessary
if(mExtrasFadeOpacity)
{
Renderer::setMatrix(trans);
Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), 0x00000000 | (unsigned char)(mExtrasFadeOpacity * 255));
}
// draw logos
float xOff = (mSize.x() - logoSize().x())/2 - (mCamOffset * logoSizeX);
float yOff = (mSize.y() - logoSize().y())/2;
// background behind the logos
Renderer::setMatrix(trans);
Renderer::drawRect(0.f, (mSize.y() - BAND_HEIGHT) / 2, mSize.x(), BAND_HEIGHT, 0xFFFFFFD8);
Eigen::Affine3f logoTrans = trans;
for(int i = center - logoCount/2; i < center + logoCount/2 + 1; i++)
{
int index = i;
while(index < 0)
index += mEntries.size();
while(index >= (int)mEntries.size())
index -= mEntries.size();
logoTrans.translation() = trans.translation() + Eigen::Vector3f(i * logoSizeX + xOff, yOff, 0);
if(index == mCursor) //scale our selection up
{
// selected
const std::shared_ptr<GuiComponent>& comp = mEntries.at(index).data.logoSelected;
comp->setOpacity(0xFF);
comp->render(logoTrans);
}else{
// not selected
const std::shared_ptr<GuiComponent>& comp = mEntries.at(index).data.logo;
comp->setOpacity(0x80);
comp->render(logoTrans);
}
}
Renderer::setMatrix(trans);
Renderer::drawRect(mSystemInfo.getPosition().x(), mSystemInfo.getPosition().y() - 1, mSize.x(), mSystemInfo.getSize().y(), 0xDDDDDD00 | (unsigned char)(mSystemInfo.getOpacity() / 255.f * 0xD8));
mSystemInfo.render(trans);
renderExtras(trans);
renderCarousel(trans);
renderInfoBar(trans);
}
std::vector<HelpPrompt> SystemView::getHelpPrompts()
{
std::vector<HelpPrompt> prompts;
if (mCarousel.type == VERTICAL)
prompts.push_back(HelpPrompt("up/down", "choose"));
else
prompts.push_back(HelpPrompt("left/right", "choose"));
prompts.push_back(HelpPrompt("a", "select"));
return prompts;
@ -345,3 +295,165 @@ HelpStyle SystemView::getHelpStyle()
style.applyTheme(mEntries.at(mCursor).object->getTheme(), "system");
return style;
}
void SystemView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
{
LOG(LogDebug) << "SystemView::onThemeChanged()";
mViewNeedsReload = true;
populate();
}
// Get the ThemeElements that make up the SystemView.
void SystemView::getViewElements(const std::shared_ptr<ThemeData>& theme)
{
LOG(LogDebug) << "SystemView::getViewElements()";
getDefaultElements();
const ThemeData::ThemeElement* carouselElem = theme->getElement("system", "systemcarousel", "carousel");
if (carouselElem)
getCarouselFromTheme(carouselElem);
const ThemeData::ThemeElement* sysInfoElem = theme->getElement("system", "systemInfo", "text");
if (sysInfoElem)
mSystemInfo.applyTheme(theme, "system", "systemInfo", ThemeFlags::ALL);
mViewNeedsReload = false;
}
// 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);
// draw logos
Eigen::Vector2f logoSpacing(0.0, 0.0); // NB: logoSpacing will include the size of the logo itself as well!
float xOff = 0.0;
float yOff = 0.0;
switch (mCarousel.type)
{
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]);
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);
break;
}
Eigen::Affine3f logoTrans = trans;
int center = (int)(mCamOffset);
int logoCount = std::min(mCarousel.maxLogoCount, (int)mEntries.size()) + 2;
for (int i = center - logoCount / 2; i < center + logoCount / 2 + 1; i++)
{
int index = i;
while (index < 0)
index += mEntries.size();
while (index >= (int)mEntries.size())
index -= mEntries.size();
logoTrans.translation() = trans.translation() + 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);
}
}
Renderer::popClipRect();
}
void SystemView::renderInfoBar(const Eigen::Affine3f& trans)
{
Renderer::setMatrix(trans);
mSystemInfo.render(trans);
}
// Draw background extras
void SystemView::renderExtras(const Eigen::Affine3f& trans)
{
Eigen::Affine3f extrasTrans = trans;
int extrasCenter = (int)mExtrasCamOffset;
for (int i = extrasCenter - 1; i < extrasCenter + 2; i++)
{
int index = i;
while (index < 0)
index += mEntries.size();
while (index >= (int)mEntries.size())
index -= mEntries.size();
extrasTrans.translation() = trans.translation() + Eigen::Vector3f((i - mExtrasCamOffset) * mSize.x(), 0, 0);
Eigen::Vector2i clipRect = Eigen::Vector2i((int)((i - mExtrasCamOffset) * mSize.x()), 0);
Renderer::pushClipRect(clipRect, mSize.cast<int>());
mEntries.at(index).data.backgroundExtras->render(extrasTrans);
Renderer::popClipRect();
}
// fade extras if necessary
if (mExtrasFadeOpacity)
{
Renderer::setMatrix(trans);
Renderer::drawRect(0.0f, 0.0f, mSize.x(), mSize.y(), 0x00000000 | (unsigned char)(mExtrasFadeOpacity * 255));
}
}
// Populate the system carousel with the legacy values
void SystemView::getDefaultElements(void)
{
// Carousel
mCarousel.type = HORIZONTAL;
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.color = 0xFFFFFFD8;
mCarousel.logoScale = 1.5f;
mCarousel.logoSize.x() = 0.25f * mSize.x();
mCarousel.logoSize.y() = 0.155f * mSize.y();
mCarousel.maxLogoCount = 3;
// System Info Bar
mSystemInfo.setSize(mSize.x(), mSystemInfo.getFont()->getLetterHeight()*2.2f);
mSystemInfo.setPosition(0, (mCarousel.pos.y() + mCarousel.size.y()));
mSystemInfo.setBackgroundColor(0xDDDDDDD8);
mSystemInfo.setFont(Font::get((int)(0.035f * mSize.y()), Font::getDefaultPath()));
mSystemInfo.setColor(0x000000FF);
}
void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem)
{
if (elem->has("type"))
mCarousel.type = !(elem->get<std::string>("type").compare("vertical")) ? VERTICAL : 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("color"))
mCarousel.color = elem->get<unsigned int>("color");
if (elem->has("logoScale"))
mCarousel.logoScale = elem->get<float>("logoScale");
if (elem->has("logoSize"))
mCarousel.logoSize = elem->get<Eigen::Vector2f>("logoSize").cwiseProduct(mSize);
if (elem->has("maxLogoCount"))
mCarousel.maxLogoCount = std::round(elem->get<float>("maxLogoCount"));
}

View file

@ -10,6 +10,12 @@
class SystemData;
class AnimatedImageComponent;
enum CarouselType : unsigned int
{
HORIZONTAL = 0,
VERTICAL = 1
};
struct SystemViewData
{
std::shared_ptr<GuiComponent> logo;
@ -17,6 +23,18 @@ struct SystemViewData
std::shared_ptr<ThemeExtras> backgroundExtras;
};
struct SystemViewCarousel
{
CarouselType type;
Eigen::Vector2f pos;
Eigen::Vector2f size;
float logoScale;
Eigen::Vector2f logoSpacing;
unsigned int color;
int maxLogoCount; // number of logos shown on the carousel
Eigen::Vector2f logoSize;
};
class SystemView : public IList<SystemViewData, SystemData*>
{
public:
@ -28,6 +46,8 @@ public:
void update(int deltaTime) override;
void render(const Eigen::Affine3f& parentTrans) override;
void onThemeChanged(const std::shared_ptr<ThemeData>& theme);
std::vector<HelpPrompt> getHelpPrompts() override;
virtual HelpStyle getHelpStyle() override;
@ -35,14 +55,22 @@ protected:
void onCursorChanged(const CursorState& state) override;
private:
inline Eigen::Vector2f logoSize() const { return Eigen::Vector2f(mSize.x() * 0.25f, mSize.y() * 0.155f); }
void populate();
void getViewElements(const std::shared_ptr<ThemeData>& theme);
void getDefaultElements(void);
void getCarouselFromTheme(const ThemeData::ThemeElement* elem);
void renderCarousel(const Eigen::Affine3f& parentTrans);
void renderExtras(const Eigen::Affine3f& parentTrans);
void renderInfoBar(const Eigen::Affine3f& trans);
SystemViewCarousel mCarousel;
TextComponent mSystemInfo;
// unit is list index
float mCamOffset;
float mExtrasCamOffset;
float mExtrasFadeOpacity;
bool mViewNeedsReload;
};

View file

@ -12,7 +12,7 @@
#include "animations/LaunchAnimation.h"
#include "animations/MoveCameraAnimation.h"
#include "animations/LambdaAnimation.h"
#include <SDL2/SDL.h>
#include <SDL.h>
ViewController* ViewController::sInstance = NULL;

View file

@ -24,7 +24,7 @@ ElementMapType makeMap(const T& mapInit)
}
std::vector<std::string> ThemeData::sSupportedViews = boost::assign::list_of("system")("basic")("detailed")("video");
std::vector<std::string> ThemeData::sSupportedFeatures = boost::assign::list_of("video");
std::vector<std::string> ThemeData::sSupportedFeatures = boost::assign::list_of("video")("carousel");
std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::map_list_of
("image", makeMap(boost::assign::map_list_of
@ -39,12 +39,14 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR)
("text", STRING)
("color", COLOR)
("backgroundColor", COLOR)
("fontPath", PATH)
("fontSize", FLOAT)
("color", COLOR)
("alignment", STRING)
("forceUppercase", BOOLEAN)
("lineSpacing", FLOAT)))
("lineSpacing", FLOAT)
("value", STRING)))
("textlist", makeMap(boost::assign::map_list_of
("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR)
@ -94,12 +96,20 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("default", PATH)
("delay", FLOAT)
("showSnapshotNoVideo", BOOLEAN)
("showSnapshotDelay", BOOLEAN)));
("showSnapshotDelay", BOOLEAN)))
("carousel", makeMap(boost::assign::map_list_of
("type", STRING)
("size", NORMALIZED_PAIR)
("pos", NORMALIZED_PAIR)
("color", COLOR)
("logoScale", FLOAT)
("logoSize", NORMALIZED_PAIR)
("maxLogoCount", FLOAT)));
namespace fs = boost::filesystem;
#define MINIMUM_THEME_FORMAT_VERSION 3
#define CURRENT_THEME_FORMAT_VERSION 3
#define CURRENT_THEME_FORMAT_VERSION 4
// helper
unsigned int getHexColor(const char* str)

View file

@ -1,4 +1,5 @@
#include "components/TextComponent.h"
#include "Renderer.h"
#include "Log.h"
#include "Window.h"
@ -7,16 +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)
mFont(Font::get(FONT_SIZE_MEDIUM)), mUppercase(false), mColor(0x000000FF), mAutoCalcExtent(true, true), mAlignment(ALIGN_LEFT), mLineSpacing(1.5f), mBgColor(NULL)
{
}
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) : GuiComponent(window),
mFont(NULL), mUppercase(false), mColor(0x000000FF), mAutoCalcExtent(true, true), mAlignment(align), mLineSpacing(1.5f)
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(NULL)
{
setFont(font);
setColor(color);
setBackgroundColor(bgcolor);
setText(text);
setPosition(pos);
setSize(size);
@ -34,19 +36,34 @@ void TextComponent::setFont(const std::shared_ptr<Font>& font)
onTextChanged();
}
// Set the color of the font/text
void TextComponent::setColor(unsigned int color)
{
mColor = color;
unsigned char opacity = mColor & 0x000000FF;
GuiComponent::setOpacity(opacity);
mColorOpacity = mColor & 0x000000FF;
onColorChanged();
}
// Set the color of the background box
void TextComponent::setBackgroundColor(unsigned int color)
{
mBgColor = color;
mBgColorOpacity = mBgColor & 0x000000FF;
}
// Scale the opacity
void TextComponent::setOpacity(unsigned char opacity)
{
mColor = (mColor & 0xFFFFFF00) | opacity;
// This method is mostly called to do fading in-out of the Text component element.
// Therefore, we assume here that opacity is a fractional value (expressed as an int 0-255),
// of the opacity originally set with setColor() or setBackgroundColor().
unsigned char o = (unsigned char)((float)opacity / 255.f * (float) mColorOpacity);
mColor = (mColor & 0xFFFFFF00) | (unsigned char) o;
unsigned char bgo = (unsigned char)((float)opacity / 255.f * (float)mBgColorOpacity);
mBgColor = (mBgColor & 0xFFFFFF00) | (unsigned char)bgo;
onColorChanged();
GuiComponent::setOpacity(opacity);
@ -73,11 +90,11 @@ void TextComponent::render(const Eigen::Affine3f& parentTrans)
{
Eigen::Affine3f trans = parentTrans * getTransform();
/*Eigen::Vector3f dim(mSize.x(), mSize.y(), 0);
dim = trans * dim - trans.translation();
Renderer::pushClipRect(Eigen::Vector2i((int)trans.translation().x(), (int)trans.translation().y()),
Eigen::Vector2i((int)(dim.x() + 0.5f), (int)(dim.y() + 0.5f)));
*/
if (mBgColor)
{
Renderer::drawRect(getPosition().x(), getPosition().y() - 1,
getSize().x(), getSize().y(), mBgColor);
}
if(mTextCache)
{
@ -111,11 +128,8 @@ void TextComponent::render(const Eigen::Affine3f& parentTrans)
break;
}
}
mFont->renderTextCache(mTextCache.get());
}
//Renderer::popClipRect();
}
void TextComponent::calculateExtent()
@ -216,9 +230,12 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const st
if(!elem)
return;
if(properties & COLOR && elem->has("color"))
if (properties & COLOR && elem->has("color"))
setColor(elem->get<unsigned int>("color"));
if (properties & COLOR && elem->has("backgroundColor"))
setBackgroundColor(elem->get<unsigned int>("backgroundColor"));
if(properties & ALIGNMENT && elem->has("alignment"))
{
std::string str = elem->get<std::string>("alignment");

View file

@ -16,7 +16,7 @@ class TextComponent : public GuiComponent
public:
TextComponent(Window* window);
TextComponent(Window* window, const std::string& text, const std::shared_ptr<Font>& font, unsigned int color = 0x000000FF, Alignment align = ALIGN_LEFT,
Eigen::Vector3f pos = Eigen::Vector3f::Zero(), Eigen::Vector2f size = Eigen::Vector2f::Zero());
Eigen::Vector3f pos = Eigen::Vector3f::Zero(), Eigen::Vector2f size = Eigen::Vector2f::Zero(), unsigned int bgcolor = 0x00000000);
void setFont(const std::shared_ptr<Font>& font);
void setUppercase(bool uppercase);
@ -25,6 +25,7 @@ public:
void setColor(unsigned int color);
void setAlignment(Alignment align);
void setLineSpacing(float spacing);
void setBackgroundColor(unsigned int color);
void render(const Eigen::Affine3f& parentTrans) override;
@ -45,6 +46,10 @@ private:
void onColorChanged();
unsigned int mColor;
unsigned int mBgColor;
unsigned char mColorOpacity;
unsigned char mBgColorOpacity;
std::shared_ptr<Font> mFont;
bool mUppercase;
Eigen::Matrix<bool, 1, 2> mAutoCalcExtent;