implement z-index support for themeing system view and gamelist views

This commit is contained in:
jrassa 2017-04-22 10:15:16 -04:00
parent 7d43c87757
commit 354d3b9dec
14 changed files with 239 additions and 84 deletions

View file

@ -265,6 +265,48 @@ Which is equivalent to:
Just remember, *this only works if the elements have the same type!* Just remember, *this only works if the elements have the same type!*
### Element rendering order with z-index
You can now change the order in which elements are rendered by setting `zIndex` values. Default values correspond to the default rendering order while allowing elements to easily be shifted without having to set `zIndex` values for every element. Elements will be rendered in order from smallest z-index to largest.
#### Defaults
##### system
* Extra Elements `extra="true"` - 10
* `carousel name="systemcarousel"` - 40
* `text name="systemInfo"` - 50
##### basic, detailed, video
* `image name="background"` - 0
* Extra Elements `extra="true"` - 10
* `textlist name="gamelist"` - 20
* Media
* `image name="md_image"` - 30
* `video name="md_video"` - 30
* `image name="md_marquee"` - 35
* Metadata - 40
* Labels
* `text name="md_lbl_rating"`
* `text name="md_lbl_releasedate"`
* `text name="md_lbl_developer"`
* `text name="md_lbl_publisher"`
* `text name="md_lbl_genre"`
* `text name="md_lbl_players"`
* `text name="md_lbl_lastplayed"`
* `text name="md_lbl_playcount"`
* Values
* `rating name="md_rating"`
* `datetime name="md_releasedate"`
* `text name="md_developer"`
* `text name="md_publisher"`
* `text name="md_genre"`
* `text name="md_players"`
* `datetime name="md_lastplayed"`
* `text name="md_playcount"`
* `text name="md_description"`
* System Logo/Text - 50
* `text name="logoText"`
* `image name="logo"`
Reference Reference
========= =========
@ -311,7 +353,7 @@ Reference
* Values * Values
* All values will follow to the right of their labels if a position isn't specified. * All values will follow to the right of their labels if a position isn't specified.
* `image name="md_image"` - POSITION | SIZE * `image name="md_image"` - POSITION | SIZE | Z_INDEX
- Path is the "image" metadata for the currently selected game. - Path is the "image" metadata for the currently selected game.
* `rating name="md_rating"` - ALL * `rating name="md_rating"` - ALL
- The "rating" metadata. - The "rating" metadata.
@ -329,7 +371,7 @@ Reference
- The "lastplayed" metadata. Displayed as a string representing the time relative to "now" (e.g. "3 hours ago"). - The "lastplayed" metadata. Displayed as a string representing the time relative to "now" (e.g. "3 hours ago").
* `text name="md_playcount"` - ALL * `text name="md_playcount"` - ALL
- The "playcount" metadata (number of times the game has been played). - The "playcount" metadata (number of times the game has been played).
* `text name="md_description"` - POSITION | SIZE | FONT_PATH | FONT_SIZE | COLOR * `text name="md_description"` - POSITION | SIZE | FONT_PATH | FONT_SIZE | COLOR | Z_INDEX
- Text is the "desc" metadata. If no `pos`/`size` is specified, will move and resize to fit under the lowest label and reach to the bottom of the screen. - Text is the "desc" metadata. If no `pos`/`size` is specified, will move and resize to fit under the lowest label and reach to the bottom of the screen.
#### video #### video
@ -358,11 +400,11 @@ Reference
* Values * Values
* All values will follow to the right of their labels if a position isn't specified. * All values will follow to the right of their labels if a position isn't specified.
* `image name="md_image"` - POSITION | SIZE * `image name="md_image"` - POSITION | SIZE | Z_INDEX
- Path is the "image" metadata for the currently selected game. - Path is the "image" metadata for the currently selected game.
* `image name="md_marquee"` - POSITION | SIZE * `image name="md_marquee"` - POSITION | SIZE | Z_INDEX
- Path is the "marquee" metadata for the currently selected game. - Path is the "marquee" metadata for the currently selected game.
* `video name="md_video"` - POSITION | SIZE * `video name="md_video"` - POSITION | SIZE | Z_INDEX
- Path is the "video" metadata for the currently selected game. - Path is the "video" metadata for the currently selected game.
* `rating name="md_rating"` - ALL * `rating name="md_rating"` - ALL
- The "rating" metadata. - The "rating" metadata.
@ -380,7 +422,7 @@ Reference
- The "lastplayed" metadata. Displayed as a string representing the time relative to "now" (e.g. "3 hours ago"). - The "lastplayed" metadata. Displayed as a string representing the time relative to "now" (e.g. "3 hours ago").
* `text name="md_playcount"` - ALL * `text name="md_playcount"` - ALL
- The "playcount" metadata (number of times the game has been played). - The "playcount" metadata (number of times the game has been played).
* `text name="md_description"` - POSITION | SIZE | FONT_PATH | FONT_SIZE | COLOR * `text name="md_description"` - POSITION | SIZE | FONT_PATH | FONT_SIZE | COLOR | Z_INDEX
- Text is the "desc" metadata. If no `pos`/`size` is specified, will move and resize to fit under the lowest label and reach to the bottom of the screen. - Text is the "desc" metadata. If no `pos`/`size` is specified, will move and resize to fit under the lowest label and reach to the bottom of the screen.
--- ---
@ -444,6 +486,8 @@ Can be created as an extra.
- If true, the image will be tiled instead of stretched to fit its size. Useful for backgrounds. - If true, the image will be tiled instead of stretched to fit its size. Useful for backgrounds.
* `color` - type: COLOR. * `color` - type: COLOR.
- Multiply each pixel's color by this color. For example, an all-white image with `<color>FF0000</color>` would become completely red. You can also control the transparency of an image with `<color>FFFFFFAA</color>` - keeping all the pixels their normal color and only affecting the alpha channel. - Multiply each pixel's color by this color. For example, an all-white image with `<color>FF0000</color>` would become completely red. You can also control the transparency of an image with `<color>FFFFFFAA</color>` - keeping all the pixels their normal color and only affecting the alpha channel.
* `zIndex` - type: FLOAT.
- z-index value for component. Components will be rendered in order of z-index value from low to high.
#### video #### video
@ -462,6 +506,8 @@ Can be created as an extra.
- If true, image will be shown when selected game does not have a video and no `default` video is configured. - If true, image will be shown when selected game does not have a video and no `default` video is configured.
* `showSnapshotDelay` - type: BOOLEAN * `showSnapshotDelay` - type: BOOLEAN
- If true, playing of video will be delayed for `delayed` seconds, when game is selected. - If true, playing of video will be delayed for `delayed` seconds, when game is selected.
* `zIndex` - type: FLOAT.
- z-index value for component. Components will be rendered in order of z-index value from low to high.
#### text #### text
@ -484,6 +530,8 @@ Can be created as an extra.
- Valid values are "left", "center", or "right". Controls alignment on the X axis. "center" will also align vertically. - Valid values are "left", "center", or "right". Controls alignment on the X axis. "center" will also align vertically.
* `forceUppercase` - type: BOOLEAN. Draw text in uppercase. * `forceUppercase` - type: BOOLEAN. Draw text in uppercase.
* `lineSpacing` - type: FLOAT. Controls the space between lines (as a multiple of font height). Default is 1.5. * `lineSpacing` - type: FLOAT. Controls the space between lines (as a multiple of font height). Default is 1.5.
* `zIndex` - type: FLOAT.
- z-index value for component. Components will be rendered in order of z-index value from low to high.
#### textlist #### textlist
@ -507,6 +555,8 @@ Can be created as an extra.
- Horizontal offset for text from the alignment point. If `alignment` is "left", offsets the text to the right. If `alignment` is "right", offsets text to the left. No effect if `alignment` is "center". Given as a percentage of the element's parent's width (same unit as `size`'s X value). - Horizontal offset for text from the alignment point. If `alignment` is "left", offsets the text to the right. If `alignment` is "right", offsets text to the left. No effect if `alignment` is "center". Given as a percentage of the element's parent's width (same unit as `size`'s X value).
* `forceUppercase` - type: BOOLEAN. Draw text in uppercase. * `forceUppercase` - type: BOOLEAN. Draw text in uppercase.
* `lineSpacing` - type: FLOAT. Controls the space between lines (as a multiple of font height). Default is 1.5. * `lineSpacing` - type: FLOAT. Controls the space between lines (as a multiple of font height). Default is 1.5.
* `zIndex` - type: FLOAT.
- z-index value for component. Components will be rendered in order of z-index value from low to high.
#### ninepatch #### ninepatch
@ -515,6 +565,8 @@ Can be created as an extra.
* `path` - type: PATH. * `path` - type: PATH.
EmulationStation borrows the concept of "nine patches" from Android (or "9-Slices"). Currently the implementation is very simple and hard-coded to only use 48x48px images (16x16px for each "patch"). Check the `data/resources` directory for some examples (button.png, frame.png). EmulationStation borrows the concept of "nine patches" from Android (or "9-Slices"). Currently the implementation is very simple and hard-coded to only use 48x48px images (16x16px for each "patch"). Check the `data/resources` directory for some examples (button.png, frame.png).
* `zIndex` - type: FLOAT.
- z-index value for component. Components will be rendered in order of z-index value from low to high.
#### rating #### rating
@ -525,6 +577,8 @@ EmulationStation borrows the concept of "nine patches" from Android (or "9-Slice
- Path to the "filled star" image. Image must be square (width equals height). - Path to the "filled star" image. Image must be square (width equals height).
* `unfilledPath` - type: PATH. * `unfilledPath` - type: PATH.
- Path to the "unfilled star" image. Image must be square (width equals height). - Path to the "unfilled star" image. Image must be square (width equals height).
* `zIndex` - type: FLOAT.
- z-index value for component. Components will be rendered in order of z-index value from low to high.
#### datetime #### datetime
@ -552,20 +606,22 @@ EmulationStation borrows the concept of "nine patches" from Android (or "9-Slice
#### carousel #### carousel
* `type` - type: STRING. * `type` - type: STRING.
* Accepted values are "HORIZONTAL" or "VERTICAL". Sets the scoll direction of the carousel. - Accepted values are "horizontal" or "vertical". Sets the scoll direction of the carousel.
* Default is "HORIZONTAL". - Default is "horizontal".
* `size` - type: NORMALIZED_PAIR. Default is "1 0.2325" * `size` - type: NORMALIZED_PAIR. Default is "1 0.2325"
* `pos` - type: NORMALIZED_PAIR. Default is "0 0.38375". * `pos` - type: NORMALIZED_PAIR. Default is "0 0.38375".
* `color` - type: COLOR. * `color` - type: COLOR.
* Controls the color of the carousel background. - Controls the color of the carousel background.
* Default is FFFFFFD8 - Default is FFFFFFD8
* `logoSize` - type: NORMALIZED_PAIR. Default is "0.25 0.155" * `logoSize` - type: NORMALIZED_PAIR. Default is "0.25 0.155"
* `logoScale` - type: FLOAT. * `logoScale` - type: FLOAT.
* Selected logo is increased in size by this scale * Selected logo is increased in size by this scale
* Default is 1.2 * Default is 1.2
* `maxLogoCount` - type: FLOAT. * `maxLogoCount` - type: FLOAT.
* Sets the number of logos to display in the carousel. - Sets the number of logos to display in the carousel.
* Default is 3 - Default is 3
* `zIndex` - type: FLOAT.
- z-index value for component. Components will be rendered in order of z-index value from low to high.
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. 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.

View file

@ -76,9 +76,18 @@ void SystemView::populate()
e.data.logoSelected = std::shared_ptr<GuiComponent>(textSelected); e.data.logoSelected = std::shared_ptr<GuiComponent>(textSelected);
} }
// delete any existing extras
for (auto extra : e.data.backgroundExtras)
delete extra;
e.data.backgroundExtras.clear();
// make background extras // make background extras
e.data.backgroundExtras = std::shared_ptr<ThemeExtras>(new ThemeExtras(mWindow)); e.data.backgroundExtras = ThemeData::makeExtras((*it)->getTheme(), "system", mWindow);
e.data.backgroundExtras->setExtras(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) {
return b->getZIndex() > a->getZIndex();
});
this->add(e); this->add(e);
} }
@ -282,9 +291,27 @@ void SystemView::render(const Eigen::Affine3f& parentTrans)
Eigen::Affine3f trans = getTransform() * parentTrans; Eigen::Affine3f trans = getTransform() * parentTrans;
renderExtras(trans); auto systemInfoZIndex = mSystemInfo.getZIndex();
renderCarousel(trans); auto minMax = std::minmax(mCarousel.zIndex, systemInfoZIndex);
renderInfoBar(trans);
renderExtras(trans, INT16_MIN, minMax.first);
renderFade(trans);
if (mCarousel.zIndex > mSystemInfo.getZIndex()) {
renderInfoBar(trans);
} else {
renderCarousel(trans);
}
renderExtras(trans, minMax.first, minMax.second);
if (mCarousel.zIndex > mSystemInfo.getZIndex()) {
renderCarousel(trans);
} else {
renderInfoBar(trans);
}
renderExtras(trans, minMax.second, INT16_MAX);
} }
std::vector<HelpPrompt> SystemView::getHelpPrompts() std::vector<HelpPrompt> SystemView::getHelpPrompts()
@ -405,7 +432,7 @@ void SystemView::renderInfoBar(const Eigen::Affine3f& trans)
} }
// Draw background extras // Draw background extras
void SystemView::renderExtras(const Eigen::Affine3f& trans) void SystemView::renderExtras(const Eigen::Affine3f& trans, float lower, float upper)
{ {
Eigen::Affine3f extrasTrans = trans; Eigen::Affine3f extrasTrans = trans;
int extrasCenter = (int)mExtrasCamOffset; int extrasCenter = (int)mExtrasCamOffset;
@ -425,10 +452,22 @@ void SystemView::renderExtras(const Eigen::Affine3f& trans)
Eigen::Vector2i clipRect = Eigen::Vector2i((int)((i - mExtrasCamOffset) * mSize.x()), 0); Eigen::Vector2i clipRect = Eigen::Vector2i((int)((i - mExtrasCamOffset) * mSize.x()), 0);
Renderer::pushClipRect(clipRect, mSize.cast<int>()); Renderer::pushClipRect(clipRect, mSize.cast<int>());
mEntries.at(index).data.backgroundExtras->render(extrasTrans);
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();
} }
}
void SystemView::renderFade(const Eigen::Affine3f& trans)
{
// fade extras if necessary // fade extras if necessary
if (mExtrasFadeOpacity) if (mExtrasFadeOpacity)
{ {
@ -451,6 +490,7 @@ void SystemView::getDefaultElements(void)
mCarousel.logoSize.x() = 0.25f * mSize.x(); mCarousel.logoSize.x() = 0.25f * mSize.x();
mCarousel.logoSize.y() = 0.155f * mSize.y(); mCarousel.logoSize.y() = 0.155f * mSize.y();
mCarousel.maxLogoCount = 3; mCarousel.maxLogoCount = 3;
mCarousel.zIndex = 40;
// System Info Bar // System Info Bar
mSystemInfo.setSize(mSize.x(), mSystemInfo.getFont()->getLetterHeight()*2.2f); mSystemInfo.setSize(mSize.x(), mSystemInfo.getFont()->getLetterHeight()*2.2f);
@ -459,6 +499,8 @@ void SystemView::getDefaultElements(void)
mSystemInfo.setRenderBackground(true); mSystemInfo.setRenderBackground(true);
mSystemInfo.setFont(Font::get((int)(0.035f * mSize.y()), Font::getDefaultPath())); mSystemInfo.setFont(Font::get((int)(0.035f * mSize.y()), Font::getDefaultPath()));
mSystemInfo.setColor(0x000000FF); mSystemInfo.setColor(0x000000FF);
mSystemInfo.setZIndex(50);
mSystemInfo.setDefaultZIndex(50);
} }
void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem) void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem)
@ -477,4 +519,6 @@ void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem)
mCarousel.logoSize = elem->get<Eigen::Vector2f>("logoSize").cwiseProduct(mSize); mCarousel.logoSize = elem->get<Eigen::Vector2f>("logoSize").cwiseProduct(mSize);
if (elem->has("maxLogoCount")) if (elem->has("maxLogoCount"))
mCarousel.maxLogoCount = std::round(elem->get<float>("maxLogoCount")); mCarousel.maxLogoCount = std::round(elem->get<float>("maxLogoCount"));
if (elem->has("zIndex"))
mCarousel.zIndex = elem->get<float>("zIndex");
} }

View file

@ -20,7 +20,7 @@ struct SystemViewData
{ {
std::shared_ptr<GuiComponent> logo; std::shared_ptr<GuiComponent> logo;
std::shared_ptr<GuiComponent> logoSelected; std::shared_ptr<GuiComponent> logoSelected;
std::shared_ptr<ThemeExtras> backgroundExtras; std::vector<GuiComponent*> backgroundExtras;
}; };
struct SystemViewCarousel struct SystemViewCarousel
@ -33,6 +33,7 @@ struct SystemViewCarousel
unsigned int color; unsigned int color;
int maxLogoCount; // number of logos shown on the carousel int maxLogoCount; // number of logos shown on the carousel
Eigen::Vector2f logoSize; Eigen::Vector2f logoSize;
float zIndex;
}; };
class SystemView : public IList<SystemViewData, SystemData*> class SystemView : public IList<SystemViewData, SystemData*>
@ -61,8 +62,10 @@ private:
void getCarouselFromTheme(const ThemeData::ThemeElement* elem); void getCarouselFromTheme(const ThemeData::ThemeElement* elem);
void renderCarousel(const Eigen::Affine3f& parentTrans); void renderCarousel(const Eigen::Affine3f& parentTrans);
void renderExtras(const Eigen::Affine3f& parentTrans); void renderExtras(const Eigen::Affine3f& parentTrans, float lower, float upper);
void renderInfoBar(const Eigen::Affine3f& trans); void renderInfoBar(const Eigen::Affine3f& trans);
void renderFade(const Eigen::Affine3f& trans);
SystemViewCarousel mCarousel; SystemViewCarousel mCarousel;
TextComponent mSystemInfo; TextComponent mSystemInfo;

View file

@ -12,6 +12,7 @@ BasicGameListView::BasicGameListView(Window* window, FileData* root)
{ {
mList.setSize(mSize.x(), mSize.y() * 0.8f); mList.setSize(mSize.x(), mSize.y() * 0.8f);
mList.setPosition(0, mSize.y() * 0.2f); mList.setPosition(0, mSize.y() * 0.2f);
mList.setDefaultZIndex(20);
addChild(&mList); addChild(&mList);
populateList(root->getChildrenListToDisplay()); populateList(root->getChildrenListToDisplay());
@ -22,6 +23,8 @@ void BasicGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
ISimpleGameListView::onThemeChanged(theme); ISimpleGameListView::onThemeChanged(theme);
using namespace ThemeFlags; using namespace ThemeFlags;
mList.applyTheme(theme, getName(), "gamelist", ALL); mList.applyTheme(theme, getName(), "gamelist", ALL);
sortChildren();
} }
void BasicGameListView::onFileChanged(FileData* file, FileChangeType change) void BasicGameListView::onFileChanged(FileData* file, FileChangeType change)

View file

@ -27,6 +27,7 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) :
mImage.setOrigin(0.5f, 0.5f); mImage.setOrigin(0.5f, 0.5f);
mImage.setPosition(mSize.x() * 0.25f, mList.getPosition().y() + mSize.y() * 0.2125f); mImage.setPosition(mSize.x() * 0.25f, mList.getPosition().y() + mSize.y() * 0.2125f);
mImage.setMaxSize(mSize.x() * (0.50f - 2*padding), mSize.y() * 0.4f); mImage.setMaxSize(mSize.x() * (0.50f - 2*padding), mSize.y() * 0.4f);
mImage.setDefaultZIndex(30);
addChild(&mImage); addChild(&mImage);
// metadata labels + values // metadata labels + values
@ -59,6 +60,7 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) :
mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f); mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f);
mDescContainer.setSize(mSize.x() * (0.50f - 2*padding), mSize.y() - mDescContainer.getPosition().y()); mDescContainer.setSize(mSize.x() * (0.50f - 2*padding), mSize.y() - mDescContainer.getPosition().y());
mDescContainer.setAutoScroll(true); mDescContainer.setAutoScroll(true);
mDescContainer.setDefaultZIndex(40);
addChild(&mDescContainer); addChild(&mDescContainer);
mDescription.setFont(Font::get(FONT_SIZE_SMALL)); mDescription.setFont(Font::get(FONT_SIZE_SMALL));
@ -76,7 +78,7 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& them
BasicGameListView::onThemeChanged(theme); BasicGameListView::onThemeChanged(theme);
using namespace ThemeFlags; using namespace ThemeFlags;
mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE); mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE | Z_INDEX);
initMDLabels(); initMDLabels();
std::vector<TextComponent*> labels = getMDLabels(); std::vector<TextComponent*> labels = getMDLabels();
@ -105,9 +107,11 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& them
values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT); values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT);
} }
mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE); mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE | Z_INDEX);
mDescription.setSize(mDescContainer.getSize().x(), 0); mDescription.setSize(mDescContainer.getSize().x(), 0);
mDescription.applyTheme(theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | TEXT)); mDescription.applyTheme(theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | TEXT));
sortChildren();
} }
void DetailedGameListView::initMDLabels() void DetailedGameListView::initMDLabels()

View file

@ -6,22 +6,24 @@
#include "Settings.h" #include "Settings.h"
ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) : IGameListView(window, root), ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) : IGameListView(window, root),
mHeaderText(window), mHeaderImage(window), mBackground(window), mThemeExtras(window) mHeaderText(window), mHeaderImage(window), mBackground(window)
{ {
mHeaderText.setText("Logo Text"); mHeaderText.setText("Logo Text");
mHeaderText.setSize(mSize.x(), 0); mHeaderText.setSize(mSize.x(), 0);
mHeaderText.setPosition(0, 0); mHeaderText.setPosition(0, 0);
mHeaderText.setAlignment(ALIGN_CENTER); mHeaderText.setAlignment(ALIGN_CENTER);
mHeaderText.setDefaultZIndex(50);
mHeaderImage.setResize(0, mSize.y() * 0.185f); mHeaderImage.setResize(0, mSize.y() * 0.185f);
mHeaderImage.setOrigin(0.5f, 0.0f); mHeaderImage.setOrigin(0.5f, 0.0f);
mHeaderImage.setPosition(mSize.x() / 2, 0); mHeaderImage.setPosition(mSize.x() / 2, 0);
mHeaderImage.setDefaultZIndex(50);
mBackground.setResize(mSize.x(), mSize.y()); mBackground.setResize(mSize.x(), mSize.y());
mBackground.setDefaultZIndex(0);
addChild(&mHeaderText); addChild(&mHeaderText);
addChild(&mBackground); addChild(&mBackground);
addChild(&mThemeExtras);
} }
void ISimpleGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme) void ISimpleGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
@ -30,7 +32,21 @@ void ISimpleGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme
mBackground.applyTheme(theme, getName(), "background", ALL); mBackground.applyTheme(theme, getName(), "background", ALL);
mHeaderImage.applyTheme(theme, getName(), "logo", ALL); mHeaderImage.applyTheme(theme, getName(), "logo", ALL);
mHeaderText.applyTheme(theme, getName(), "logoText", ALL); mHeaderText.applyTheme(theme, getName(), "logoText", ALL);
mThemeExtras.setExtras(ThemeData::makeExtras(theme, getName(), mWindow));
// Remove old theme extras
for (auto extra : mThemeExtras)
{
removeChild(extra);
delete extra;
}
mThemeExtras.clear();
// Add new theme extras
mThemeExtras = ThemeData::makeExtras(theme, getName(), mWindow);
for (auto extra : mThemeExtras)
{
addChild(extra);
}
if(mHeaderImage.hasImage()) if(mHeaderImage.hasImage())
{ {

View file

@ -31,8 +31,8 @@ protected:
TextComponent mHeaderText; TextComponent mHeaderText;
ImageComponent mHeaderImage; ImageComponent mHeaderImage;
ImageComponent mBackground; ImageComponent mBackground;
ThemeExtras mThemeExtras; std::vector<GuiComponent*> mThemeExtras;
std::stack<FileData*> mCursorStack; std::stack<FileData*> mCursorStack;
}; };

View file

@ -30,6 +30,7 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
mMarquee.setOrigin(0.5f, 0.5f); mMarquee.setOrigin(0.5f, 0.5f);
mMarquee.setPosition(mSize.x() * 0.25f, mSize.y() * 0.10f); mMarquee.setPosition(mSize.x() * 0.25f, mSize.y() * 0.10f);
mMarquee.setMaxSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.18f); mMarquee.setMaxSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.18f);
mMarquee.setDefaultZIndex(35);
addChild(&mMarquee); addChild(&mMarquee);
// Image // Image
@ -37,25 +38,16 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
// Default to off the screen // Default to off the screen
mImage.setPosition(2.0f, 2.0f); mImage.setPosition(2.0f, 2.0f);
mImage.setMaxSize(1.0f, 1.0f); mImage.setMaxSize(1.0f, 1.0f);
mImage.setDefaultZIndex(30);
addChild(&mImage); addChild(&mImage);
// video // video
mVideo.setOrigin(0.5f, 0.5f); mVideo.setOrigin(0.5f, 0.5f);
mVideo.setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f); mVideo.setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f);
mVideo.setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f); mVideo.setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f);
mVideo.setDefaultZIndex(30);
addChild(&mVideo); addChild(&mVideo);
// We want the video to be in front of the background but behind any 'extra' images
for (std::vector<GuiComponent*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
{
if (*it == &mThemeExtras)
{
mChildren.insert(it, &mVideo);
mChildren.pop_back();
break;
}
}
// metadata labels + values // metadata labels + values
mLblRating.setText("Rating: "); mLblRating.setText("Rating: ");
addChild(&mLblRating); addChild(&mLblRating);
@ -86,6 +78,7 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f); mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f);
mDescContainer.setSize(mSize.x() * (0.50f - 2*padding), mSize.y() - mDescContainer.getPosition().y()); mDescContainer.setSize(mSize.x() * (0.50f - 2*padding), mSize.y() - mDescContainer.getPosition().y());
mDescContainer.setAutoScroll(true); mDescContainer.setAutoScroll(true);
mDescContainer.setDefaultZIndex(40);
addChild(&mDescContainer); addChild(&mDescContainer);
mDescription.setFont(Font::get(FONT_SIZE_SMALL)); mDescription.setFont(Font::get(FONT_SIZE_SMALL));
@ -105,9 +98,9 @@ void VideoGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
BasicGameListView::onThemeChanged(theme); BasicGameListView::onThemeChanged(theme);
using namespace ThemeFlags; using namespace ThemeFlags;
mMarquee.applyTheme(theme, getName(), "md_marquee", POSITION | ThemeFlags::SIZE); mMarquee.applyTheme(theme, getName(), "md_marquee", POSITION | ThemeFlags::SIZE | Z_INDEX);
mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE); mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE | Z_INDEX);
mVideo.applyTheme(theme, getName(), "md_video", POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY); mVideo.applyTheme(theme, getName(), "md_video", POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY | Z_INDEX);
initMDLabels(); initMDLabels();
std::vector<TextComponent*> labels = getMDLabels(); std::vector<TextComponent*> labels = getMDLabels();
@ -136,9 +129,11 @@ void VideoGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT); values[i]->applyTheme(theme, getName(), valElements[i], ALL ^ ThemeFlags::TEXT);
} }
mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE); mDescContainer.applyTheme(theme, getName(), "md_description", POSITION | ThemeFlags::SIZE | Z_INDEX);
mDescription.setSize(mDescContainer.getSize().x(), 0); mDescription.setSize(mDescContainer.getSize().x(), 0);
mDescription.applyTheme(theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | TEXT)); mDescription.applyTheme(theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | TEXT));
sortChildren();
} }
void VideoGameListView::initMDLabels() void VideoGameListView::initMDLabels()
@ -170,6 +165,7 @@ void VideoGameListView::initMDLabels()
components[i]->setFont(Font::get(FONT_SIZE_SMALL)); components[i]->setFont(Font::get(FONT_SIZE_SMALL));
components[i]->setPosition(pos); components[i]->setPosition(pos);
components[i]->setDefaultZIndex(40);
} }
} }
@ -198,6 +194,7 @@ void VideoGameListView::initMDValues()
const float heightDiff = (labels[i]->getSize().y() - values[i]->getSize().y()) / 2; const float heightDiff = (labels[i]->getSize().y() - values[i]->getSize().y()) / 2;
values[i]->setPosition(labels[i]->getPosition() + Vector3f(labels[i]->getSize().x(), heightDiff, 0)); values[i]->setPosition(labels[i]->getPosition() + Vector3f(labels[i]->getSize().x(), heightDiff, 0));
values[i]->setSize(colSize - labels[i]->getSize().x(), values[i]->getSize().y()); values[i]->setSize(colSize - labels[i]->getSize().x(), values[i]->getSize().y());
values[i]->setDefaultZIndex(40);
float testBot = values[i]->getPosition().y() + values[i]->getSize().y(); float testBot = values[i]->getPosition().y() + values[i]->getSize().y();
if(testBot > bottom) if(testBot > bottom)

View file

@ -105,6 +105,26 @@ void GuiComponent::setSize(float w, float h)
onSizeChanged(); onSizeChanged();
} }
float GuiComponent::getZIndex() const
{
return mZIndex;
}
void GuiComponent::setZIndex(float z)
{
mZIndex = z;
}
float GuiComponent::getDefaultZIndex() const
{
return mDefaultZIndex;
}
void GuiComponent::setDefaultZIndex(float z)
{
mDefaultZIndex = z;
}
//Children stuff. //Children stuff.
void GuiComponent::addChild(GuiComponent* cmp) void GuiComponent::addChild(GuiComponent* cmp)
{ {
@ -143,6 +163,13 @@ void GuiComponent::clearChildren()
mChildren.clear(); mChildren.clear();
} }
void GuiComponent::sortChildren()
{
std:stable_sort(mChildren.begin(), mChildren.end(), [](GuiComponent* a, GuiComponent* b) {
return b->getZIndex() > a->getZIndex();
});
}
unsigned int GuiComponent::getChildCount() const unsigned int GuiComponent::getChildCount() const
{ {
return mChildren.size(); return mChildren.size();
@ -320,6 +347,11 @@ void GuiComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std
if(properties & ThemeFlags::SIZE && elem->has("size")) if(properties & ThemeFlags::SIZE && elem->has("size"))
setSize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale)); setSize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
if(properties & ThemeFlags::Z_INDEX && elem->has("zIndex"))
setZIndex(elem->get<float>("zIndex"));
else
setZIndex(getDefaultZIndex());
} }
void GuiComponent::updateHelpPrompts() void GuiComponent::updateHelpPrompts()

View file

@ -46,12 +46,19 @@ public:
void setSize(float w, float h); void setSize(float w, float h);
virtual void onSizeChanged() {}; virtual void onSizeChanged() {};
float getZIndex() const;
void setZIndex(float zIndex);
float getDefaultZIndex() const;
void setDefaultZIndex(float zIndex);
void setParent(GuiComponent* parent); void setParent(GuiComponent* parent);
GuiComponent* getParent() const; GuiComponent* getParent() const;
void addChild(GuiComponent* cmp); void addChild(GuiComponent* cmp);
void removeChild(GuiComponent* cmp); void removeChild(GuiComponent* cmp);
void clearChildren(); void clearChildren();
void sortChildren();
unsigned int getChildCount() const; unsigned int getChildCount() const;
GuiComponent* getChild(unsigned int i) const; GuiComponent* getChild(unsigned int i) const;
@ -110,6 +117,9 @@ protected:
Eigen::Vector3f mPosition; Eigen::Vector3f mPosition;
Eigen::Vector2f mSize; Eigen::Vector2f mSize;
float mDefaultZIndex = 0;
float mZIndex = 0;
bool mIsProcessing; bool mIsProcessing;
public: public:

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::sSupportedViews = boost::assign::list_of("system")("basic")("detailed")("video");
std::vector<std::string> ThemeData::sSupportedFeatures = boost::assign::list_of("video")("carousel"); std::vector<std::string> ThemeData::sSupportedFeatures = boost::assign::list_of("video")("carousel")("z-index");
std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::map_list_of std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::map_list_of
("image", makeMap(boost::assign::map_list_of ("image", makeMap(boost::assign::map_list_of
@ -34,7 +34,8 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("origin", NORMALIZED_PAIR) ("origin", NORMALIZED_PAIR)
("path", PATH) ("path", PATH)
("tile", BOOLEAN) ("tile", BOOLEAN)
("color", COLOR))) ("color", COLOR)
("zIndex", FLOAT)))
("text", makeMap(boost::assign::map_list_of ("text", makeMap(boost::assign::map_list_of
("pos", NORMALIZED_PAIR) ("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR)
@ -46,7 +47,8 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("alignment", STRING) ("alignment", STRING)
("forceUppercase", BOOLEAN) ("forceUppercase", BOOLEAN)
("lineSpacing", FLOAT) ("lineSpacing", FLOAT)
("value", STRING))) ("value", STRING)
("zIndex", FLOAT)))
("textlist", makeMap(boost::assign::map_list_of ("textlist", makeMap(boost::assign::map_list_of
("pos", NORMALIZED_PAIR) ("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR)
@ -60,26 +62,31 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("alignment", STRING) ("alignment", STRING)
("horizontalMargin", FLOAT) ("horizontalMargin", FLOAT)
("forceUppercase", BOOLEAN) ("forceUppercase", BOOLEAN)
("lineSpacing", FLOAT))) ("lineSpacing", FLOAT)
("zIndex", FLOAT)))
("container", makeMap(boost::assign::map_list_of ("container", makeMap(boost::assign::map_list_of
("pos", NORMALIZED_PAIR) ("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR))) ("size", NORMALIZED_PAIR)
("zIndex", FLOAT)))
("ninepatch", makeMap(boost::assign::map_list_of ("ninepatch", makeMap(boost::assign::map_list_of
("pos", NORMALIZED_PAIR) ("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR)
("path", PATH))) ("path", PATH)
("zIndex", FLOAT)))
("datetime", makeMap(boost::assign::map_list_of ("datetime", makeMap(boost::assign::map_list_of
("pos", NORMALIZED_PAIR) ("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR)
("color", COLOR) ("color", COLOR)
("fontPath", PATH) ("fontPath", PATH)
("fontSize", FLOAT) ("fontSize", FLOAT)
("forceUppercase", BOOLEAN))) ("forceUppercase", BOOLEAN)
("zIndex", FLOAT)))
("rating", makeMap(boost::assign::map_list_of ("rating", makeMap(boost::assign::map_list_of
("pos", NORMALIZED_PAIR) ("pos", NORMALIZED_PAIR)
("size", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR)
("filledPath", PATH) ("filledPath", PATH)
("unfilledPath", PATH))) ("unfilledPath", PATH)
("zIndex", FLOAT)))
("sound", makeMap(boost::assign::map_list_of ("sound", makeMap(boost::assign::map_list_of
("path", PATH))) ("path", PATH)))
("helpsystem", makeMap(boost::assign::map_list_of ("helpsystem", makeMap(boost::assign::map_list_of
@ -95,6 +102,7 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("origin", NORMALIZED_PAIR) ("origin", NORMALIZED_PAIR)
("default", PATH) ("default", PATH)
("delay", FLOAT) ("delay", FLOAT)
("zIndex", FLOAT)
("showSnapshotNoVideo", BOOLEAN) ("showSnapshotNoVideo", BOOLEAN)
("showSnapshotDelay", BOOLEAN))) ("showSnapshotDelay", BOOLEAN)))
("carousel", makeMap(boost::assign::map_list_of ("carousel", makeMap(boost::assign::map_list_of
@ -104,7 +112,8 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign::
("color", COLOR) ("color", COLOR)
("logoScale", FLOAT) ("logoScale", FLOAT)
("logoSize", NORMALIZED_PAIR) ("logoSize", NORMALIZED_PAIR)
("maxLogoCount", FLOAT))); ("maxLogoCount", FLOAT)
("zIndex", FLOAT)));
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
@ -450,6 +459,7 @@ std::vector<GuiComponent*> ThemeData::makeExtras(const std::shared_ptr<ThemeData
else if(t == "text") else if(t == "text")
comp = new TextComponent(window); comp = new TextComponent(window);
comp->setDefaultZIndex(10);
comp->applyTheme(theme, view, *it, ThemeFlags::ALL); comp->applyTheme(theme, view, *it, ThemeFlags::ALL);
comps.push_back(comp); comps.push_back(comp);
} }
@ -458,24 +468,6 @@ std::vector<GuiComponent*> ThemeData::makeExtras(const std::shared_ptr<ThemeData
return comps; return comps;
} }
void ThemeExtras::setExtras(const std::vector<GuiComponent*>& extras)
{
// delete old extras (if any)
for(auto it = mExtras.begin(); it != mExtras.end(); it++)
delete *it;
mExtras = extras;
for(auto it = mExtras.begin(); it != mExtras.end(); it++)
addChild(*it);
}
ThemeExtras::~ThemeExtras()
{
for(auto it = mExtras.begin(); it != mExtras.end(); it++)
delete *it;
}
std::map<std::string, ThemeSet> ThemeData::getThemeSets() std::map<std::string, ThemeSet> ThemeData::getThemeSets()
{ {
std::map<std::string, ThemeSet> sets; std::map<std::string, ThemeSet> sets;

View file

@ -38,6 +38,7 @@ namespace ThemeFlags
FORCE_UPPERCASE = 1024, FORCE_UPPERCASE = 1024,
LINE_SPACING = 2048, LINE_SPACING = 2048,
DELAY = 4096, DELAY = 4096,
Z_INDEX = 8192,
ALL = 0xFFFFFFFF ALL = 0xFFFFFFFF
}; };
@ -71,19 +72,6 @@ ThemeException& operator<<(ThemeException& e, T appendMsg)
return e; return e;
} }
class ThemeExtras : public GuiComponent
{
public:
ThemeExtras(Window* window) : GuiComponent(window) {};
virtual ~ThemeExtras();
// will take ownership of the components within extras (delete them in destructor or when setExtras is called again)
void setExtras(const std::vector<GuiComponent*>& extras);
private:
std::vector<GuiComponent*> mExtras;
};
struct ThemeSet struct ThemeSet
{ {
boost::filesystem::path path; boost::filesystem::path path;

View file

@ -362,6 +362,11 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
if(properties & COLOR && elem->has("color")) if(properties & COLOR && elem->has("color"))
setColorShift(elem->get<unsigned int>("color")); setColorShift(elem->get<unsigned int>("color"));
if(properties & ThemeFlags::Z_INDEX && elem->has("zIndex"))
setZIndex(elem->get<float>("zIndex"));
else
setZIndex(getDefaultZIndex());
} }
std::vector<HelpPrompt> ImageComponent::getHelpPrompts() std::vector<HelpPrompt> ImageComponent::getHelpPrompts()

View file

@ -347,6 +347,11 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
if (elem->has("showSnapshotDelay")) if (elem->has("showSnapshotDelay"))
mConfig.showSnapshotDelay = elem->get<bool>("showSnapshotDelay"); mConfig.showSnapshotDelay = elem->get<bool>("showSnapshotDelay");
if(properties & ThemeFlags::Z_INDEX && elem->has("zIndex"))
setZIndex(elem->get<float>("zIndex"));
else
setZIndex(getDefaultZIndex());
} }
std::vector<HelpPrompt> VideoComponent::getHelpPrompts() std::vector<HelpPrompt> VideoComponent::getHelpPrompts()