mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-28 17:15:38 +00:00
Large update to get the new theme engine up and running.
This commit is contained in:
parent
0ca2b62edf
commit
c35a297d9a
|
@ -642,6 +642,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
AudioManager::getInstance();
|
AudioManager::getInstance();
|
||||||
MameNames::getInstance();
|
MameNames::getInstance();
|
||||||
|
ThemeData::getThemeSets();
|
||||||
loadSystemsReturnCode loadSystemsStatus = loadSystemConfigFile();
|
loadSystemsReturnCode loadSystemsStatus = loadSystemConfigFile();
|
||||||
|
|
||||||
if (loadSystemsStatus) {
|
if (loadSystemsStatus) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "components/BadgeComponent.h"
|
#include "components/BadgeComponent.h"
|
||||||
#include "components/DateTimeComponent.h"
|
#include "components/DateTimeComponent.h"
|
||||||
|
#include "components/LottieComponent.h"
|
||||||
#include "components/RatingComponent.h"
|
#include "components/RatingComponent.h"
|
||||||
#include "components/ScrollableContainer.h"
|
#include "components/ScrollableContainer.h"
|
||||||
#include "components/TextComponent.h"
|
#include "components/TextComponent.h"
|
||||||
|
|
|
@ -45,7 +45,7 @@ void GamelistView::legacyPopulateFields()
|
||||||
|
|
||||||
// Thumbnails.
|
// Thumbnails.
|
||||||
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
mImageComponents.back()->setMetadataField("md_thumbnail");
|
mImageComponents.back()->setMetadataField("image_md_thumbnail");
|
||||||
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
mImageComponents.back()->setVisible(false);
|
mImageComponents.back()->setVisible(false);
|
||||||
mImageComponents.back()->setMaxSize(mSize.x * (0.25f - 2.0f * padding), mSize.y * 0.10f);
|
mImageComponents.back()->setMaxSize(mSize.x * (0.25f - 2.0f * padding), mSize.y * 0.10f);
|
||||||
|
@ -54,7 +54,7 @@ void GamelistView::legacyPopulateFields()
|
||||||
|
|
||||||
// Marquee.
|
// Marquee.
|
||||||
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
mImageComponents.back()->setMetadataField("md_marquee");
|
mImageComponents.back()->setMetadataField("image_md_marquee");
|
||||||
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
mImageComponents.back()->setVisible(false);
|
mImageComponents.back()->setVisible(false);
|
||||||
mImageComponents.back()->setMaxSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.18f);
|
mImageComponents.back()->setMaxSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.18f);
|
||||||
|
@ -63,7 +63,7 @@ void GamelistView::legacyPopulateFields()
|
||||||
|
|
||||||
// Image.
|
// Image.
|
||||||
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
mImageComponents.back()->setMetadataField("md_image");
|
mImageComponents.back()->setMetadataField("image_md_image");
|
||||||
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
mImageComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
mImageComponents.back()->setPosition(mSize.x * 0.25f,
|
mImageComponents.back()->setPosition(mSize.x * 0.25f,
|
||||||
mList.getPosition().y + mSize.y * 0.2125f);
|
mList.getPosition().y + mSize.y * 0.2125f);
|
||||||
|
@ -74,9 +74,10 @@ void GamelistView::legacyPopulateFields()
|
||||||
if (mViewStyle == ViewController::VIDEO) {
|
if (mViewStyle == ViewController::VIDEO) {
|
||||||
// Video.
|
// Video.
|
||||||
mVideoComponents.push_back(std::make_unique<VideoFFmpegComponent>());
|
mVideoComponents.push_back(std::make_unique<VideoFFmpegComponent>());
|
||||||
mVideoComponents.back()->setMetadataField("md_video");
|
mVideoComponents.back()->setMetadataField("video_md_video");
|
||||||
mVideoComponents.back()->setOrigin(0.5f, 0.5f);
|
mVideoComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
mVideoComponents.back()->setPosition(mSize.x * 0.25f, mSize.y * 0.4f);
|
mVideoComponents.back()->setPosition(mSize.x * 0.25f,
|
||||||
|
mList.getPosition().y + mSize.y * 0.2125f);
|
||||||
mVideoComponents.back()->setSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.4f);
|
mVideoComponents.back()->setSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.4f);
|
||||||
mVideoComponents.back()->setDefaultZIndex(30.0f);
|
mVideoComponents.back()->setDefaultZIndex(30.0f);
|
||||||
addChild(mVideoComponents.back().get());
|
addChild(mVideoComponents.back().get());
|
||||||
|
@ -85,84 +86,85 @@ void GamelistView::legacyPopulateFields()
|
||||||
mList.setPosition(mSize.x * (0.50f + padding), mList.getPosition().y);
|
mList.setPosition(mSize.x * (0.50f + padding), mList.getPosition().y);
|
||||||
mList.setSize(mSize.x * (0.50f - padding), mList.getSize().y);
|
mList.setSize(mSize.x * (0.50f - padding), mList.getSize().y);
|
||||||
mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT);
|
mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT);
|
||||||
mList.setCursorChangedCallback([&](const CursorState& /*state*/) { legacyUpdateInfoPanel(); });
|
mList.setCursorChangedCallback([&](const CursorState& /*state*/) { updateInfoPanel(); });
|
||||||
|
|
||||||
// Metadata labels + values.
|
// Metadata labels + values.
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setText("Rating: ", false);
|
mTextComponents.back()->setText("Rating: ", false);
|
||||||
mTextComponents.back()->setMetadataField("md_lbl_rating");
|
mTextComponents.back()->setMetadataField("text_md_lbl_rating");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setText("Released: ", false);
|
mTextComponents.back()->setText("Released: ", false);
|
||||||
mTextComponents.back()->setMetadataField("md_lbl_releasedate");
|
mTextComponents.back()->setMetadataField("text_md_lbl_releasedate");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setText("Developer: ", false);
|
mTextComponents.back()->setText("Developer: ", false);
|
||||||
mTextComponents.back()->setMetadataField("md_lbl_developer");
|
mTextComponents.back()->setMetadataField("text_md_lbl_developer");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setText("Publisher: ", false);
|
mTextComponents.back()->setText("Publisher: ", false);
|
||||||
mTextComponents.back()->setMetadataField("md_lbl_publisher");
|
mTextComponents.back()->setMetadataField("text_md_lbl_publisher");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setText("Genre: ", false);
|
mTextComponents.back()->setText("Genre: ", false);
|
||||||
mTextComponents.back()->setMetadataField("md_lbl_genre");
|
mTextComponents.back()->setMetadataField("text_md_lbl_genre");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setText("Players: ", false);
|
mTextComponents.back()->setText("Players: ", false);
|
||||||
mTextComponents.back()->setMetadataField("md_lbl_players");
|
mTextComponents.back()->setMetadataField("text_md_lbl_players");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setText("Last played: ", false);
|
mTextComponents.back()->setText("Last played: ", false);
|
||||||
mTextComponents.back()->setMetadataField("md_lbl_lastplayed");
|
mTextComponents.back()->setMetadataField("text_md_lbl_lastplayed");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setText("Times played: ", false);
|
mTextComponents.back()->setText("Times played: ", false);
|
||||||
mTextComponents.back()->setMetadataField("md_lbl_playcount");
|
mTextComponents.back()->setMetadataField("text_md_lbl_playcount");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mRatingComponents.push_back(std::make_unique<RatingComponent>());
|
mRatingComponents.push_back(std::make_unique<RatingComponent>());
|
||||||
mRatingComponents.back()->setMetadataField("md_rating");
|
mRatingComponents.back()->setMetadataField("rating_md_rating");
|
||||||
mRatingComponents.back()->setDefaultZIndex(40.0f);
|
mRatingComponents.back()->setDefaultZIndex(40.0f);
|
||||||
addChild(mRatingComponents.back().get());
|
addChild(mRatingComponents.back().get());
|
||||||
|
|
||||||
mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
|
mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
|
||||||
mDateTimeComponents.back()->setMetadataField("md_releasedate");
|
mDateTimeComponents.back()->setMetadataField("datetime_md_releasedate");
|
||||||
addChild(mDateTimeComponents.back().get());
|
addChild(mDateTimeComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setMetadataField("md_developer");
|
mTextComponents.back()->setMetadataField("text_md_developer");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setMetadataField("md_publisher");
|
mTextComponents.back()->setMetadataField("text_md_publisher");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setMetadataField("md_genre");
|
mTextComponents.back()->setMetadataField("text_md_genre");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setMetadataField("md_players");
|
mTextComponents.back()->setMetadataField("text_md_players");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
|
mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
|
||||||
mDateTimeComponents.back()->setMetadataField("md_lastplayed");
|
mDateTimeComponents.back()->setMetadataField("datetime_md_lastplayed");
|
||||||
|
mDateTimeComponents.back()->setDisplayRelative(true);
|
||||||
addChild(mDateTimeComponents.back().get());
|
addChild(mDateTimeComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setMetadataField("md_playcount");
|
mTextComponents.back()->setMetadataField("text_md_playcount");
|
||||||
addChild(mTextComponents.back().get());
|
addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setMetadataField("md_name");
|
mTextComponents.back()->setMetadataField("text_md_name");
|
||||||
mTextComponents.back()->setPosition(mSize.x, mSize.y);
|
mTextComponents.back()->setPosition(mSize.x, mSize.y);
|
||||||
mTextComponents.back()->setFont(Font::get(FONT_SIZE_MEDIUM));
|
mTextComponents.back()->setFont(Font::get(FONT_SIZE_MEDIUM));
|
||||||
mTextComponents.back()->setHorizontalAlignment(ALIGN_CENTER);
|
mTextComponents.back()->setHorizontalAlignment(ALIGN_CENTER);
|
||||||
|
@ -172,7 +174,7 @@ void GamelistView::legacyPopulateFields()
|
||||||
|
|
||||||
// Badges.
|
// Badges.
|
||||||
mBadgeComponents.push_back(std::make_unique<BadgeComponent>());
|
mBadgeComponents.push_back(std::make_unique<BadgeComponent>());
|
||||||
mBadgeComponents.back()->setMetadataField("md_badges");
|
mBadgeComponents.back()->setMetadataField("badges_md_badges");
|
||||||
mBadgeComponents.back()->setOrigin(0.5f, 0.5f);
|
mBadgeComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
mBadgeComponents.back()->setPosition(mSize.x * 0.8f, mSize.y * 0.7f);
|
mBadgeComponents.back()->setPosition(mSize.x * 0.8f, mSize.y * 0.7f);
|
||||||
mBadgeComponents.back()->setSize(mSize.x * 0.15f, mSize.y * 0.2f);
|
mBadgeComponents.back()->setSize(mSize.x * 0.15f, mSize.y * 0.2f);
|
||||||
|
@ -180,22 +182,21 @@ void GamelistView::legacyPopulateFields()
|
||||||
addChild(mBadgeComponents.back().get());
|
addChild(mBadgeComponents.back().get());
|
||||||
|
|
||||||
// Scrollable container (game description).
|
// Scrollable container (game description).
|
||||||
mScrollableContainerComponents.push_back(std::make_unique<ScrollableContainer>());
|
mContainerComponents.push_back(std::make_unique<ScrollableContainer>());
|
||||||
mScrollableContainerComponents.back()->setMetadataField("md_description");
|
mContainerComponents.back()->setMetadataField("text_md_description");
|
||||||
mScrollableContainerComponents.back()->setSize(
|
mContainerComponents.back()->setSize(mSize.x * (0.50f - 2.0f * padding),
|
||||||
mSize.x * (0.50f - 2.0f * padding),
|
mSize.y - mContainerComponents.back()->getPosition().y);
|
||||||
mSize.y - mScrollableContainerComponents.back()->getPosition().y);
|
mContainerComponents.back()->setAutoScroll(true);
|
||||||
mScrollableContainerComponents.back()->setAutoScroll(true);
|
mContainerComponents.back()->setDefaultZIndex(40.0f);
|
||||||
mScrollableContainerComponents.back()->setDefaultZIndex(40.0f);
|
addChild(mContainerComponents.back().get());
|
||||||
addChild(mScrollableContainerComponents.back().get());
|
|
||||||
|
|
||||||
mTextComponents.push_back(std::make_unique<TextComponent>());
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mTextComponents.back()->setFont(Font::get(FONT_SIZE_SMALL));
|
mTextComponents.back()->setFont(Font::get(FONT_SIZE_SMALL));
|
||||||
mTextComponents.back()->setSize(mScrollableContainerComponents.back()->getSize().x, 0.0f);
|
mTextComponents.back()->setSize(mContainerComponents.back()->getSize().x, 0.0f);
|
||||||
mScrollableContainerComponents.back()->addChild(mTextComponents.back().get());
|
mContainerComponents.back()->addChild(mTextComponents.back().get());
|
||||||
|
|
||||||
mGamelistInfoComponents.push_back(std::make_unique<TextComponent>());
|
mGamelistInfoComponents.push_back(std::make_unique<TextComponent>());
|
||||||
mGamelistInfoComponents.back()->setMetadataField("gamelistInfo");
|
mGamelistInfoComponents.back()->setMetadataField("text_gamelistInfo");
|
||||||
mGamelistInfoComponents.back()->setOrigin(0.5f, 0.5f);
|
mGamelistInfoComponents.back()->setOrigin(0.5f, 0.5f);
|
||||||
mGamelistInfoComponents.back()->setFont(Font::get(FONT_SIZE_SMALL));
|
mGamelistInfoComponents.back()->setFont(Font::get(FONT_SIZE_SMALL));
|
||||||
mGamelistInfoComponents.back()->setDefaultZIndex(50.0f);
|
mGamelistInfoComponents.back()->setDefaultZIndex(50.0f);
|
||||||
|
@ -209,9 +210,9 @@ void GamelistView::legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
|
|
||||||
using namespace ThemeFlags;
|
using namespace ThemeFlags;
|
||||||
|
|
||||||
mTextComponents[LOGOTEXT]->applyTheme(theme, getName(), "logoText", ALL);
|
mTextComponents[LOGOTEXT]->applyTheme(theme, getName(), "text_logoText", ALL);
|
||||||
mImageComponents[LOGO]->applyTheme(theme, getName(), "logo", ALL);
|
mImageComponents[LOGO]->applyTheme(theme, getName(), "image_logo", ALL);
|
||||||
mImageComponents[BACKGROUND]->applyTheme(theme, getName(), "background", ALL);
|
mImageComponents[BACKGROUND]->applyTheme(theme, getName(), "image_background", ALL);
|
||||||
|
|
||||||
// Remove old theme extras.
|
// Remove old theme extras.
|
||||||
for (auto extra : mThemeExtras) {
|
for (auto extra : mThemeExtras) {
|
||||||
|
@ -225,12 +226,13 @@ void GamelistView::legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
for (auto extra : mThemeExtras)
|
for (auto extra : mThemeExtras)
|
||||||
addChild(extra);
|
addChild(extra);
|
||||||
|
|
||||||
mList.applyTheme(theme, getName(), "gamelist", ALL);
|
mList.applyTheme(theme, getName(), "textlist_gamelist", ALL);
|
||||||
|
|
||||||
mImageComponents[LegacyImage::MD_THUMBNAIL]->applyTheme(
|
mImageComponents[LegacyImage::MD_THUMBNAIL]->applyTheme(
|
||||||
theme, getName(), mImageComponents[LegacyImage::MD_THUMBNAIL]->getMetadataField(), ALL);
|
theme, getName(), mImageComponents[LegacyImage::MD_THUMBNAIL]->getMetadataField(), ALL);
|
||||||
mImageComponents[LegacyImage::MD_MARQUEE]->applyTheme(
|
mImageComponents[LegacyImage::MD_MARQUEE]->applyTheme(theme, getName(), "image_md_marquee",
|
||||||
theme, getName(), "md_marquee", POSITION | ThemeFlags::SIZE | Z_INDEX | ROTATION | VISIBLE);
|
POSITION | ThemeFlags::SIZE | Z_INDEX |
|
||||||
|
ROTATION | VISIBLE);
|
||||||
|
|
||||||
if (mViewStyle == ViewController::DETAILED) {
|
if (mViewStyle == ViewController::DETAILED) {
|
||||||
mImageComponents[LegacyImage::MD_IMAGE]->applyTheme(
|
mImageComponents[LegacyImage::MD_IMAGE]->applyTheme(
|
||||||
|
@ -276,15 +278,15 @@ void GamelistView::legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
ALL);
|
ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& container : mScrollableContainerComponents) {
|
for (auto& container : mContainerComponents) {
|
||||||
container->applyTheme(theme, getName(), container->getMetadataField(),
|
container->applyTheme(theme, getName(), container->getMetadataField(),
|
||||||
POSITION | ThemeFlags::SIZE | Z_INDEX | VISIBLE);
|
POSITION | ThemeFlags::SIZE | Z_INDEX | VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mTextComponents[LegacyText::MD_DESCRIPTION]->setSize(
|
mTextComponents[LegacyText::MD_DESCRIPTION]->setSize(mContainerComponents.front()->getSize().x,
|
||||||
mScrollableContainerComponents.front()->getSize().x, 0.0f);
|
0.0f);
|
||||||
mTextComponents[LegacyText::MD_DESCRIPTION]->applyTheme(
|
mTextComponents[LegacyText::MD_DESCRIPTION]->applyTheme(
|
||||||
theme, getName(), "md_description",
|
theme, getName(), "text_md_description",
|
||||||
ALL ^ (POSITION | ThemeFlags::SIZE | ThemeFlags::ORIGIN | TEXT | ROTATION));
|
ALL ^ (POSITION | ThemeFlags::SIZE | ThemeFlags::ORIGIN | TEXT | ROTATION));
|
||||||
|
|
||||||
for (auto& gamelistInfo : mGamelistInfoComponents)
|
for (auto& gamelistInfo : mGamelistInfoComponents)
|
||||||
|
@ -299,10 +301,10 @@ void GamelistView::legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
|
|
||||||
// Hide some components if we're in Basic mode.
|
// Hide some components if we're in Basic mode.
|
||||||
if (mViewStyle == ViewController::BASIC) {
|
if (mViewStyle == ViewController::BASIC) {
|
||||||
if (mTheme->getElement(getName(), "logoText", "text") == nullptr)
|
if (mTheme->getElement(getName(), "text_logoText", "text") == nullptr)
|
||||||
mTextComponents[LegacyText::LOGOTEXT]->setVisible(false);
|
mTextComponents[LegacyText::LOGOTEXT]->setVisible(false);
|
||||||
mImageComponents[LegacyImage::MD_IMAGE]->setVisible(false);
|
mImageComponents[LegacyImage::MD_IMAGE]->setVisible(false);
|
||||||
for (auto& container : mScrollableContainerComponents)
|
for (auto& container : mContainerComponents)
|
||||||
container->setVisible(false);
|
container->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,11 +341,12 @@ void GamelistView::legacyUpdateInfoPanel()
|
||||||
|
|
||||||
// If we're scrolling, hide the metadata fields if the last game had this options set,
|
// If we're scrolling, hide the metadata fields if the last game had this options set,
|
||||||
// or if we're in the grouped custom collection view.
|
// or if we're in the grouped custom collection view.
|
||||||
if (mList.isScrolling())
|
if (mList.isScrolling()) {
|
||||||
if ((mLastUpdated && mLastUpdated->metadata.get("hidemetadata") == "true") ||
|
if ((mLastUpdated && mLastUpdated->metadata.get("hidemetadata") == "true") ||
|
||||||
(mLastUpdated->getSystem()->isCustomCollection() &&
|
(mLastUpdated->getSystem()->isCustomCollection() &&
|
||||||
mLastUpdated->getPath() == mLastUpdated->getSystem()->getName()))
|
mLastUpdated->getPath() == mLastUpdated->getSystem()->getName()))
|
||||||
hideMetaDataFields = true;
|
hideMetaDataFields = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (hideMetaDataFields || mViewStyle == ViewController::BASIC) {
|
if (hideMetaDataFields || mViewStyle == ViewController::BASIC) {
|
||||||
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_DESCRIPTION; ++i)
|
for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_DESCRIPTION; ++i)
|
||||||
|
@ -484,7 +487,7 @@ void GamelistView::legacyUpdateInfoPanel()
|
||||||
}
|
}
|
||||||
|
|
||||||
mTextComponents[LegacyText::MD_DESCRIPTION]->setText(file->metadata.get("desc"));
|
mTextComponents[LegacyText::MD_DESCRIPTION]->setText(file->metadata.get("desc"));
|
||||||
for (auto& container : mScrollableContainerComponents)
|
for (auto& container : mContainerComponents)
|
||||||
container->reset();
|
container->reset();
|
||||||
|
|
||||||
for (auto& rating : mRatingComponents)
|
for (auto& rating : mRatingComponents)
|
||||||
|
@ -540,66 +543,6 @@ void GamelistView::legacyUpdateInfoPanel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& text : mTextComponents) {
|
|
||||||
if (text->getValue() != "")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string metadata = text->getMetadataField();
|
|
||||||
if (metadata == "")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (metadata == "md_controller") {
|
|
||||||
std::string controller =
|
|
||||||
BadgeComponent::getDisplayName(file->metadata.get("controller"));
|
|
||||||
text->setValue(controller == "unknown" ? "" : controller);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (metadata == "md_name")
|
|
||||||
text->setValue(file->metadata.get("name"));
|
|
||||||
else if (metadata == "md_rating")
|
|
||||||
text->setValue(mRatingComponents.front()->getRatingValue());
|
|
||||||
else if (metadata == "md_developer")
|
|
||||||
text->setValue(file->metadata.get("developer"));
|
|
||||||
else if (metadata == "md_publisher")
|
|
||||||
text->setValue(file->metadata.get("publisher"));
|
|
||||||
else if (metadata == "md_genre")
|
|
||||||
text->setValue(file->metadata.get("genre"));
|
|
||||||
else if (metadata == "md_players")
|
|
||||||
text->setValue(file->metadata.get("players"));
|
|
||||||
else if (metadata == "md_favorite")
|
|
||||||
text->setValue(file->metadata.get("favorite") == "true" ? "yes" : "no");
|
|
||||||
else if (metadata == "md_completed")
|
|
||||||
text->setValue(file->metadata.get("completed") == "true" ? "yes" : "no");
|
|
||||||
else if (metadata == "md_kidgame")
|
|
||||||
text->setValue(file->metadata.get("kidgame") == "true" ? "yes" : "no");
|
|
||||||
else if (metadata == "md_broken")
|
|
||||||
text->setValue(file->metadata.get("broken") == "true" ? "yes" : "no");
|
|
||||||
else if (metadata == "md_playcount")
|
|
||||||
text->setValue(file->metadata.get("playcount"));
|
|
||||||
else if (metadata == "md_altemulator")
|
|
||||||
text->setValue(file->metadata.get("altemulator"));
|
|
||||||
else
|
|
||||||
text->setValue(metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& date : mDateTimeComponents) {
|
|
||||||
std::string metadata = date->getMetadataField();
|
|
||||||
if (metadata == "")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (metadata == "md_releasedate") {
|
|
||||||
date->setValue(file->metadata.get("releasedate"));
|
|
||||||
}
|
|
||||||
else if (metadata == "md_lastplayed") {
|
|
||||||
date->setValue(file->metadata.get("lastplayed"));
|
|
||||||
date->setDisplayRelative(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
date->setValue("19700101T000000");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fadingOut = false;
|
fadingOut = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,10 +699,10 @@ void GamelistView::legacyInitMDValues()
|
||||||
mRatingComponents.front()->setPosition(Renderer::getScreenWidth() * 2.0f,
|
mRatingComponents.front()->setPosition(Renderer::getScreenWidth() * 2.0f,
|
||||||
Renderer::getScreenHeight() * 2.0f);
|
Renderer::getScreenHeight() * 2.0f);
|
||||||
|
|
||||||
mScrollableContainerComponents.front()->setPosition(Renderer::getScreenWidth() * 2.0f,
|
mContainerComponents.front()->setPosition(Renderer::getScreenWidth() * 2.0f,
|
||||||
Renderer::getScreenHeight() * 2.0f);
|
Renderer::getScreenHeight() * 2.0f);
|
||||||
|
|
||||||
for (auto& container : mScrollableContainerComponents) {
|
for (auto& container : mContainerComponents) {
|
||||||
container->setPosition(container->getPosition().x, bottom + mSize.y * 0.01f);
|
container->setPosition(container->getPosition().x, bottom + mSize.y * 0.01f);
|
||||||
container->setSize(container->getSize().x, mSize.y - container->getPosition().y);
|
container->setSize(container->getSize().x, mSize.y - container->getPosition().y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,17 +13,14 @@
|
||||||
#include "UIModeController.h"
|
#include "UIModeController.h"
|
||||||
#include "animations/LambdaAnimation.h"
|
#include "animations/LambdaAnimation.h"
|
||||||
|
|
||||||
// #define FADE_IN_START_OPACITY 0.5f
|
#define FADE_IN_START_OPACITY 0.5f
|
||||||
// #define FADE_IN_TIME 325
|
#define FADE_IN_TIME 325
|
||||||
|
|
||||||
GamelistView::GamelistView(FileData* root, bool legacyMode)
|
GamelistView::GamelistView(FileData* root)
|
||||||
: GamelistBase {root}
|
: GamelistBase {root}
|
||||||
, mLegacyMode {legacyMode}
|
, mLegacyMode {false}
|
||||||
, mViewStyle {ViewController::BASIC}
|
, mViewStyle {ViewController::BASIC}
|
||||||
{
|
{
|
||||||
// TEMPORARY
|
|
||||||
mLegacyMode = true;
|
|
||||||
|
|
||||||
mViewStyle = ViewController::getInstance()->getState().viewstyle;
|
mViewStyle = ViewController::getInstance()->getState().viewstyle;
|
||||||
|
|
||||||
if (mLegacyMode)
|
if (mLegacyMode)
|
||||||
|
@ -71,8 +68,14 @@ void GamelistView::onFileChanged(FileData* file, bool reloadGamelist)
|
||||||
void GamelistView::onShow()
|
void GamelistView::onShow()
|
||||||
{
|
{
|
||||||
// Reset any Lottie animations.
|
// Reset any Lottie animations.
|
||||||
|
for (auto& animation : mLottieAnimComponents)
|
||||||
|
animation->resetFileAnimation();
|
||||||
|
|
||||||
|
// Reset any Lottie animations.
|
||||||
|
if (mLegacyMode) {
|
||||||
for (auto extra : mThemeExtras)
|
for (auto extra : mThemeExtras)
|
||||||
extra->resetFileAnimation();
|
extra->resetFileAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
mLastUpdated = nullptr;
|
mLastUpdated = nullptr;
|
||||||
GuiComponent::onShow();
|
GuiComponent::onShow();
|
||||||
|
@ -84,6 +87,8 @@ void GamelistView::onShow()
|
||||||
|
|
||||||
void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
{
|
{
|
||||||
|
mLegacyMode = mTheme->isLegacyTheme();
|
||||||
|
|
||||||
if (mLegacyMode) {
|
if (mLegacyMode) {
|
||||||
legacyOnThemeChanged(theme);
|
legacyOnThemeChanged(theme);
|
||||||
return;
|
return;
|
||||||
|
@ -91,21 +96,94 @@ void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
|
|
||||||
using namespace ThemeFlags;
|
using namespace ThemeFlags;
|
||||||
|
|
||||||
// Remove old theme extras.
|
if (mTheme->hasView("gamelist")) {
|
||||||
for (auto extra : mThemeExtras) {
|
for (auto& element : mTheme->getViewElements("gamelist").elements) {
|
||||||
removeChild(extra);
|
if (element.second.type == "image") {
|
||||||
delete extra;
|
mImageComponents.push_back(std::make_unique<ImageComponent>());
|
||||||
|
mImageComponents.back()->setDefaultZIndex(30.0f);
|
||||||
|
mImageComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
if (mImageComponents.back()->getMetadataField() != "")
|
||||||
|
mImageComponents.back()->setScrollHide(true);
|
||||||
|
addChild(mImageComponents.back().get());
|
||||||
|
}
|
||||||
|
else if (element.second.type == "video") {
|
||||||
|
mVideoComponents.push_back(std::make_unique<VideoFFmpegComponent>());
|
||||||
|
mVideoComponents.back()->setDefaultZIndex(30.0f);
|
||||||
|
addChild(mVideoComponents.back().get());
|
||||||
|
mVideoComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
if (mVideoComponents.back()->getMetadataField() != "")
|
||||||
|
mVideoComponents.back()->setScrollHide(true);
|
||||||
|
}
|
||||||
|
else if (element.second.type == "animation") {
|
||||||
|
mLottieAnimComponents.push_back(std::make_unique<LottieComponent>());
|
||||||
|
mLottieAnimComponents.back()->setDefaultZIndex(35.0f);
|
||||||
|
mLottieAnimComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
addChild(mLottieAnimComponents.back().get());
|
||||||
|
}
|
||||||
|
else if (element.second.type == "badges") {
|
||||||
|
mBadgeComponents.push_back(std::make_unique<BadgeComponent>());
|
||||||
|
mBadgeComponents.back()->setDefaultZIndex(35.0f);
|
||||||
|
mBadgeComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
mBadgeComponents.back()->setScrollHide(true);
|
||||||
|
addChild(mBadgeComponents.back().get());
|
||||||
|
}
|
||||||
|
else if (element.second.type == "text") {
|
||||||
|
if (element.second.has("container") && element.second.get<bool>("container")) {
|
||||||
|
mContainerTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mContainerTextComponents.back()->setDefaultZIndex(40.0f);
|
||||||
|
mContainerComponents.push_back(std::make_unique<ScrollableContainer>());
|
||||||
|
mContainerComponents.back()->setAutoScroll(true);
|
||||||
|
mContainerComponents.back()->addChild(mContainerTextComponents.back().get());
|
||||||
|
mContainerComponents.back()->applyTheme(theme, "gamelist", element.first,
|
||||||
|
POSITION | ThemeFlags::SIZE | Z_INDEX |
|
||||||
|
VISIBLE);
|
||||||
|
mContainerTextComponents.back()->applyTheme(theme, "gamelist", element.first,
|
||||||
|
ALL ^ POSITION ^ Z_INDEX ^
|
||||||
|
ThemeFlags::SIZE ^ VISIBLE);
|
||||||
|
mContainerTextComponents.back()->setSize(
|
||||||
|
mContainerComponents.back()->getSize().x, 0.0f);
|
||||||
|
mContainerComponents.back()->setDefaultZIndex(
|
||||||
|
mContainerTextComponents.back()->getDefaultZIndex());
|
||||||
|
mContainerComponents.back()->setZIndex(
|
||||||
|
mContainerTextComponents.back()->getZIndex());
|
||||||
|
mContainerComponents.back()->setScrollHide(true);
|
||||||
|
addChild(mContainerComponents.back().get());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mTextComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mTextComponents.back()->setDefaultZIndex(40.0f);
|
||||||
|
mTextComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
if (mTextComponents.back()->getMetadataField() != "")
|
||||||
|
mTextComponents.back()->setScrollHide(true);
|
||||||
|
addChild(mTextComponents.back().get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (element.second.type == "datetime") {
|
||||||
|
mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
|
||||||
|
mDateTimeComponents.back()->setDefaultZIndex(40.0f);
|
||||||
|
mDateTimeComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
if (mDateTimeComponents.back()->getMetadataField() != "")
|
||||||
|
mDateTimeComponents.back()->setScrollHide(true);
|
||||||
|
addChild(mDateTimeComponents.back().get());
|
||||||
|
}
|
||||||
|
else if (element.second.type == "gamelistinfo") {
|
||||||
|
mGamelistInfoComponents.push_back(std::make_unique<TextComponent>());
|
||||||
|
mGamelistInfoComponents.back()->setDefaultZIndex(45.0f);
|
||||||
|
mGamelistInfoComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
addChild(mGamelistInfoComponents.back().get());
|
||||||
|
}
|
||||||
|
else if (element.second.type == "rating") {
|
||||||
|
mRatingComponents.push_back(std::make_unique<RatingComponent>());
|
||||||
|
mRatingComponents.back()->setDefaultZIndex(45.0f);
|
||||||
|
mRatingComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
mRatingComponents.back()->setScrollHide(true);
|
||||||
|
addChild(mRatingComponents.back().get());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mThemeExtras.clear();
|
|
||||||
|
|
||||||
// Add new theme extras.
|
mList.setDefaultZIndex(50.0f);
|
||||||
mThemeExtras = ThemeData::makeExtras(theme, getName());
|
mList.applyTheme(theme, "gamelist", "textlist_gamelist", ALL);
|
||||||
for (auto extra : mThemeExtras)
|
|
||||||
addChild(extra);
|
|
||||||
|
|
||||||
mList.applyTheme(theme, getName(), "gamelist", ALL);
|
|
||||||
|
|
||||||
// TODO: Implement logic to populate component vectors.
|
|
||||||
|
|
||||||
sortChildren();
|
sortChildren();
|
||||||
}
|
}
|
||||||
|
@ -117,6 +195,23 @@ void GamelistView::update(int deltaTime)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ViewController::getInstance()->getGameLaunchTriggered()) {
|
||||||
|
for (auto& image : mImageComponents) {
|
||||||
|
if (image->isAnimationPlaying(0))
|
||||||
|
image->finishAnimation(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& video : mVideoComponents) {
|
||||||
|
if (!mVideoPlaying)
|
||||||
|
video->onHide();
|
||||||
|
else if (mVideoPlaying && !video->isVideoPaused() && !mWindow->isScreensaverActive())
|
||||||
|
video->onShow();
|
||||||
|
|
||||||
|
if (ViewController::getInstance()->getGameLaunchTriggered() && video->isAnimationPlaying(0))
|
||||||
|
video->finishAnimation(0);
|
||||||
|
}
|
||||||
|
|
||||||
updateChildren(deltaTime);
|
updateChildren(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +235,10 @@ void GamelistView::render(const glm::mat4& parentTrans)
|
||||||
HelpStyle GamelistView::getHelpStyle()
|
HelpStyle GamelistView::getHelpStyle()
|
||||||
{
|
{
|
||||||
HelpStyle style;
|
HelpStyle style;
|
||||||
|
if (mLegacyMode)
|
||||||
style.applyTheme(mTheme, getName());
|
style.applyTheme(mTheme, getName());
|
||||||
|
else
|
||||||
|
style.applyTheme(mTheme, "gamelist");
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +291,11 @@ std::vector<HelpPrompt> GamelistView::getHelpPrompts()
|
||||||
|
|
||||||
void GamelistView::updateInfoPanel()
|
void GamelistView::updateInfoPanel()
|
||||||
{
|
{
|
||||||
|
if (mLegacyMode) {
|
||||||
|
legacyUpdateInfoPanel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FileData* file {(mList.size() == 0 || mList.isScrolling()) ? nullptr : mList.getSelected()};
|
FileData* file {(mList.size() == 0 || mList.isScrolling()) ? nullptr : mList.getSelected()};
|
||||||
|
|
||||||
// If the game data has already been rendered to the info panel, then skip it this time.
|
// If the game data has already been rendered to the info panel, then skip it this time.
|
||||||
|
@ -219,8 +322,438 @@ void GamelistView::updateInfoPanel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hideMetaDataFields)
|
// If we're scrolling, hide the metadata fields if the last game had this options set,
|
||||||
;
|
// or if we're in the grouped custom collection view.
|
||||||
|
if (mList.isScrolling()) {
|
||||||
|
if ((mLastUpdated && mLastUpdated->metadata.get("hidemetadata") == "true") ||
|
||||||
|
(mLastUpdated->getSystem()->isCustomCollection() &&
|
||||||
|
mLastUpdated->getPath() == mLastUpdated->getSystem()->getName()))
|
||||||
|
hideMetaDataFields = true;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement gamelist logic.
|
if (hideMetaDataFields) {
|
||||||
|
for (auto& text : mTextComponents) {
|
||||||
|
if (text->getMetadataField() != "")
|
||||||
|
text->setVisible(false);
|
||||||
|
}
|
||||||
|
for (auto& date : mDateTimeComponents)
|
||||||
|
date->setVisible(false);
|
||||||
|
for (auto& badge : mBadgeComponents)
|
||||||
|
badge->setVisible(false);
|
||||||
|
for (auto& rating : mRatingComponents)
|
||||||
|
rating->setVisible(false);
|
||||||
|
for (auto& cText : mContainerTextComponents) {
|
||||||
|
if (cText->getMetadataField() != "md_description")
|
||||||
|
cText->setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (auto& text : mTextComponents) {
|
||||||
|
if (text->getMetadataField() != "")
|
||||||
|
text->setVisible(true);
|
||||||
|
}
|
||||||
|
for (auto& date : mDateTimeComponents)
|
||||||
|
date->setVisible(true);
|
||||||
|
for (auto& badge : mBadgeComponents)
|
||||||
|
badge->setVisible(true);
|
||||||
|
for (auto& rating : mRatingComponents)
|
||||||
|
rating->setVisible(true);
|
||||||
|
for (auto& cText : mContainerTextComponents) {
|
||||||
|
if (cText->getMetadataField() != "md_description")
|
||||||
|
cText->setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fadingOut = false;
|
||||||
|
if (file == nullptr) {
|
||||||
|
mVideoPlaying = false;
|
||||||
|
fadingOut = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If we're browsing a grouped custom collection, then update the folder metadata
|
||||||
|
// which will generate a description of three random games and return a pointer to
|
||||||
|
// the first of these so that we can display its game media.
|
||||||
|
if (file->getSystem()->isCustomCollection() &&
|
||||||
|
file->getPath() == file->getSystem()->getName()) {
|
||||||
|
mRandomGame = CollectionSystemsManager::getInstance()->updateCollectionFolderMetadata(
|
||||||
|
file->getSystem());
|
||||||
|
if (mRandomGame) {
|
||||||
|
for (auto& image : mImageComponents) {
|
||||||
|
if (image->getMetadataField() == "md_image")
|
||||||
|
image->setImage(mRandomGame->getImagePath());
|
||||||
|
else if (image->getMetadataField() == "md_miximage")
|
||||||
|
image->setImage(mRandomGame->getMiximagePath());
|
||||||
|
else if (image->getMetadataField() == "md_marquee")
|
||||||
|
image->setImage(mRandomGame->getMarqueePath(), false, true);
|
||||||
|
else if (image->getMetadataField() == "md_screenshot")
|
||||||
|
image->setImage(mRandomGame->getScreenshotPath());
|
||||||
|
else if (image->getMetadataField() == "md_titlescreen")
|
||||||
|
image->setImage(mRandomGame->getTitleScreenPath());
|
||||||
|
else if (image->getMetadataField() == "md_cover")
|
||||||
|
image->setImage(mRandomGame->getCoverPath());
|
||||||
|
else if (image->getMetadataField() == "md_backcover")
|
||||||
|
image->setImage(mRandomGame->getBackCoverPath());
|
||||||
|
else if (image->getMetadataField() == "md_3dbox")
|
||||||
|
image->setImage(mRandomGame->get3DBoxPath());
|
||||||
|
else if (image->getMetadataField() == "md_fanart")
|
||||||
|
image->setImage(mRandomGame->getFanArtPath());
|
||||||
|
else if (image->getMetadataField() == "md_thumbnail")
|
||||||
|
image->setImage(mRandomGame->getThumbnailPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& video : mVideoComponents) {
|
||||||
|
if (video->getMetadataField() == "md_image")
|
||||||
|
video->setImage(mRandomGame->getImagePath());
|
||||||
|
else if (video->getMetadataField() == "md_miximage")
|
||||||
|
video->setImage(mRandomGame->getMiximagePath());
|
||||||
|
else if (video->getMetadataField() == "md_marquee")
|
||||||
|
video->setImage(mRandomGame->getMarqueePath(), false, true);
|
||||||
|
else if (video->getMetadataField() == "md_screenshot")
|
||||||
|
video->setImage(mRandomGame->getScreenshotPath());
|
||||||
|
else if (video->getMetadataField() == "md_titlescreen")
|
||||||
|
video->setImage(mRandomGame->getTitleScreenPath());
|
||||||
|
else if (video->getMetadataField() == "md_cover")
|
||||||
|
video->setImage(mRandomGame->getCoverPath());
|
||||||
|
else if (video->getMetadataField() == "md_backcover")
|
||||||
|
video->setImage(mRandomGame->getBackCoverPath());
|
||||||
|
else if (video->getMetadataField() == "md_3dbox")
|
||||||
|
video->setImage(mRandomGame->get3DBoxPath());
|
||||||
|
else if (video->getMetadataField() == "md_fanart")
|
||||||
|
video->setImage(mRandomGame->getFanArtPath());
|
||||||
|
else if (video->getMetadataField() == "md_thumbnail")
|
||||||
|
video->setImage(mRandomGame->getThumbnailPath());
|
||||||
|
|
||||||
|
// Always stop the video before setting a new video as it will otherwise
|
||||||
|
// continue to play if it has the same path (i.e. it is the same physical
|
||||||
|
// video file) as the previously set video. That may happen when entering a
|
||||||
|
// folder with the same name as the first game file inside, or as in this
|
||||||
|
// case, when entering a custom collection.
|
||||||
|
video->onHide();
|
||||||
|
|
||||||
|
if (video->hasStaticVideo())
|
||||||
|
video->setStaticVideo();
|
||||||
|
else if (!video->setVideo(mRandomGame->getVideoPath()))
|
||||||
|
video->setDefaultVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (auto& image : mImageComponents) {
|
||||||
|
if (image->getMetadataField() != "")
|
||||||
|
image->setImage("");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& video : mVideoComponents) {
|
||||||
|
video->setImage("");
|
||||||
|
video->setVideo("");
|
||||||
|
if (video->hasStaticVideo()) {
|
||||||
|
video->onStopVideo();
|
||||||
|
video->setStaticVideo();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
video->setDefaultVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (auto& image : mImageComponents) {
|
||||||
|
if (image->getMetadataField() == "md_image")
|
||||||
|
image->setImage(file->getImagePath());
|
||||||
|
else if (image->getMetadataField() == "md_miximage")
|
||||||
|
image->setImage(file->getMiximagePath());
|
||||||
|
else if (image->getMetadataField() == "md_marquee")
|
||||||
|
image->setImage(file->getMarqueePath(), false, true);
|
||||||
|
else if (image->getMetadataField() == "md_screenshot")
|
||||||
|
image->setImage(file->getScreenshotPath());
|
||||||
|
else if (image->getMetadataField() == "md_titlescreen")
|
||||||
|
image->setImage(file->getTitleScreenPath());
|
||||||
|
else if (image->getMetadataField() == "md_cover")
|
||||||
|
image->setImage(file->getCoverPath());
|
||||||
|
else if (image->getMetadataField() == "md_backcover")
|
||||||
|
image->setImage(file->getBackCoverPath());
|
||||||
|
else if (image->getMetadataField() == "md_3dbox")
|
||||||
|
image->setImage(file->get3DBoxPath());
|
||||||
|
else if (image->getMetadataField() == "md_fanart")
|
||||||
|
image->setImage(file->getFanArtPath());
|
||||||
|
else if (image->getMetadataField() == "md_thumbnail")
|
||||||
|
image->setImage(file->getThumbnailPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& video : mVideoComponents) {
|
||||||
|
if (video->getMetadataField() == "md_image")
|
||||||
|
video->setImage(file->getImagePath());
|
||||||
|
else if (video->getMetadataField() == "md_miximage")
|
||||||
|
video->setImage(file->getMiximagePath());
|
||||||
|
else if (video->getMetadataField() == "md_marquee")
|
||||||
|
video->setImage(file->getMarqueePath(), false, true);
|
||||||
|
else if (video->getMetadataField() == "md_screenshot")
|
||||||
|
video->setImage(file->getScreenshotPath());
|
||||||
|
else if (video->getMetadataField() == "md_titlescreen")
|
||||||
|
video->setImage(file->getTitleScreenPath());
|
||||||
|
else if (video->getMetadataField() == "md_cover")
|
||||||
|
video->setImage(file->getCoverPath());
|
||||||
|
else if (video->getMetadataField() == "md_backcover")
|
||||||
|
video->setImage(file->getBackCoverPath());
|
||||||
|
else if (video->getMetadataField() == "md_3dbox")
|
||||||
|
video->setImage(file->get3DBoxPath());
|
||||||
|
else if (video->getMetadataField() == "md_fanart")
|
||||||
|
video->setImage(file->getFanArtPath());
|
||||||
|
else if (video->getMetadataField() == "md_thumbnail")
|
||||||
|
video->setImage(file->getThumbnailPath());
|
||||||
|
|
||||||
|
video->onHide();
|
||||||
|
|
||||||
|
if (video->hasStaticVideo())
|
||||||
|
video->setStaticVideo();
|
||||||
|
else if (!video->setVideo(file->getVideoPath()))
|
||||||
|
video->setDefaultVideo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mVideoPlaying = true;
|
||||||
|
|
||||||
|
// Populate the gamelistInfo field which shows an icon if a folder has been entered
|
||||||
|
// as well as the game count for the entire system (total and favorites separately).
|
||||||
|
// If a filter has been applied, then the number of filtered and total games replaces
|
||||||
|
// the game counter.
|
||||||
|
for (auto& gamelistInfo : mGamelistInfoComponents) {
|
||||||
|
std::string gamelistInfoString;
|
||||||
|
Alignment infoAlign = gamelistInfo->getHorizontalAlignment();
|
||||||
|
|
||||||
|
if (mIsFolder && infoAlign == ALIGN_RIGHT)
|
||||||
|
gamelistInfoString = ViewController::FOLDER_CHAR + " ";
|
||||||
|
|
||||||
|
if (mIsFiltered) {
|
||||||
|
if (mFilteredGameCountAll == mFilteredGameCount)
|
||||||
|
gamelistInfoString += ViewController::FILTER_CHAR + " " +
|
||||||
|
std::to_string(mFilteredGameCount) + " / " +
|
||||||
|
std::to_string(mGameCount);
|
||||||
|
else
|
||||||
|
gamelistInfoString +=
|
||||||
|
ViewController::FILTER_CHAR + " " + std::to_string(mFilteredGameCount) +
|
||||||
|
" + " + std::to_string(mFilteredGameCountAll - mFilteredGameCount) + " / " +
|
||||||
|
std::to_string(mGameCount);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gamelistInfoString +=
|
||||||
|
ViewController::CONTROLLER_CHAR + " " + std::to_string(mGameCount);
|
||||||
|
if (!(file->getSystem()->isCollection() &&
|
||||||
|
file->getSystem()->getFullName() == "favorites"))
|
||||||
|
gamelistInfoString += " " + ViewController::FAVORITE_CHAR + " " +
|
||||||
|
std::to_string(mFavoritesGameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIsFolder && infoAlign != ALIGN_RIGHT)
|
||||||
|
gamelistInfoString += " " + ViewController::FOLDER_CHAR;
|
||||||
|
|
||||||
|
gamelistInfo->setValue(gamelistInfoString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade in the game image.
|
||||||
|
for (auto& image : mImageComponents) {
|
||||||
|
if (image->getMetadataField() == "md_image") {
|
||||||
|
auto func = [&image](float t) {
|
||||||
|
image->setOpacity(static_cast<unsigned char>(
|
||||||
|
glm::mix(static_cast<float>(FADE_IN_START_OPACITY), 1.0f, t) * 255));
|
||||||
|
};
|
||||||
|
image->setAnimation(new LambdaAnimation(func, FADE_IN_TIME), 0, nullptr, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade in the static image.
|
||||||
|
for (auto& video : mVideoComponents) {
|
||||||
|
if (video->getMetadataField() == "md_video") {
|
||||||
|
auto func = [&video](float t) {
|
||||||
|
video->setOpacity(static_cast<unsigned char>(
|
||||||
|
glm::mix(static_cast<float>(FADE_IN_START_OPACITY), 1.0f, t) * 255));
|
||||||
|
};
|
||||||
|
video->setAnimation(new LambdaAnimation(func, FADE_IN_TIME), 0, nullptr, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& container : mContainerComponents)
|
||||||
|
container->reset();
|
||||||
|
|
||||||
|
for (auto& rating : mRatingComponents)
|
||||||
|
rating->setValue(file->metadata.get("rating"));
|
||||||
|
|
||||||
|
// Populate the badge slots based on game metadata.
|
||||||
|
std::vector<BadgeComponent::BadgeInfo> badgeSlots;
|
||||||
|
for (auto& badgeComponent : mBadgeComponents) {
|
||||||
|
for (auto& badge : badgeComponent->getBadgeTypes()) {
|
||||||
|
BadgeComponent::BadgeInfo badgeInfo;
|
||||||
|
badgeInfo.badgeType = badge;
|
||||||
|
if (badge == "controller") {
|
||||||
|
if (file->metadata.get("controller").compare("") != 0) {
|
||||||
|
badgeInfo.gameController = file->metadata.get("controller");
|
||||||
|
badgeSlots.push_back(badgeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (badge == "altemulator") {
|
||||||
|
if (file->metadata.get(badge).compare("") != 0)
|
||||||
|
badgeSlots.push_back(badgeInfo);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (file->metadata.get(badge).compare("true") == 0)
|
||||||
|
badgeSlots.push_back(badgeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
badgeComponent->setBadges(badgeSlots);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& text : mTextComponents) {
|
||||||
|
if (text->getMetadataField() == "md_name")
|
||||||
|
text->setText(file->metadata.get("name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->getType() == GAME) {
|
||||||
|
if (!hideMetaDataFields) {
|
||||||
|
for (auto& date : mDateTimeComponents) {
|
||||||
|
if (date->getMetadataField() == "md_lastplayed")
|
||||||
|
date->setValue(file->metadata.get("lastplayed"));
|
||||||
|
else if (date->getMetadataField() == "md_playcount")
|
||||||
|
date->setValue(file->metadata.get("playcount"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (file->getType() == FOLDER) {
|
||||||
|
if (!hideMetaDataFields) {
|
||||||
|
for (auto& date : mDateTimeComponents) {
|
||||||
|
if (date->getMetadataField() == "md_lastplayed") {
|
||||||
|
date->setValue(file->metadata.get("lastplayed"));
|
||||||
|
date->setVisible(false);
|
||||||
|
date->setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string metadata;
|
||||||
|
|
||||||
|
auto getMetadataValue = [&file, &metadata]() -> std::string {
|
||||||
|
if (metadata == "md_name")
|
||||||
|
return file->metadata.get("name");
|
||||||
|
else if (metadata == "md_description")
|
||||||
|
return file->metadata.get("desc");
|
||||||
|
else if (metadata == "md_developer")
|
||||||
|
return file->metadata.get("developer");
|
||||||
|
else if (metadata == "md_publisher")
|
||||||
|
return file->metadata.get("publisher");
|
||||||
|
else if (metadata == "md_genre")
|
||||||
|
return file->metadata.get("genre");
|
||||||
|
else if (metadata == "md_players")
|
||||||
|
return file->metadata.get("players");
|
||||||
|
else if (metadata == "md_favorite")
|
||||||
|
return file->metadata.get("favorite") == "true" ? "Yes" : "No";
|
||||||
|
else if (metadata == "md_completed")
|
||||||
|
return file->metadata.get("completed") == "true" ? "Yes" : "No";
|
||||||
|
else if (metadata == "md_kidgame")
|
||||||
|
return file->metadata.get("kidgame") == "true" ? "Yes" : "No";
|
||||||
|
else if (metadata == "md_broken")
|
||||||
|
return file->metadata.get("broken") == "true" ? "Yes" : "No";
|
||||||
|
else if (metadata == "md_playcount")
|
||||||
|
return file->metadata.get("playcount");
|
||||||
|
else if (metadata == "md_altemulator")
|
||||||
|
return file->metadata.get("altemulator");
|
||||||
|
else
|
||||||
|
return metadata;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto& text : mContainerTextComponents) {
|
||||||
|
metadata = text->getMetadataField();
|
||||||
|
if (metadata == "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (metadata == "md_rating") {
|
||||||
|
text->setValue(mRatingComponents.front()->getRatingValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (metadata == "md_controller") {
|
||||||
|
std::string controller =
|
||||||
|
BadgeComponent::getDisplayName(file->metadata.get("controller"));
|
||||||
|
text->setValue(controller == "unknown" ? "" : controller);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
text->setValue(getMetadataValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& text : mTextComponents) {
|
||||||
|
metadata = text->getMetadataField();
|
||||||
|
if (metadata == "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (metadata == "md_rating") {
|
||||||
|
text->setValue(mRatingComponents.front()->getRatingValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (metadata == "md_controller") {
|
||||||
|
std::string controller =
|
||||||
|
BadgeComponent::getDisplayName(file->metadata.get("controller"));
|
||||||
|
text->setValue(controller == "unknown" ? "" : controller);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
text->setValue(getMetadataValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& date : mDateTimeComponents) {
|
||||||
|
std::string metadata = date->getMetadataField();
|
||||||
|
if (metadata == "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (metadata == "md_releasedate") {
|
||||||
|
date->setValue(file->metadata.get("releasedate"));
|
||||||
|
}
|
||||||
|
else if (metadata == "md_lastplayed") {
|
||||||
|
date->setValue(file->metadata.get("lastplayed"));
|
||||||
|
date->setDisplayRelative(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
date->setValue("19700101T000000");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fadingOut = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GuiComponent*> comps;
|
||||||
|
|
||||||
|
for (auto& text : mTextComponents) {
|
||||||
|
if (text->getScrollHide())
|
||||||
|
comps.emplace_back(text.get());
|
||||||
|
}
|
||||||
|
for (auto& date : mDateTimeComponents) {
|
||||||
|
if (date->getScrollHide())
|
||||||
|
comps.emplace_back(date.get());
|
||||||
|
}
|
||||||
|
for (auto& image : mImageComponents) {
|
||||||
|
if (image->getScrollHide())
|
||||||
|
comps.emplace_back(image.get());
|
||||||
|
}
|
||||||
|
for (auto& badge : mBadgeComponents) {
|
||||||
|
if (badge->getScrollHide())
|
||||||
|
comps.emplace_back(badge.get());
|
||||||
|
}
|
||||||
|
for (auto& rating : mRatingComponents) {
|
||||||
|
if (rating->getScrollHide())
|
||||||
|
comps.emplace_back(rating.get());
|
||||||
|
}
|
||||||
|
for (auto& container : mContainerComponents) {
|
||||||
|
if (container->getScrollHide())
|
||||||
|
comps.emplace_back(container.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = comps.cbegin(); it != comps.cend(); ++it) {
|
||||||
|
GuiComponent* comp = *it;
|
||||||
|
// An animation is playing, then animate if reverse != fadingOut.
|
||||||
|
// An animation is not playing, then animate if opacity != our target opacity.
|
||||||
|
if ((comp->isAnimationPlaying(0) && comp->isAnimationReversed(0) != fadingOut) ||
|
||||||
|
(!comp->isAnimationPlaying(0) && comp->getOpacity() != (fadingOut ? 0 : 255))) {
|
||||||
|
auto func = [comp](float t) {
|
||||||
|
comp->setOpacity(static_cast<unsigned char>(glm::mix(0.0f, 1.0f, t) * 255));
|
||||||
|
};
|
||||||
|
comp->setAnimation(new LambdaAnimation(func, 150), 0, nullptr, fadingOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
class GamelistView : public GamelistBase
|
class GamelistView : public GamelistBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GamelistView(FileData* root, bool legacyMode = false);
|
GamelistView(FileData* root);
|
||||||
~GamelistView();
|
~GamelistView();
|
||||||
|
|
||||||
// Called when a FileData* is added, has its metadata changed, or is removed.
|
// Called when a FileData* is added, has its metadata changed, or is removed.
|
||||||
|
@ -76,9 +76,11 @@ private:
|
||||||
std::vector<std::unique_ptr<DateTimeComponent>> mDateTimeComponents;
|
std::vector<std::unique_ptr<DateTimeComponent>> mDateTimeComponents;
|
||||||
std::vector<std::unique_ptr<ImageComponent>> mImageComponents;
|
std::vector<std::unique_ptr<ImageComponent>> mImageComponents;
|
||||||
std::vector<std::unique_ptr<VideoFFmpegComponent>> mVideoComponents;
|
std::vector<std::unique_ptr<VideoFFmpegComponent>> mVideoComponents;
|
||||||
|
std::vector<std::unique_ptr<LottieComponent>> mLottieAnimComponents;
|
||||||
std::vector<std::unique_ptr<BadgeComponent>> mBadgeComponents;
|
std::vector<std::unique_ptr<BadgeComponent>> mBadgeComponents;
|
||||||
std::vector<std::unique_ptr<RatingComponent>> mRatingComponents;
|
std::vector<std::unique_ptr<RatingComponent>> mRatingComponents;
|
||||||
std::vector<std::unique_ptr<ScrollableContainer>> mScrollableContainerComponents;
|
std::vector<std::unique_ptr<ScrollableContainer>> mContainerComponents;
|
||||||
|
std::vector<std::unique_ptr<TextComponent>> mContainerTextComponents;
|
||||||
std::vector<std::unique_ptr<TextComponent>> mGamelistInfoComponents;
|
std::vector<std::unique_ptr<TextComponent>> mGamelistInfoComponents;
|
||||||
|
|
||||||
enum LegacyText {
|
enum LegacyText {
|
||||||
|
|
|
@ -76,7 +76,8 @@ void SystemView::populate()
|
||||||
glm::vec3 offsetLogoPlaceholderText = {0.0f, 0.0f, 0.0f};
|
glm::vec3 offsetLogoPlaceholderText = {0.0f, 0.0f, 0.0f};
|
||||||
|
|
||||||
// Make logo.
|
// Make logo.
|
||||||
const ThemeData::ThemeElement* logoElem = theme->getElement("system", "logo", "image");
|
const ThemeData::ThemeElement* logoElem =
|
||||||
|
theme->getElement("system", "image_logo", "image");
|
||||||
if (logoElem) {
|
if (logoElem) {
|
||||||
auto path = logoElem->get<std::string>("path");
|
auto path = logoElem->get<std::string>("path");
|
||||||
std::string defaultPath =
|
std::string defaultPath =
|
||||||
|
@ -86,7 +87,8 @@ void SystemView::populate()
|
||||||
ResourceManager::getInstance().fileExists(defaultPath))) {
|
ResourceManager::getInstance().fileExists(defaultPath))) {
|
||||||
auto* logo = new ImageComponent(false, false);
|
auto* logo = new ImageComponent(false, false);
|
||||||
logo->setMaxSize(glm::round(mCarousel.logoSize * mCarousel.logoScale));
|
logo->setMaxSize(glm::round(mCarousel.logoSize * mCarousel.logoScale));
|
||||||
logo->applyTheme(theme, "system", "logo", ThemeFlags::PATH | ThemeFlags::COLOR);
|
logo->applyTheme(theme, "system", "image_logo",
|
||||||
|
ThemeFlags::PATH | ThemeFlags::COLOR);
|
||||||
logo->setRotateByTargetSize(true);
|
logo->setRotateByTargetSize(true);
|
||||||
e.data.logo = std::shared_ptr<GuiComponent>(logo);
|
e.data.logo = std::shared_ptr<GuiComponent>(logo);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +102,7 @@ void SystemView::populate()
|
||||||
glm::vec3 center {resolution.x / 2.0f, resolution.y / 2.0f, 1.0f};
|
glm::vec3 center {resolution.x / 2.0f, resolution.y / 2.0f, 1.0f};
|
||||||
|
|
||||||
// Placeholder Image.
|
// Placeholder Image.
|
||||||
logoElem = theme->getElement("system", "logoPlaceholderImage", "image");
|
logoElem = theme->getElement("system", "image_logoPlaceholderImage", "image");
|
||||||
if (logoElem) {
|
if (logoElem) {
|
||||||
auto path = logoElem->get<std::string>("path");
|
auto path = logoElem->get<std::string>("path");
|
||||||
std::string defaultPath =
|
std::string defaultPath =
|
||||||
|
@ -109,7 +111,8 @@ void SystemView::populate()
|
||||||
(!defaultPath.empty() &&
|
(!defaultPath.empty() &&
|
||||||
ResourceManager::getInstance().fileExists(defaultPath))) {
|
ResourceManager::getInstance().fileExists(defaultPath))) {
|
||||||
auto* logo = new ImageComponent(false, false);
|
auto* logo = new ImageComponent(false, false);
|
||||||
logo->applyTheme(theme, "system", "logoPlaceholderImage", ThemeFlags::ALL);
|
logo->applyTheme(theme, "system", "image_logoPlaceholderImage",
|
||||||
|
ThemeFlags::ALL);
|
||||||
if (!logoElem->has("size"))
|
if (!logoElem->has("size"))
|
||||||
logo->setMaxSize(mCarousel.logoSize * mCarousel.logoScale);
|
logo->setMaxSize(mCarousel.logoSize * mCarousel.logoScale);
|
||||||
offsetLogo = logo->getPosition() - center;
|
offsetLogo = logo->getPosition() - center;
|
||||||
|
@ -120,7 +123,7 @@ void SystemView::populate()
|
||||||
|
|
||||||
// Placeholder Text.
|
// Placeholder Text.
|
||||||
const ThemeData::ThemeElement* logoPlaceholderText =
|
const ThemeData::ThemeElement* logoPlaceholderText =
|
||||||
theme->getElement("system", "logoPlaceholderText", "text");
|
theme->getElement("system", "text_logoPlaceholderText", "text");
|
||||||
if (logoPlaceholderText) {
|
if (logoPlaceholderText) {
|
||||||
// Element 'logoPlaceholderText' found in theme: place text
|
// Element 'logoPlaceholderText' found in theme: place text
|
||||||
auto* text = new TextComponent(it->getName(), Font::get(FONT_SIZE_LARGE),
|
auto* text = new TextComponent(it->getName(), Font::get(FONT_SIZE_LARGE),
|
||||||
|
@ -134,7 +137,7 @@ void SystemView::populate()
|
||||||
text->setHorizontalAlignment(ALIGN_CENTER);
|
text->setHorizontalAlignment(ALIGN_CENTER);
|
||||||
text->setVerticalAlignment(mCarousel.logoAlignment);
|
text->setVerticalAlignment(mCarousel.logoAlignment);
|
||||||
}
|
}
|
||||||
text->applyTheme(it->getTheme(), "system", "logoPlaceholderText",
|
text->applyTheme(it->getTheme(), "system", "text_logoPlaceholderText",
|
||||||
ThemeFlags::ALL);
|
ThemeFlags::ALL);
|
||||||
if (!e.data.logo) {
|
if (!e.data.logo) {
|
||||||
e.data.logo = std::shared_ptr<GuiComponent>(text);
|
e.data.logo = std::shared_ptr<GuiComponent>(text);
|
||||||
|
@ -541,15 +544,16 @@ void SystemView::getViewElements(const std::shared_ptr<ThemeData>& theme)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ThemeData::ThemeElement* carouselElem =
|
const ThemeData::ThemeElement* carouselElem =
|
||||||
theme->getElement("system", "systemcarousel", "carousel");
|
theme->getElement("system", "carousel_systemcarousel", "carousel");
|
||||||
|
|
||||||
if (carouselElem)
|
if (carouselElem)
|
||||||
getCarouselFromTheme(carouselElem);
|
getCarouselFromTheme(carouselElem);
|
||||||
|
|
||||||
const ThemeData::ThemeElement* sysInfoElem = theme->getElement("system", "systemInfo", "text");
|
const ThemeData::ThemeElement* sysInfoElem =
|
||||||
|
theme->getElement("system", "text_systemInfo", "text");
|
||||||
|
|
||||||
if (sysInfoElem)
|
if (sysInfoElem)
|
||||||
mSystemInfo.applyTheme(theme, "system", "systemInfo", ThemeFlags::ALL);
|
mSystemInfo.applyTheme(theme, "system", "text_systemInfo", ThemeFlags::ALL);
|
||||||
|
|
||||||
mViewNeedsReload = false;
|
mViewNeedsReload = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "resources/Font.h"
|
#include "resources/Font.h"
|
||||||
|
|
||||||
|
#define PREFIX "button_"
|
||||||
|
|
||||||
HelpStyle::HelpStyle()
|
HelpStyle::HelpStyle()
|
||||||
{
|
{
|
||||||
position =
|
position =
|
||||||
|
@ -32,7 +34,7 @@ HelpStyle::HelpStyle()
|
||||||
|
|
||||||
void HelpStyle::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view)
|
void HelpStyle::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view)
|
||||||
{
|
{
|
||||||
auto elem = theme->getElement(view, "help", "helpsystem");
|
auto elem = theme->getElement(view, "helpsystem_help", "helpsystem");
|
||||||
if (!elem)
|
if (!elem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -73,74 +75,76 @@ void HelpStyle::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::s
|
||||||
textStyle = elem->get<std::string>("textStyle");
|
textStyle = elem->get<std::string>("textStyle");
|
||||||
|
|
||||||
// Load custom button icons.
|
// Load custom button icons.
|
||||||
|
// The names may look a bit strange when combined with the PREFIX string "button_" but it's
|
||||||
|
// because ThemeData adds this prefix to avoid name collisions when using XML attributes.
|
||||||
|
|
||||||
// General.
|
// General.
|
||||||
if (elem->has("dpad_updown"))
|
if (elem->has(PREFIX "dpad_updown"))
|
||||||
mCustomButtons.dpad_updown = elem->get<std::string>("dpad_updown");
|
mCustomButtons.dpad_updown = elem->get<std::string>(PREFIX "dpad_updown");
|
||||||
if (elem->has("dpad_leftright"))
|
if (elem->has(PREFIX "dpad_leftright"))
|
||||||
mCustomButtons.dpad_leftright = elem->get<std::string>("dpad_leftright");
|
mCustomButtons.dpad_leftright = elem->get<std::string>(PREFIX "dpad_leftright");
|
||||||
if (elem->has("dpad_all"))
|
if (elem->has(PREFIX "dpad_all"))
|
||||||
mCustomButtons.dpad_all = elem->get<std::string>("dpad_all");
|
mCustomButtons.dpad_all = elem->get<std::string>(PREFIX "dpad_all");
|
||||||
if (elem->has("thumbstick_click"))
|
if (elem->has(PREFIX "thumbstick_click"))
|
||||||
mCustomButtons.thumbstick_click = elem->get<std::string>("thumbstick_click");
|
mCustomButtons.thumbstick_click = elem->get<std::string>(PREFIX "thumbstick_click");
|
||||||
if (elem->has("button_l"))
|
if (elem->has(PREFIX "button_l"))
|
||||||
mCustomButtons.button_l = elem->get<std::string>("button_l");
|
mCustomButtons.button_l = elem->get<std::string>(PREFIX "button_l");
|
||||||
if (elem->has("button_r"))
|
if (elem->has(PREFIX "button_r"))
|
||||||
mCustomButtons.button_r = elem->get<std::string>("button_r");
|
mCustomButtons.button_r = elem->get<std::string>(PREFIX "button_r");
|
||||||
if (elem->has("button_lr"))
|
if (elem->has(PREFIX "button_lr"))
|
||||||
mCustomButtons.button_lr = elem->get<std::string>("button_lr");
|
mCustomButtons.button_lr = elem->get<std::string>(PREFIX "button_lr");
|
||||||
if (elem->has("button_lt"))
|
if (elem->has(PREFIX "button_lt"))
|
||||||
mCustomButtons.button_lt = elem->get<std::string>("button_lt");
|
mCustomButtons.button_lt = elem->get<std::string>(PREFIX "button_lt");
|
||||||
if (elem->has("button_rt"))
|
if (elem->has(PREFIX "button_rt"))
|
||||||
mCustomButtons.button_rt = elem->get<std::string>("button_rt");
|
mCustomButtons.button_rt = elem->get<std::string>(PREFIX "button_rt");
|
||||||
|
|
||||||
// SNES.
|
// SNES.
|
||||||
if (elem->has("button_a_SNES"))
|
if (elem->has(PREFIX "button_a_SNES"))
|
||||||
mCustomButtons.button_a_SNES = elem->get<std::string>("button_a_SNES");
|
mCustomButtons.button_a_SNES = elem->get<std::string>(PREFIX "button_a_SNES");
|
||||||
if (elem->has("button_b_SNES"))
|
if (elem->has(PREFIX "button_b_SNES"))
|
||||||
mCustomButtons.button_b_SNES = elem->get<std::string>("button_b_SNES");
|
mCustomButtons.button_b_SNES = elem->get<std::string>(PREFIX "button_b_SNES");
|
||||||
if (elem->has("button_x_SNES"))
|
if (elem->has(PREFIX "button_x_SNES"))
|
||||||
mCustomButtons.button_x_SNES = elem->get<std::string>("button_x_SNES");
|
mCustomButtons.button_x_SNES = elem->get<std::string>(PREFIX "button_x_SNES");
|
||||||
if (elem->has("button_y_SNES"))
|
if (elem->has(PREFIX "button_y_SNES"))
|
||||||
mCustomButtons.button_y_SNES = elem->get<std::string>("button_y_SNES");
|
mCustomButtons.button_y_SNES = elem->get<std::string>(PREFIX "button_y_SNES");
|
||||||
if (elem->has("button_start_SNES"))
|
if (elem->has(PREFIX "button_start_SNES"))
|
||||||
mCustomButtons.button_start_SNES = elem->get<std::string>("button_start_SNES");
|
mCustomButtons.button_start_SNES = elem->get<std::string>(PREFIX "button_start_SNES");
|
||||||
if (elem->has("button_back_SNES"))
|
if (elem->has(PREFIX "button_back_SNES"))
|
||||||
mCustomButtons.button_back_SNES = elem->get<std::string>("button_back_SNES");
|
mCustomButtons.button_back_SNES = elem->get<std::string>(PREFIX "button_back_SNES");
|
||||||
|
|
||||||
// PS.
|
// PlayStation.
|
||||||
if (elem->has("button_a_PS"))
|
if (elem->has(PREFIX "button_a_PS"))
|
||||||
mCustomButtons.button_a_PS = elem->get<std::string>("button_a_PS");
|
mCustomButtons.button_a_PS = elem->get<std::string>(PREFIX "button_a_PS");
|
||||||
if (elem->has("button_b_PS"))
|
if (elem->has(PREFIX "button_b_PS"))
|
||||||
mCustomButtons.button_b_PS = elem->get<std::string>("button_b_PS");
|
mCustomButtons.button_b_PS = elem->get<std::string>(PREFIX "button_b_PS");
|
||||||
if (elem->has("button_x_PS"))
|
if (elem->has(PREFIX "button_x_PS"))
|
||||||
mCustomButtons.button_x_PS = elem->get<std::string>("button_x_PS");
|
mCustomButtons.button_x_PS = elem->get<std::string>(PREFIX "button_x_PS");
|
||||||
if (elem->has("button_y_PS"))
|
if (elem->has(PREFIX "button_y_PS"))
|
||||||
mCustomButtons.button_y_PS = elem->get<std::string>("button_y_PS");
|
mCustomButtons.button_y_PS = elem->get<std::string>(PREFIX "button_y_PS");
|
||||||
if (elem->has("button_start_PS4"))
|
if (elem->has(PREFIX "button_start_PS4"))
|
||||||
mCustomButtons.button_start_PS4 = elem->get<std::string>("button_start_PS4");
|
mCustomButtons.button_start_PS4 = elem->get<std::string>(PREFIX "button_start_PS4");
|
||||||
if (elem->has("button_back_PS4"))
|
if (elem->has(PREFIX "button_back_PS4"))
|
||||||
mCustomButtons.button_back_PS4 = elem->get<std::string>("button_back_PS4");
|
mCustomButtons.button_back_PS4 = elem->get<std::string>(PREFIX "button_back_PS4");
|
||||||
if (elem->has("button_start_PS5"))
|
if (elem->has(PREFIX "button_start_PS5"))
|
||||||
mCustomButtons.button_start_PS5 = elem->get<std::string>("button_start_PS5");
|
mCustomButtons.button_start_PS5 = elem->get<std::string>(PREFIX "button_start_PS5");
|
||||||
if (elem->has("button_back_PS5"))
|
if (elem->has(PREFIX "button_back_PS5"))
|
||||||
mCustomButtons.button_back_PS5 = elem->get<std::string>("button_back_PS5");
|
mCustomButtons.button_back_PS5 = elem->get<std::string>(PREFIX "button_back_PS5");
|
||||||
|
|
||||||
// XBOX.
|
// XBOX.
|
||||||
if (elem->has("button_a_XBOX"))
|
if (elem->has(PREFIX "button_a_XBOX"))
|
||||||
mCustomButtons.button_a_XBOX = elem->get<std::string>("button_a_XBOX");
|
mCustomButtons.button_a_XBOX = elem->get<std::string>(PREFIX "button_a_XBOX");
|
||||||
if (elem->has("button_b_XBOX"))
|
if (elem->has(PREFIX "button_b_XBOX"))
|
||||||
mCustomButtons.button_b_XBOX = elem->get<std::string>("button_b_XBOX");
|
mCustomButtons.button_b_XBOX = elem->get<std::string>(PREFIX "button_b_XBOX");
|
||||||
if (elem->has("button_x_XBOX"))
|
if (elem->has(PREFIX "button_x_XBOX"))
|
||||||
mCustomButtons.button_x_XBOX = elem->get<std::string>("button_x_XBOX");
|
mCustomButtons.button_x_XBOX = elem->get<std::string>(PREFIX "button_x_XBOX");
|
||||||
if (elem->has("button_y_XBOX"))
|
if (elem->has(PREFIX "button_y_XBOX"))
|
||||||
mCustomButtons.button_y_XBOX = elem->get<std::string>("button_y_XBOX");
|
mCustomButtons.button_y_XBOX = elem->get<std::string>(PREFIX "button_y_XBOX");
|
||||||
if (elem->has("button_start_XBOX"))
|
if (elem->has(PREFIX "button_start_XBOX"))
|
||||||
mCustomButtons.button_start_XBOX = elem->get<std::string>("button_start_XBOX");
|
mCustomButtons.button_start_XBOX = elem->get<std::string>(PREFIX "button_start_XBOX");
|
||||||
if (elem->has("button_back_XBOX"))
|
if (elem->has(PREFIX "button_back_XBOX"))
|
||||||
mCustomButtons.button_back_XBOX = elem->get<std::string>("button_back_XBOX");
|
mCustomButtons.button_back_XBOX = elem->get<std::string>(PREFIX "button_back_XBOX");
|
||||||
if (elem->has("button_start_XBOX360"))
|
if (elem->has(PREFIX "button_start_XBOX360"))
|
||||||
mCustomButtons.button_start_XBOX360 = elem->get<std::string>("button_start_XBOX360");
|
mCustomButtons.button_start_XBOX360 = elem->get<std::string>(PREFIX "button_start_XBOX360");
|
||||||
if (elem->has("button_back_XBOX360"))
|
if (elem->has(PREFIX "button_back_XBOX360"))
|
||||||
mCustomButtons.button_back_XBOX360 = elem->get<std::string>("button_back_XBOX360");
|
mCustomButtons.button_back_XBOX360 = elem->get<std::string>(PREFIX "button_back_XBOX360");
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,8 @@ void Settings::setDefaults()
|
||||||
mStringMap["GamelistViewStyle"] = {"automatic", "automatic"};
|
mStringMap["GamelistViewStyle"] = {"automatic", "automatic"};
|
||||||
mStringMap["TransitionStyle"] = {"slide", "slide"};
|
mStringMap["TransitionStyle"] = {"slide", "slide"};
|
||||||
mStringMap["ThemeSet"] = {"rbsimple-DE", "rbsimple-DE"};
|
mStringMap["ThemeSet"] = {"rbsimple-DE", "rbsimple-DE"};
|
||||||
|
mStringMap["ThemeVariant"] = {"", ""};
|
||||||
|
mStringMap["ThemeAspectRatio"] = {"", ""};
|
||||||
mStringMap["UIMode"] = {"full", "full"};
|
mStringMap["UIMode"] = {"full", "full"};
|
||||||
mStringMap["DefaultSortOrder"] = {"filename, ascending", "filename, ascending"};
|
mStringMap["DefaultSortOrder"] = {"filename, ascending", "filename, ascending"};
|
||||||
mStringMap["MenuOpeningEffect"] = {"scale-up", "scale-up"};
|
mStringMap["MenuOpeningEffect"] = {"scale-up", "scale-up"};
|
||||||
|
|
|
@ -33,18 +33,20 @@ std::shared_ptr<Sound> Sound::getFromTheme(ThemeData* const theme,
|
||||||
const std::string& view,
|
const std::string& view,
|
||||||
const std::string& element)
|
const std::string& element)
|
||||||
{
|
{
|
||||||
|
std::string elemName {element.substr(6, std::string::npos)};
|
||||||
|
|
||||||
if (theme == nullptr) {
|
if (theme == nullptr) {
|
||||||
LOG(LogDebug) << "Sound::getFromTheme(): Using fallback sound file for \"" << element
|
LOG(LogDebug) << "Sound::getFromTheme(): Using fallback sound file for \"" << elemName
|
||||||
<< "\"";
|
<< "\"";
|
||||||
return get(ResourceManager::getInstance().getResourcePath(":/sounds/" + element + ".wav"));
|
return get(ResourceManager::getInstance().getResourcePath(":/sounds/" + elemName + ".wav"));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(LogDebug) << "Sound::getFromTheme(): Looking for tag <sound name=\"" << element << "\">";
|
LOG(LogDebug) << "Sound::getFromTheme(): Looking for tag <sound name=\"" << elemName << "\">";
|
||||||
|
|
||||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "sound");
|
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "sound");
|
||||||
if (!elem || !elem->has("path")) {
|
if (!elem || !elem->has("path")) {
|
||||||
LOG(LogDebug) << "Sound::getFromTheme(): Tag not found, using fallback sound file";
|
LOG(LogDebug) << "Sound::getFromTheme(): Tag not found, using fallback sound file";
|
||||||
return get(ResourceManager::getInstance().getResourcePath(":/sounds/" + element + ".wav"));
|
return get(ResourceManager::getInstance().getResourcePath(":/sounds/" + elemName + ".wav"));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(LogDebug) << "Sound::getFromTheme(): Tag found, ready to load theme sound file";
|
LOG(LogDebug) << "Sound::getFromTheme(): Tag found, ready to load theme sound file";
|
||||||
|
@ -79,8 +81,7 @@ void Sound::init()
|
||||||
Uint8* data = nullptr;
|
Uint8* data = nullptr;
|
||||||
Uint32 dlen = 0;
|
Uint32 dlen = 0;
|
||||||
if (SDL_LoadWAV(mPath.c_str(), &wave, &data, &dlen) == nullptr) {
|
if (SDL_LoadWAV(mPath.c_str(), &wave, &data, &dlen) == nullptr) {
|
||||||
LOG(LogError) << "Failed to load theme navigation sound file:";
|
LOG(LogError) << "Failed to load theme navigation sound file: " << SDL_GetError();
|
||||||
LOG(LogError) << SDL_GetError();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,14 +91,12 @@ void Sound::init()
|
||||||
AudioManager::sAudioFormat.channels, AudioManager::sAudioFormat.freq);
|
AudioManager::sAudioFormat.channels, AudioManager::sAudioFormat.freq);
|
||||||
|
|
||||||
if (conversionStream == nullptr) {
|
if (conversionStream == nullptr) {
|
||||||
LOG(LogError) << "Failed to create sample conversion stream:";
|
LOG(LogError) << "Failed to create sample conversion stream: " << SDL_GetError();
|
||||||
LOG(LogError) << SDL_GetError();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_AudioStreamPut(conversionStream, data, dlen) == -1) {
|
if (SDL_AudioStreamPut(conversionStream, data, dlen) == -1) {
|
||||||
LOG(LogError) << "Failed to put samples in the conversion stream:";
|
LOG(LogError) << "Failed to put samples in the conversion stream: " << SDL_GetError();
|
||||||
LOG(LogError) << SDL_GetError();
|
|
||||||
SDL_FreeAudioStream(conversionStream);
|
SDL_FreeAudioStream(conversionStream);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -106,8 +105,7 @@ void Sound::init()
|
||||||
|
|
||||||
Uint8* converted = new Uint8[sampleLength];
|
Uint8* converted = new Uint8[sampleLength];
|
||||||
if (SDL_AudioStreamGet(conversionStream, converted, sampleLength) == -1) {
|
if (SDL_AudioStreamGet(conversionStream, converted, sampleLength) == -1) {
|
||||||
LOG(LogError) << "Failed to convert sound file '" << mPath << "':";
|
LOG(LogError) << "Failed to convert sound file '" << mPath << "': " << SDL_GetError();
|
||||||
LOG(LogError) << SDL_GetError();
|
|
||||||
SDL_FreeAudioStream(conversionStream);
|
SDL_FreeAudioStream(conversionStream);
|
||||||
delete[] converted;
|
delete[] converted;
|
||||||
return;
|
return;
|
||||||
|
@ -209,13 +207,13 @@ void NavigationSounds::loadThemeNavigationSounds(ThemeData* const theme)
|
||||||
"Theme set does not include navigation sound support, using fallback sounds";
|
"Theme set does not include navigation sound support, using fallback sounds";
|
||||||
}
|
}
|
||||||
|
|
||||||
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "systembrowse"));
|
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "sound_systembrowse"));
|
||||||
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "quicksysselect"));
|
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "sound_quicksysselect"));
|
||||||
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "select"));
|
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "sound_select"));
|
||||||
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "back"));
|
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "sound_back"));
|
||||||
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "scroll"));
|
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "sound_scroll"));
|
||||||
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "favorite"));
|
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "sound_favorite"));
|
||||||
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "launch"));
|
mNavigationSounds.push_back(Sound::getFromTheme(theme, "all", "sound_launch"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigationSounds::playThemeNavigationSound(NavigationSoundsID soundID)
|
void NavigationSounds::playThemeNavigationSound(NavigationSoundsID soundID)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,9 +3,9 @@
|
||||||
// EmulationStation Desktop Edition
|
// EmulationStation Desktop Edition
|
||||||
// ThemeData.h
|
// ThemeData.h
|
||||||
//
|
//
|
||||||
// Finds available themes on the file system and loads these,
|
// Finds available themes on the file system and loads and parses these.
|
||||||
// including the parsing of individual theme components
|
// Basic error checking for valid elements and data types is done here,
|
||||||
// (includes, features, variables, views, elements).
|
// with additional validation handled by the individual components.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef ES_CORE_THEME_DATA_H
|
#ifndef ES_CORE_THEME_DATA_H
|
||||||
|
@ -158,8 +158,31 @@ public:
|
||||||
|
|
||||||
ThemeData();
|
ThemeData();
|
||||||
|
|
||||||
|
class ThemeView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::map<std::string, ThemeElement> elements;
|
||||||
|
std::vector<std::string> legacyOrderedKeys;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThemeVariant {
|
||||||
|
std::string name;
|
||||||
|
std::string label;
|
||||||
|
bool selectable;
|
||||||
|
bool override;
|
||||||
|
std::string overrideTrigger;
|
||||||
|
std::string overrideVariant;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThemeCapability {
|
||||||
|
std::vector<ThemeVariant> variants;
|
||||||
|
std::vector<std::string> aspectRatios;
|
||||||
|
bool legacyTheme;
|
||||||
|
};
|
||||||
|
|
||||||
struct ThemeSet {
|
struct ThemeSet {
|
||||||
std::string path;
|
std::string path;
|
||||||
|
ThemeCapability capabilities;
|
||||||
|
|
||||||
std::string getName() const { return Utils::FileSystem::getStem(path); }
|
std::string getName() const { return Utils::FileSystem::getStem(path); }
|
||||||
std::string getThemePath(const std::string& system) const
|
std::string getThemePath(const std::string& system) const
|
||||||
|
@ -168,21 +191,22 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Throws ThemeException.
|
|
||||||
void loadFile(const std::map<std::string, std::string>& sysDataMap, const std::string& path);
|
void loadFile(const std::map<std::string, std::string>& sysDataMap, const std::string& path);
|
||||||
bool hasView(const std::string& view);
|
bool hasView(const std::string& view);
|
||||||
|
ThemeView& getViewElements(std::string view) { return mViews[view]; }
|
||||||
|
|
||||||
static std::vector<GuiComponent*> makeExtras(const std::shared_ptr<ThemeData>& theme,
|
static std::vector<GuiComponent*> makeExtras(const std::shared_ptr<ThemeData>& theme,
|
||||||
const std::string& view);
|
const std::string& view);
|
||||||
|
|
||||||
// If expectedType is an empty string, then do no type checking.
|
|
||||||
const ThemeElement* getElement(const std::string& view,
|
const ThemeElement* getElement(const std::string& view,
|
||||||
const std::string& element,
|
const std::string& element,
|
||||||
const std::string& expectedType) const;
|
const std::string& expectedType) const;
|
||||||
|
|
||||||
static std::map<std::string, ThemeSet> getThemeSets();
|
static std::map<std::string, ThemeSet>& getThemeSets();
|
||||||
static std::string getThemeFromCurrentSet(const std::string& system);
|
static std::string getThemeFromCurrentSet(const std::string& system);
|
||||||
|
|
||||||
|
const bool isLegacyTheme() { return mLegacyTheme; }
|
||||||
|
|
||||||
enum ElementPropertyType {
|
enum ElementPropertyType {
|
||||||
NORMALIZED_RECT,
|
NORMALIZED_RECT,
|
||||||
NORMALIZED_PAIR,
|
NORMALIZED_PAIR,
|
||||||
|
@ -196,26 +220,16 @@ public:
|
||||||
std::map<std::string, std::string> mVariables;
|
std::map<std::string, std::string> mVariables;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ThemeView
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::map<std::string, ThemeElement> elements;
|
|
||||||
std::vector<std::string> orderedKeys;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::map<std::string, std::map<std::string, ElementPropertyType>> sElementMap;
|
|
||||||
static std::vector<std::string> sSupportedFeatures;
|
|
||||||
static std::vector<std::string> sSupportedViews;
|
|
||||||
|
|
||||||
std::deque<std::string> mPaths;
|
|
||||||
float mVersion;
|
|
||||||
|
|
||||||
static const std::shared_ptr<ThemeData> getDefault();
|
static const std::shared_ptr<ThemeData> getDefault();
|
||||||
unsigned int getHexColor(const std::string& str);
|
unsigned int getHexColor(const std::string& str);
|
||||||
std::string resolvePlaceholders(const std::string& in);
|
std::string resolvePlaceholders(const std::string& in);
|
||||||
|
|
||||||
|
static ThemeCapability parseThemeCapabilities(const std::string& path);
|
||||||
|
|
||||||
void parseIncludes(const pugi::xml_node& themeRoot);
|
void parseIncludes(const pugi::xml_node& themeRoot);
|
||||||
void parseFeatures(const pugi::xml_node& themeRoot);
|
void parseFeatures(const pugi::xml_node& themeRoot);
|
||||||
|
void parseVariants(const pugi::xml_node& themeRoot);
|
||||||
|
void parseAspectRatios(const pugi::xml_node& themeRoot);
|
||||||
void parseVariables(const pugi::xml_node& root);
|
void parseVariables(const pugi::xml_node& root);
|
||||||
void parseViews(const pugi::xml_node& themeRoot);
|
void parseViews(const pugi::xml_node& themeRoot);
|
||||||
void parseView(const pugi::xml_node& viewNode, ThemeView& view);
|
void parseView(const pugi::xml_node& viewNode, ThemeView& view);
|
||||||
|
@ -223,7 +237,24 @@ private:
|
||||||
const std::map<std::string, ElementPropertyType>& typeMap,
|
const std::map<std::string, ElementPropertyType>& typeMap,
|
||||||
ThemeElement& element);
|
ThemeElement& element);
|
||||||
|
|
||||||
|
static std::map<std::string, std::map<std::string, ElementPropertyType>> sElementMap;
|
||||||
|
static std::map<std::string, std::map<std::string, std::string>> sPropertyAttributeMap;
|
||||||
|
|
||||||
|
static std::vector<std::string> sLegacySupportedFeatures;
|
||||||
|
static std::vector<std::string> sLegacySupportedViews;
|
||||||
|
static std::vector<std::string> sSupportedViews;
|
||||||
|
static std::vector<std::string> sSupportedAspectRatios;
|
||||||
|
|
||||||
|
static inline std::map<std::string, ThemeSet> mThemeSets;
|
||||||
|
std::map<std::string, ThemeData::ThemeSet>::iterator mCurrentThemeSet;
|
||||||
|
|
||||||
std::map<std::string, ThemeView> mViews;
|
std::map<std::string, ThemeView> mViews;
|
||||||
|
std::deque<std::string> mPaths;
|
||||||
|
std::vector<std::string> mVariants;
|
||||||
|
std::vector<std::string> mAspectRatios;
|
||||||
|
std::string mSelectedVariant;
|
||||||
|
std::string mSelectedAspectRatio;
|
||||||
|
bool mLegacyTheme;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_CORE_THEME_DATA_H
|
#endif // ES_CORE_THEME_DATA_H
|
||||||
|
|
|
@ -290,8 +290,10 @@ void BadgeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
|
|
||||||
for (auto slot : slots) {
|
for (auto slot : slots) {
|
||||||
if (std::find(mBadgeTypes.cbegin(), mBadgeTypes.cend(), slot) != mBadgeTypes.end()) {
|
if (std::find(mBadgeTypes.cbegin(), mBadgeTypes.cend(), slot) != mBadgeTypes.end()) {
|
||||||
if (properties & PATH && elem->has(slot))
|
// The "badge_" string is required as ThemeData adds this as a prefix to avoid
|
||||||
mBadgeIcons[slot] = elem->get<std::string>(slot);
|
// name collisions when using XML attributes.
|
||||||
|
if (properties & PATH && elem->has("badge_" + slot))
|
||||||
|
mBadgeIcons[slot] = elem->get<std::string>("badge_" + slot);
|
||||||
|
|
||||||
FlexboxComponent::FlexboxItem item;
|
FlexboxComponent::FlexboxItem item;
|
||||||
item.label = slot;
|
item.label = slot;
|
||||||
|
@ -309,8 +311,9 @@ void BadgeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& gameController : sGameControllers) {
|
for (auto& gameController : sGameControllers) {
|
||||||
if (properties & PATH && elem->has(gameController.shortName))
|
if (properties & PATH && elem->has("controller_" + gameController.shortName))
|
||||||
gameController.fileName = elem->get<std::string>(gameController.shortName);
|
gameController.fileName =
|
||||||
|
elem->get<std::string>("controller_" + gameController.shortName);
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiComponent::applyTheme(theme, view, element, properties);
|
GuiComponent::applyTheme(theme, view, element, properties);
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
unsigned int properties) override;
|
unsigned int properties) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static std::vector<GameControllers> sGameControllers;
|
static inline std::vector<GameControllers> sGameControllers;
|
||||||
|
|
||||||
std::vector<FlexboxComponent::FlexboxItem> mFlexboxItems;
|
std::vector<FlexboxComponent::FlexboxItem> mFlexboxItems;
|
||||||
FlexboxComponent mFlexboxComponent;
|
FlexboxComponent mFlexboxComponent;
|
||||||
|
|
|
@ -111,7 +111,6 @@ void DateTimeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
unsigned int properties)
|
unsigned int properties)
|
||||||
{
|
{
|
||||||
GuiComponent::applyTheme(theme, view, element, properties);
|
GuiComponent::applyTheme(theme, view, element, properties);
|
||||||
|
|
||||||
using namespace ThemeFlags;
|
using namespace ThemeFlags;
|
||||||
|
|
||||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "datetime");
|
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "datetime");
|
||||||
|
|
|
@ -475,7 +475,6 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
unsigned int properties)
|
unsigned int properties)
|
||||||
{
|
{
|
||||||
using namespace ThemeFlags;
|
using namespace ThemeFlags;
|
||||||
|
|
||||||
GuiComponent::applyTheme(theme, view, element,
|
GuiComponent::applyTheme(theme, view, element,
|
||||||
(properties ^ ThemeFlags::SIZE) |
|
(properties ^ ThemeFlags::SIZE) |
|
||||||
((properties & (ThemeFlags::SIZE | POSITION)) ? ORIGIN : 0));
|
((properties & (ThemeFlags::SIZE | POSITION)) ? ORIGIN : 0));
|
||||||
|
@ -505,6 +504,9 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
setImage(elem->get<std::string>("path"), tile);
|
setImage(elem->get<std::string>("path"), tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties & METADATA && elem->has("metadata"))
|
||||||
|
setMetadataField(elem->get<std::string>("metadata"));
|
||||||
|
|
||||||
if (properties & COLOR) {
|
if (properties & COLOR) {
|
||||||
if (elem->has("color"))
|
if (elem->has("color"))
|
||||||
setColorShift(elem->get<unsigned int>("color"));
|
setColorShift(elem->get<unsigned int>("color"));
|
||||||
|
|
|
@ -214,7 +214,6 @@ void LottieComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
unsigned int properties)
|
unsigned int properties)
|
||||||
{
|
{
|
||||||
using namespace ThemeFlags;
|
using namespace ThemeFlags;
|
||||||
|
|
||||||
const ThemeData::ThemeElement* elem {theme->getElement(view, element, "animation")};
|
const ThemeData::ThemeElement* elem {theme->getElement(view, element, "animation")};
|
||||||
|
|
||||||
if (elem->has("size")) {
|
if (elem->has("size")) {
|
||||||
|
|
|
@ -50,8 +50,8 @@ private:
|
||||||
std::vector<uint8_t> mPictureRGBA;
|
std::vector<uint8_t> mPictureRGBA;
|
||||||
std::unordered_map<size_t, std::vector<uint8_t>> mFrameCache;
|
std::unordered_map<size_t, std::vector<uint8_t>> mFrameCache;
|
||||||
// Set a 1024 MiB total Lottie animation cache as default.
|
// Set a 1024 MiB total Lottie animation cache as default.
|
||||||
inline static size_t mMaxTotalFrameCache = 1024 * 1024 * 1024;
|
static inline size_t mMaxTotalFrameCache = 1024 * 1024 * 1024;
|
||||||
inline static size_t mTotalFrameCache;
|
static inline size_t mTotalFrameCache;
|
||||||
bool mCacheFrames;
|
bool mCacheFrames;
|
||||||
size_t mMaxCacheSize;
|
size_t mMaxCacheSize;
|
||||||
size_t mCacheSize;
|
size_t mCacheSize;
|
||||||
|
|
|
@ -211,7 +211,6 @@ void RatingComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
unsigned int properties)
|
unsigned int properties)
|
||||||
{
|
{
|
||||||
using namespace ThemeFlags;
|
using namespace ThemeFlags;
|
||||||
|
|
||||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "rating");
|
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "rating");
|
||||||
if (!elem)
|
if (!elem)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -291,11 +291,15 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
const std::string& element,
|
const std::string& element,
|
||||||
unsigned int properties)
|
unsigned int properties)
|
||||||
{
|
{
|
||||||
|
using namespace ThemeFlags;
|
||||||
GuiComponent::applyTheme(theme, view, element, properties);
|
GuiComponent::applyTheme(theme, view, element, properties);
|
||||||
|
|
||||||
using namespace ThemeFlags;
|
std::string elementType {"text"};
|
||||||
|
|
||||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "text");
|
if (element.substr(0, 13) == "gamelistinfo_")
|
||||||
|
elementType = "gamelistinfo";
|
||||||
|
|
||||||
|
const ThemeData::ThemeElement* elem = theme->getElement(view, element, elementType);
|
||||||
if (!elem)
|
if (!elem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -75,13 +75,13 @@ bool VideoComponent::setVideo(std::string path)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoComponent::setImage(std::string path)
|
void VideoComponent::setImage(const std::string& path, bool tile, bool linearMagnify)
|
||||||
{
|
{
|
||||||
// Check that the image has changed.
|
// Check that the image has changed.
|
||||||
if (path == mStaticImagePath)
|
if (path == mStaticImagePath)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mStaticImage.setImage(path);
|
mStaticImage.setImage(path, tile, linearMagnify);
|
||||||
mStaticImagePath = path;
|
mStaticImagePath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +212,6 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
unsigned int properties)
|
unsigned int properties)
|
||||||
{
|
{
|
||||||
using namespace ThemeFlags;
|
using namespace ThemeFlags;
|
||||||
|
|
||||||
GuiComponent::applyTheme(theme, view, element,
|
GuiComponent::applyTheme(theme, view, element,
|
||||||
(properties ^ ThemeFlags::SIZE) |
|
(properties ^ ThemeFlags::SIZE) |
|
||||||
((properties & (ThemeFlags::SIZE | POSITION)) ? ORIGIN : 0));
|
((properties & (ThemeFlags::SIZE | POSITION)) ? ORIGIN : 0));
|
||||||
|
@ -245,14 +244,24 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
if (elem->has("default"))
|
if (elem->has("default"))
|
||||||
mConfig.defaultVideoPath = elem->get<std::string>("default");
|
mConfig.defaultVideoPath = elem->get<std::string>("default");
|
||||||
|
|
||||||
|
if (elem->has("path"))
|
||||||
|
mConfig.staticVideoPath = elem->get<std::string>("path");
|
||||||
|
|
||||||
if ((properties & ThemeFlags::DELAY) && elem->has("delay"))
|
if ((properties & ThemeFlags::DELAY) && elem->has("delay"))
|
||||||
mConfig.startDelay = static_cast<unsigned>((elem->get<float>("delay") * 1000.0f));
|
mConfig.startDelay = static_cast<unsigned>((elem->get<float>("delay") * 1000.0f));
|
||||||
|
|
||||||
if (elem->has("showSnapshotNoVideo"))
|
if (!theme->isLegacyTheme())
|
||||||
|
mConfig.showSnapshotNoVideo = true;
|
||||||
|
else if (elem->has("showSnapshotNoVideo"))
|
||||||
mConfig.showSnapshotNoVideo = elem->get<bool>("showSnapshotNoVideo");
|
mConfig.showSnapshotNoVideo = elem->get<bool>("showSnapshotNoVideo");
|
||||||
|
|
||||||
if (elem->has("showSnapshotDelay"))
|
if (!theme->isLegacyTheme() && mConfig.startDelay != 0)
|
||||||
|
mConfig.showSnapshotDelay = true;
|
||||||
|
else if (elem->has("showSnapshotDelay"))
|
||||||
mConfig.showSnapshotDelay = elem->get<bool>("showSnapshotDelay");
|
mConfig.showSnapshotDelay = elem->get<bool>("showSnapshotDelay");
|
||||||
|
|
||||||
|
if (properties & METADATA && elem->has("imageMetadata"))
|
||||||
|
setMetadataField(elem->get<std::string>("imageMetadata"));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<HelpPrompt> VideoComponent::getHelpPrompts()
|
std::vector<HelpPrompt> VideoComponent::getHelpPrompts()
|
||||||
|
|
|
@ -26,6 +26,7 @@ class VideoComponent : public GuiComponent
|
||||||
bool showSnapshotNoVideo;
|
bool showSnapshotNoVideo;
|
||||||
bool showSnapshotDelay;
|
bool showSnapshotDelay;
|
||||||
std::string defaultVideoPath;
|
std::string defaultVideoPath;
|
||||||
|
std::string staticVideoPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -36,8 +37,10 @@ public:
|
||||||
bool setVideo(std::string path);
|
bool setVideo(std::string path);
|
||||||
// Configures the component to show the default video.
|
// Configures the component to show the default video.
|
||||||
void setDefaultVideo() { setVideo(mConfig.defaultVideoPath); }
|
void setDefaultVideo() { setVideo(mConfig.defaultVideoPath); }
|
||||||
|
// Configures the component to show the static video.
|
||||||
|
void setStaticVideo() { setVideo(mConfig.staticVideoPath); }
|
||||||
// Loads a static image that is displayed if the video cannot be played.
|
// Loads a static image that is displayed if the video cannot be played.
|
||||||
void setImage(std::string path);
|
void setImage(const std::string& path, bool tile = false, bool linearMagnify = false);
|
||||||
// Sets whether we're in media viewer mode.
|
// Sets whether we're in media viewer mode.
|
||||||
void setMediaViewerMode(bool isMediaViewer) { mMediaViewerMode = isMediaViewer; }
|
void setMediaViewerMode(bool isMediaViewer) { mMediaViewerMode = isMediaViewer; }
|
||||||
// Sets whether we're in screensaver mode.
|
// Sets whether we're in screensaver mode.
|
||||||
|
@ -45,6 +48,8 @@ public:
|
||||||
// Set the opacity for the embedded static image.
|
// Set the opacity for the embedded static image.
|
||||||
void setOpacity(unsigned char opacity) override { mOpacity = opacity; }
|
void setOpacity(unsigned char opacity) override { mOpacity = opacity; }
|
||||||
|
|
||||||
|
bool hasStaticVideo() { return !mConfig.staticVideoPath.empty(); }
|
||||||
|
|
||||||
void onShow() override;
|
void onShow() override;
|
||||||
void onHide() override;
|
void onHide() override;
|
||||||
void onStopVideo() override;
|
void onStopVideo() override;
|
||||||
|
|
|
@ -215,6 +215,7 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans)
|
||||||
Renderer::drawTriangleStrips(&vertices[0], 4, trans);
|
Renderer::drawTriangleStrips(&vertices[0], 4, trans);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (mVisible)
|
||||||
VideoComponent::renderSnapshot(parentTrans);
|
VideoComponent::renderSnapshot(parentTrans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue