diff --git a/THEMES.md b/THEMES.md index 1c42102c3..6b7db4714 100644 --- a/THEMES.md +++ b/THEMES.md @@ -265,6 +265,48 @@ Which is equivalent to: 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 ========= @@ -311,7 +353,7 @@ Reference * Values * 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. * `rating name="md_rating"` - ALL - 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"). * `text name="md_playcount"` - ALL - 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. #### video @@ -358,11 +400,11 @@ Reference * Values * 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. - * `image name="md_marquee"` - POSITION | SIZE + * `image name="md_marquee"` - POSITION | SIZE | Z_INDEX - 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. * `rating name="md_rating"` - ALL - 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"). * `text name="md_playcount"` - ALL - 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. --- @@ -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. * `color` - type: COLOR. - Multiply each pixel's color by this color. For example, an all-white image with `FF0000` would become completely red. You can also control the transparency of an image with `FFFFFFAA` - 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 @@ -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. * `showSnapshotDelay` - type: BOOLEAN - 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 @@ -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. * `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. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. #### 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). * `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. +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. #### ninepatch @@ -515,6 +565,8 @@ Can be created as an extra. * `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). +* `zIndex` - type: FLOAT. + - z-index value for component. Components will be rendered in order of z-index value from low to high. #### 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). * `unfilledPath` - type: PATH. - 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 @@ -552,20 +606,22 @@ 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". + - 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 + - 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 * `maxLogoCount` - type: FLOAT. - * Sets the number of logos to display in the carousel. - * Default is 3 + - Sets the number of logos to display in the carousel. + - 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. diff --git a/es-app/src/views/SystemView.cpp b/es-app/src/views/SystemView.cpp index 06668796a..0b2a950c2 100644 --- a/es-app/src/views/SystemView.cpp +++ b/es-app/src/views/SystemView.cpp @@ -76,9 +76,18 @@ void SystemView::populate() e.data.logoSelected = std::shared_ptr(textSelected); } + // delete any existing extras + for (auto extra : e.data.backgroundExtras) + delete extra; + e.data.backgroundExtras.clear(); + // make background extras - e.data.backgroundExtras = std::shared_ptr(new ThemeExtras(mWindow)); - e.data.backgroundExtras->setExtras(ThemeData::makeExtras((*it)->getTheme(), "system", mWindow)); + 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) { + return b->getZIndex() > a->getZIndex(); + }); this->add(e); } @@ -282,9 +291,27 @@ void SystemView::render(const Eigen::Affine3f& parentTrans) Eigen::Affine3f trans = getTransform() * parentTrans; - renderExtras(trans); - renderCarousel(trans); - renderInfoBar(trans); + auto systemInfoZIndex = mSystemInfo.getZIndex(); + auto minMax = std::minmax(mCarousel.zIndex, systemInfoZIndex); + + 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 SystemView::getHelpPrompts() @@ -405,7 +432,7 @@ void SystemView::renderInfoBar(const Eigen::Affine3f& trans) } // 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; 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); Renderer::pushClipRect(clipRect, mSize.cast()); - 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(); } +} +void SystemView::renderFade(const Eigen::Affine3f& trans) +{ // fade extras if necessary if (mExtrasFadeOpacity) { @@ -451,6 +490,7 @@ void SystemView::getDefaultElements(void) mCarousel.logoSize.x() = 0.25f * mSize.x(); mCarousel.logoSize.y() = 0.155f * mSize.y(); mCarousel.maxLogoCount = 3; + mCarousel.zIndex = 40; // System Info Bar mSystemInfo.setSize(mSize.x(), mSystemInfo.getFont()->getLetterHeight()*2.2f); @@ -459,6 +499,8 @@ void SystemView::getDefaultElements(void) mSystemInfo.setRenderBackground(true); mSystemInfo.setFont(Font::get((int)(0.035f * mSize.y()), Font::getDefaultPath())); mSystemInfo.setColor(0x000000FF); + mSystemInfo.setZIndex(50); + mSystemInfo.setDefaultZIndex(50); } void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem) @@ -477,4 +519,6 @@ void SystemView::getCarouselFromTheme(const ThemeData::ThemeElement* elem) mCarousel.logoSize = elem->get("logoSize").cwiseProduct(mSize); if (elem->has("maxLogoCount")) mCarousel.maxLogoCount = std::round(elem->get("maxLogoCount")); + if (elem->has("zIndex")) + mCarousel.zIndex = elem->get("zIndex"); } diff --git a/es-app/src/views/SystemView.h b/es-app/src/views/SystemView.h index 209c4b0e9..c766c5902 100644 --- a/es-app/src/views/SystemView.h +++ b/es-app/src/views/SystemView.h @@ -20,7 +20,7 @@ struct SystemViewData { std::shared_ptr logo; std::shared_ptr logoSelected; - std::shared_ptr backgroundExtras; + std::vector backgroundExtras; }; struct SystemViewCarousel @@ -33,6 +33,7 @@ struct SystemViewCarousel unsigned int color; int maxLogoCount; // number of logos shown on the carousel Eigen::Vector2f logoSize; + float zIndex; }; class SystemView : public IList @@ -61,8 +62,10 @@ private: void getCarouselFromTheme(const ThemeData::ThemeElement* elem); 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 renderFade(const Eigen::Affine3f& trans); + SystemViewCarousel mCarousel; TextComponent mSystemInfo; diff --git a/es-app/src/views/gamelist/BasicGameListView.cpp b/es-app/src/views/gamelist/BasicGameListView.cpp index 54a8742c7..d7fe8ec2b 100644 --- a/es-app/src/views/gamelist/BasicGameListView.cpp +++ b/es-app/src/views/gamelist/BasicGameListView.cpp @@ -12,6 +12,7 @@ BasicGameListView::BasicGameListView(Window* window, FileData* root) { mList.setSize(mSize.x(), mSize.y() * 0.8f); mList.setPosition(0, mSize.y() * 0.2f); + mList.setDefaultZIndex(20); addChild(&mList); populateList(root->getChildrenListToDisplay()); @@ -22,6 +23,8 @@ void BasicGameListView::onThemeChanged(const std::shared_ptr& theme) ISimpleGameListView::onThemeChanged(theme); using namespace ThemeFlags; mList.applyTheme(theme, getName(), "gamelist", ALL); + + sortChildren(); } void BasicGameListView::onFileChanged(FileData* file, FileChangeType change) diff --git a/es-app/src/views/gamelist/DetailedGameListView.cpp b/es-app/src/views/gamelist/DetailedGameListView.cpp index d042352bc..460f60827 100644 --- a/es-app/src/views/gamelist/DetailedGameListView.cpp +++ b/es-app/src/views/gamelist/DetailedGameListView.cpp @@ -27,6 +27,7 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) : mImage.setOrigin(0.5f, 0.5f); 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.setDefaultZIndex(30); addChild(&mImage); // metadata labels + values @@ -59,6 +60,7 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) : mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f); mDescContainer.setSize(mSize.x() * (0.50f - 2*padding), mSize.y() - mDescContainer.getPosition().y()); mDescContainer.setAutoScroll(true); + mDescContainer.setDefaultZIndex(40); addChild(&mDescContainer); mDescription.setFont(Font::get(FONT_SIZE_SMALL)); @@ -76,7 +78,7 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr& them BasicGameListView::onThemeChanged(theme); using namespace ThemeFlags; - mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE); + mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE | Z_INDEX); initMDLabels(); std::vector labels = getMDLabels(); @@ -105,9 +107,11 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr& them 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.applyTheme(theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | TEXT)); + + sortChildren(); } void DetailedGameListView::initMDLabels() diff --git a/es-app/src/views/gamelist/ISimpleGameListView.cpp b/es-app/src/views/gamelist/ISimpleGameListView.cpp index a0029361f..617b61350 100644 --- a/es-app/src/views/gamelist/ISimpleGameListView.cpp +++ b/es-app/src/views/gamelist/ISimpleGameListView.cpp @@ -6,22 +6,24 @@ #include "Settings.h" 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.setSize(mSize.x(), 0); mHeaderText.setPosition(0, 0); mHeaderText.setAlignment(ALIGN_CENTER); - + mHeaderText.setDefaultZIndex(50); + mHeaderImage.setResize(0, mSize.y() * 0.185f); mHeaderImage.setOrigin(0.5f, 0.0f); mHeaderImage.setPosition(mSize.x() / 2, 0); + mHeaderImage.setDefaultZIndex(50); mBackground.setResize(mSize.x(), mSize.y()); + mBackground.setDefaultZIndex(0); addChild(&mHeaderText); addChild(&mBackground); - addChild(&mThemeExtras); } void ISimpleGameListView::onThemeChanged(const std::shared_ptr& theme) @@ -30,7 +32,21 @@ void ISimpleGameListView::onThemeChanged(const std::shared_ptr& theme mBackground.applyTheme(theme, getName(), "background", ALL); mHeaderImage.applyTheme(theme, getName(), "logo", 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()) { diff --git a/es-app/src/views/gamelist/ISimpleGameListView.h b/es-app/src/views/gamelist/ISimpleGameListView.h index 9022cde73..ff405b42a 100644 --- a/es-app/src/views/gamelist/ISimpleGameListView.h +++ b/es-app/src/views/gamelist/ISimpleGameListView.h @@ -31,8 +31,8 @@ protected: TextComponent mHeaderText; ImageComponent mHeaderImage; ImageComponent mBackground; - - ThemeExtras mThemeExtras; + + std::vector mThemeExtras; std::stack mCursorStack; }; diff --git a/es-app/src/views/gamelist/VideoGameListView.cpp b/es-app/src/views/gamelist/VideoGameListView.cpp index eeefe643d..620c288f1 100644 --- a/es-app/src/views/gamelist/VideoGameListView.cpp +++ b/es-app/src/views/gamelist/VideoGameListView.cpp @@ -30,6 +30,7 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) : mMarquee.setOrigin(0.5f, 0.5f); mMarquee.setPosition(mSize.x() * 0.25f, mSize.y() * 0.10f); mMarquee.setMaxSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.18f); + mMarquee.setDefaultZIndex(35); addChild(&mMarquee); // Image @@ -37,25 +38,16 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) : // Default to off the screen mImage.setPosition(2.0f, 2.0f); mImage.setMaxSize(1.0f, 1.0f); + mImage.setDefaultZIndex(30); addChild(&mImage); // video mVideo.setOrigin(0.5f, 0.5f); mVideo.setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f); mVideo.setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f); + mVideo.setDefaultZIndex(30); addChild(&mVideo); - // We want the video to be in front of the background but behind any 'extra' images - for (std::vector::iterator it = mChildren.begin(); it != mChildren.end(); ++it) - { - if (*it == &mThemeExtras) - { - mChildren.insert(it, &mVideo); - mChildren.pop_back(); - break; - } - } - // metadata labels + values mLblRating.setText("Rating: "); addChild(&mLblRating); @@ -86,6 +78,7 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) : mDescContainer.setPosition(mSize.x() * padding, mSize.y() * 0.65f); mDescContainer.setSize(mSize.x() * (0.50f - 2*padding), mSize.y() - mDescContainer.getPosition().y()); mDescContainer.setAutoScroll(true); + mDescContainer.setDefaultZIndex(40); addChild(&mDescContainer); mDescription.setFont(Font::get(FONT_SIZE_SMALL)); @@ -105,9 +98,9 @@ void VideoGameListView::onThemeChanged(const std::shared_ptr& theme) BasicGameListView::onThemeChanged(theme); using namespace ThemeFlags; - mMarquee.applyTheme(theme, getName(), "md_marquee", POSITION | ThemeFlags::SIZE); - mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE); - mVideo.applyTheme(theme, getName(), "md_video", POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY); + mMarquee.applyTheme(theme, getName(), "md_marquee", POSITION | ThemeFlags::SIZE | Z_INDEX); + mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE | Z_INDEX); + mVideo.applyTheme(theme, getName(), "md_video", POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY | Z_INDEX); initMDLabels(); std::vector labels = getMDLabels(); @@ -136,9 +129,11 @@ void VideoGameListView::onThemeChanged(const std::shared_ptr& theme) 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.applyTheme(theme, getName(), "md_description", ALL ^ (POSITION | ThemeFlags::SIZE | TEXT)); + + sortChildren(); } void VideoGameListView::initMDLabels() @@ -170,6 +165,7 @@ void VideoGameListView::initMDLabels() components[i]->setFont(Font::get(FONT_SIZE_SMALL)); 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; 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]->setDefaultZIndex(40); float testBot = values[i]->getPosition().y() + values[i]->getSize().y(); if(testBot > bottom) diff --git a/es-core/src/GuiComponent.cpp b/es-core/src/GuiComponent.cpp index 6ba531f2b..21d093d3c 100644 --- a/es-core/src/GuiComponent.cpp +++ b/es-core/src/GuiComponent.cpp @@ -105,6 +105,26 @@ void GuiComponent::setSize(float w, float h) 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. void GuiComponent::addChild(GuiComponent* cmp) { @@ -143,6 +163,13 @@ void GuiComponent::clearChildren() 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 { return mChildren.size(); @@ -320,6 +347,11 @@ void GuiComponent::applyTheme(const std::shared_ptr& theme, const std if(properties & ThemeFlags::SIZE && elem->has("size")) setSize(elem->get("size").cwiseProduct(scale)); + + if(properties & ThemeFlags::Z_INDEX && elem->has("zIndex")) + setZIndex(elem->get("zIndex")); + else + setZIndex(getDefaultZIndex()); } void GuiComponent::updateHelpPrompts() diff --git a/es-core/src/GuiComponent.h b/es-core/src/GuiComponent.h index e37abe69f..ec57662e0 100644 --- a/es-core/src/GuiComponent.h +++ b/es-core/src/GuiComponent.h @@ -46,12 +46,19 @@ public: void setSize(float w, float h); virtual void onSizeChanged() {}; + float getZIndex() const; + void setZIndex(float zIndex); + + float getDefaultZIndex() const; + void setDefaultZIndex(float zIndex); + void setParent(GuiComponent* parent); GuiComponent* getParent() const; void addChild(GuiComponent* cmp); void removeChild(GuiComponent* cmp); void clearChildren(); + void sortChildren(); unsigned int getChildCount() const; GuiComponent* getChild(unsigned int i) const; @@ -110,6 +117,9 @@ protected: Eigen::Vector3f mPosition; Eigen::Vector2f mSize; + float mDefaultZIndex = 0; + float mZIndex = 0; + bool mIsProcessing; public: diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index 50958b11f..b54299d10 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -24,7 +24,7 @@ ElementMapType makeMap(const T& mapInit) } std::vector ThemeData::sSupportedViews = boost::assign::list_of("system")("basic")("detailed")("video"); -std::vector ThemeData::sSupportedFeatures = boost::assign::list_of("video")("carousel"); +std::vector ThemeData::sSupportedFeatures = boost::assign::list_of("video")("carousel")("z-index"); std::map< std::string, ElementMapType > ThemeData::sElementMap = 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) ("path", PATH) ("tile", BOOLEAN) - ("color", COLOR))) + ("color", COLOR) + ("zIndex", FLOAT))) ("text", makeMap(boost::assign::map_list_of ("pos", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR) @@ -46,7 +47,8 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign:: ("alignment", STRING) ("forceUppercase", BOOLEAN) ("lineSpacing", FLOAT) - ("value", STRING))) + ("value", STRING) + ("zIndex", FLOAT))) ("textlist", makeMap(boost::assign::map_list_of ("pos", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR) @@ -60,26 +62,31 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign:: ("alignment", STRING) ("horizontalMargin", FLOAT) ("forceUppercase", BOOLEAN) - ("lineSpacing", FLOAT))) + ("lineSpacing", FLOAT) + ("zIndex", FLOAT))) ("container", makeMap(boost::assign::map_list_of ("pos", NORMALIZED_PAIR) - ("size", NORMALIZED_PAIR))) + ("size", NORMALIZED_PAIR) + ("zIndex", FLOAT))) ("ninepatch", makeMap(boost::assign::map_list_of ("pos", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR) - ("path", PATH))) + ("path", PATH) + ("zIndex", FLOAT))) ("datetime", makeMap(boost::assign::map_list_of ("pos", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR) ("color", COLOR) ("fontPath", PATH) ("fontSize", FLOAT) - ("forceUppercase", BOOLEAN))) + ("forceUppercase", BOOLEAN) + ("zIndex", FLOAT))) ("rating", makeMap(boost::assign::map_list_of ("pos", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR) ("filledPath", PATH) - ("unfilledPath", PATH))) + ("unfilledPath", PATH) + ("zIndex", FLOAT))) ("sound", makeMap(boost::assign::map_list_of ("path", PATH))) ("helpsystem", makeMap(boost::assign::map_list_of @@ -95,6 +102,7 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign:: ("origin", NORMALIZED_PAIR) ("default", PATH) ("delay", FLOAT) + ("zIndex", FLOAT) ("showSnapshotNoVideo", BOOLEAN) ("showSnapshotDelay", BOOLEAN))) ("carousel", makeMap(boost::assign::map_list_of @@ -104,7 +112,8 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign:: ("color", COLOR) ("logoScale", FLOAT) ("logoSize", NORMALIZED_PAIR) - ("maxLogoCount", FLOAT))); + ("maxLogoCount", FLOAT) + ("zIndex", FLOAT))); namespace fs = boost::filesystem; @@ -450,6 +459,7 @@ std::vector ThemeData::makeExtras(const std::shared_ptrsetDefaultZIndex(10); comp->applyTheme(theme, view, *it, ThemeFlags::ALL); comps.push_back(comp); } @@ -458,24 +468,6 @@ std::vector ThemeData::makeExtras(const std::shared_ptr& 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 ThemeData::getThemeSets() { std::map sets; diff --git a/es-core/src/ThemeData.h b/es-core/src/ThemeData.h index 8231e07ed..e0e7bb129 100644 --- a/es-core/src/ThemeData.h +++ b/es-core/src/ThemeData.h @@ -38,6 +38,7 @@ namespace ThemeFlags FORCE_UPPERCASE = 1024, LINE_SPACING = 2048, DELAY = 4096, + Z_INDEX = 8192, ALL = 0xFFFFFFFF }; @@ -71,19 +72,6 @@ ThemeException& operator<<(ThemeException& e, T appendMsg) 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& extras); - -private: - std::vector mExtras; -}; - struct ThemeSet { boost::filesystem::path path; diff --git a/es-core/src/components/ImageComponent.cpp b/es-core/src/components/ImageComponent.cpp index 0705e0c28..8e28b7cf4 100644 --- a/es-core/src/components/ImageComponent.cpp +++ b/es-core/src/components/ImageComponent.cpp @@ -362,6 +362,11 @@ void ImageComponent::applyTheme(const std::shared_ptr& theme, const s if(properties & COLOR && elem->has("color")) setColorShift(elem->get("color")); + + if(properties & ThemeFlags::Z_INDEX && elem->has("zIndex")) + setZIndex(elem->get("zIndex")); + else + setZIndex(getDefaultZIndex()); } std::vector ImageComponent::getHelpPrompts() diff --git a/es-core/src/components/VideoComponent.cpp b/es-core/src/components/VideoComponent.cpp index 268a45316..6d7f9e0e7 100644 --- a/es-core/src/components/VideoComponent.cpp +++ b/es-core/src/components/VideoComponent.cpp @@ -347,6 +347,11 @@ void VideoComponent::applyTheme(const std::shared_ptr& theme, const s if (elem->has("showSnapshotDelay")) mConfig.showSnapshotDelay = elem->get("showSnapshotDelay"); + + if(properties & ThemeFlags::Z_INDEX && elem->has("zIndex")) + setZIndex(elem->get("zIndex")); + else + setZIndex(getDefaultZIndex()); } std::vector VideoComponent::getHelpPrompts()