diff --git a/es-app/src/views/GamelistBase.cpp b/es-app/src/views/GamelistBase.cpp index 78faec534..64a630705 100644 --- a/es-app/src/views/GamelistBase.cpp +++ b/es-app/src/views/GamelistBase.cpp @@ -557,15 +557,43 @@ void GamelistBase::populateList(const std::vector& files, FileData* f auto theme = mRoot->getSystem()->getTheme(); std::string name; + std::string carouselItemType; + std::string carouselDefaultItem; unsigned int color {0}; + if (mCarousel != nullptr) { + carouselItemType = mCarousel->getItemType(); + carouselDefaultItem = mCarousel->getDefaultItem(); + } + if (files.size() > 0) { for (auto it = files.cbegin(); it != files.cend(); ++it) { if (mCarousel != nullptr) { + assert(carouselItemType != ""); + CarouselComponent::Entry carouselEntry; carouselEntry.name = (*it)->getName(); carouselEntry.object = *it; - carouselEntry.data.logoPath = (*it)->getMarqueePath(); + if (carouselItemType == "" || carouselItemType == "marquee") + carouselEntry.data.logoPath = (*it)->getMarqueePath(); + else if (carouselItemType == "cover") + carouselEntry.data.logoPath = (*it)->getCoverPath(); + else if (carouselItemType == "3dbox") + carouselEntry.data.logoPath = (*it)->get3DBoxPath(); + else if (carouselItemType == "screenshot") + carouselEntry.data.logoPath = (*it)->getScreenshotPath(); + else if (carouselItemType == "titlescreen") + carouselEntry.data.logoPath = (*it)->getTitleScreenPath(); + else if (carouselItemType == "backcover") + carouselEntry.data.logoPath = (*it)->getBackCoverPath(); + else if (carouselItemType == "miximage") + carouselEntry.data.logoPath = (*it)->getMiximagePath(); + else if (carouselItemType == "fanart") + carouselEntry.data.logoPath = (*it)->getFanArtPath(); + + if (carouselDefaultItem != "") + carouselEntry.data.defaultLogoPath = carouselDefaultItem; + mCarousel->addEntry(carouselEntry, theme); } diff --git a/es-app/src/views/GamelistView.cpp b/es-app/src/views/GamelistView.cpp index 685e10817..cd362d9f0 100644 --- a/es-app/src/views/GamelistView.cpp +++ b/es-app/src/views/GamelistView.cpp @@ -136,6 +136,27 @@ void GamelistView::onThemeChanged(const std::shared_ptr& theme) if (element.second.type == "carousel") { if (mCarousel == nullptr) { mCarousel = std::make_unique>(); + if (element.second.has("itemType")) { + const std::string itemType {element.second.get("itemType")}; + if (itemType == "marquee" || itemType == "cover" || itemType == "3dbox" || + itemType == "screenshot" || itemType == "titlescreen" || + itemType == "backcover" || itemType == "miximage" || + itemType == "fanart") { + mCarousel->setItemType(itemType); + } + else { + LOG(LogWarning) + << "GamelistView::onThemeChanged(): Invalid theme configuration, " + " property defined as \"" + << itemType << "\""; + mCarousel->setItemType("marquee"); + } + } + else { + mCarousel->setItemType("marquee"); + } + if (element.second.has("defaultItem")) + mCarousel->setDefaultItem(element.second.get("defaultItem")); mPrimary = mCarousel.get(); } mPrimary->setCursorChangedCallback( diff --git a/es-app/src/views/SystemView.cpp b/es-app/src/views/SystemView.cpp index b79f9f126..201871820 100644 --- a/es-app/src/views/SystemView.cpp +++ b/es-app/src/views/SystemView.cpp @@ -466,10 +466,10 @@ void SystemView::populate() } }); if (mCarousel != nullptr) { - if (element.second.has("logo")) - logoPath = element.second.get("logo"); - if (element.second.has("defaultLogo")) - defaultLogoPath = element.second.get("defaultLogo"); + if (element.second.has("staticItem")) + logoPath = element.second.get("staticItem"); + if (element.second.has("defaultItem")) + defaultLogoPath = element.second.get("defaultItem"); } } else if (element.second.type == "image") { diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index 09065b66b..c49471345 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -48,7 +48,13 @@ std::vector ThemeData::sLegacyElements { {"showSnapshotDelay"}, {"forceUppercase"}, {"alignment"}, - {"logoAlignment"}}; + {"defaultLogo"}, + {"logoSize"}, + {"logoScale"}, + {"logoRotation"}, + {"logoRotationOrigin"}, + {"logoAlignment"}, + {"maxLogoCount"}}; std::vector> ThemeData::sSupportedAspectRatios { {"16:9", "16:9"}, @@ -120,8 +126,8 @@ std::map> {"saturation", FLOAT}, {"visible", BOOLEAN}, {"zIndex", FLOAT}, - {"showSnapshotNoVideo", BOOLEAN}, // For backward compatibility with legacy themes. - {"showSnapshotDelay", BOOLEAN}}}, // For backward compatibility with legacy themes. + {"showSnapshotNoVideo", BOOLEAN}, // For backward compatibility with legacy themes. + {"showSnapshotDelay", BOOLEAN}}}, // For backward compatibility with legacy themes. {"animation", {{"pos", NORMALIZED_PAIR}, {"size", NORMALIZED_PAIR}, @@ -144,7 +150,7 @@ std::map> {"rotation", FLOAT}, {"rotationOrigin", NORMALIZED_PAIR}, {"horizontalAlignment", STRING}, - {"alignment", STRING}, // For backward compatibility with legacy themes. + {"alignment", STRING}, // For backward compatibility with legacy themes. {"direction", STRING}, {"lines", UNSIGNED_INTEGER}, {"itemsPerLine", UNSIGNED_INTEGER}, @@ -178,11 +184,11 @@ std::map> {"fontSize", FLOAT}, {"horizontalAlignment", STRING}, {"verticalAlignment", STRING}, - {"alignment", STRING}, // For backward compatibility with legacy themes. + {"alignment", STRING}, // For backward compatibility with legacy themes. {"color", COLOR}, {"backgroundColor", COLOR}, {"letterCase", STRING}, - {"forceUppercase", BOOLEAN}, // For backward compatibility with legacy themes. + {"forceUppercase", BOOLEAN}, // For backward compatibility with legacy themes. {"lineSpacing", FLOAT}, {"opacity", FLOAT}, {"visible", BOOLEAN}, @@ -199,11 +205,11 @@ std::map> {"fontSize", FLOAT}, {"horizontalAlignment", STRING}, {"verticalAlignment", STRING}, - {"alignment", STRING}, // For backward compatibility with legacy themes. + {"alignment", STRING}, // For backward compatibility with legacy themes. {"color", COLOR}, {"backgroundColor", COLOR}, {"letterCase", STRING}, - {"forceUppercase", BOOLEAN}, // For backward compatibility with legacy themes. + {"forceUppercase", BOOLEAN}, // For backward compatibility with legacy themes. {"lineSpacing", FLOAT}, {"format", STRING}, {"displayRelative", BOOLEAN}, @@ -222,7 +228,7 @@ std::map> {"backgroundColor", COLOR}, {"horizontalAlignment", STRING}, {"verticalAlignment", STRING}, - {"alignment", STRING}, // For backward compatibility with legacy themes. + {"alignment", STRING}, // For backward compatibility with legacy themes. {"opacity", FLOAT}, {"visible", BOOLEAN}, {"zIndex", FLOAT}}}, @@ -247,16 +253,23 @@ std::map> {"color", COLOR}, {"colorEnd", COLOR}, {"gradientType", STRING}, - {"logo", PATH}, - {"defaultLogo", PATH}, - {"logoSize", NORMALIZED_PAIR}, - {"logoScale", FLOAT}, - {"logoRotation", FLOAT}, - {"logoRotationOrigin", NORMALIZED_PAIR}, - {"logoHorizontalAlignment", STRING}, - {"logoVerticalAlignment", STRING}, - {"logoAlignment", STRING}, // For backward compatibility with legacy themes. - {"maxLogoCount", FLOAT}, + {"staticItem", PATH}, + {"itemType", STRING}, + {"defaultItem", PATH}, + {"itemSize", NORMALIZED_PAIR}, + {"itemScale", FLOAT}, + {"itemRotation", FLOAT}, + {"itemRotationOrigin", NORMALIZED_PAIR}, + {"itemHorizontalAlignment", STRING}, + {"itemVerticalAlignment", STRING}, + {"maxItemCount", FLOAT}, + {"defaultLogo", PATH}, // For backward compatibility with legacy themes. + {"logoSize", NORMALIZED_PAIR}, // For backward compatibility with legacy themes. + {"logoScale", FLOAT}, // For backward compatibility with legacy themes. + {"logoRotation", FLOAT}, // For backward compatibility with legacy themes. + {"logoRotationOrigin", NORMALIZED_PAIR}, // For backward compatibility with legacy themes. + {"logoAlignment", STRING}, // For backward compatibility with legacy themes. + {"maxLogoCount", FLOAT}, // For backward compatibility with legacy themes. {"text", STRING}, {"textColor", COLOR}, {"textBackgroundColor", COLOR}, @@ -265,7 +278,7 @@ std::map> {"fontSize", FLOAT}, {"lineSpacing", FLOAT}, {"zIndex", FLOAT}, - {"legacyZIndexMode", STRING}}}, // For backward compatibility with legacy themes. + {"legacyZIndexMode", STRING}}}, // For backward compatibility with legacy themes. {"textlist", {{"pos", NORMALIZED_PAIR}, {"size", NORMALIZED_PAIR}, @@ -282,12 +295,12 @@ std::map> {"secondaryColor", COLOR}, {"fontPath", PATH}, {"fontSize", FLOAT}, - {"scrollSound", PATH}, // For backward compatibility with legacy themes. + {"scrollSound", PATH}, // For backward compatibility with legacy themes. {"horizontalAlignment", STRING}, - {"alignment", STRING}, // For backward compatibility with legacy themes. + {"alignment", STRING}, // For backward compatibility with legacy themes. {"horizontalMargin", FLOAT}, {"letterCase", STRING}, - {"forceUppercase", BOOLEAN}, // For backward compatibility with legacy themes. + {"forceUppercase", BOOLEAN}, // For backward compatibility with legacy themes. {"lineSpacing", FLOAT}, {"indicators", STRING}, {"collectionIndicators", STRING}, @@ -307,7 +320,7 @@ std::map> {"entrySpacing", FLOAT}, {"iconTextSpacing", FLOAT}, {"letterCase", STRING}, - {"textStyle", STRING}, // For backward compatibility with legacy themes. + {"textStyle", STRING}, // For backward compatibility with legacy themes. {"opacity", FLOAT}, {"customButtonIcon", PATH}}}, {"sound", diff --git a/es-core/src/components/primary/CarouselComponent.h b/es-core/src/components/primary/CarouselComponent.h index 55dee1e04..af965b665 100644 --- a/es-core/src/components/primary/CarouselComponent.h +++ b/es-core/src/components/primary/CarouselComponent.h @@ -55,6 +55,10 @@ public: void addEntry(Entry& entry, const std::shared_ptr& theme = nullptr); Entry& getEntry(int index) { return mEntries.at(index); } const CarouselType getType() { return mType; } + const std::string& getItemType() { return mItemType; } + void setItemType(std::string itemType) { mItemType = itemType; } + const std::string& getDefaultItem() { return mDefaultItem; } + void setDefaultItem(std::string defaultItem) { mDefaultItem = defaultItem; } void setCursorChangedCallback(const std::function& func) override { @@ -111,6 +115,8 @@ private: bool mTriggerJump; CarouselType mType; + std::string mItemType; + std::string mDefaultItem; std::shared_ptr mFont; unsigned int mTextColor; unsigned int mTextBackgroundColor; @@ -547,6 +553,75 @@ void CarouselComponent::applyTheme(const std::shared_ptr& theme, } } + if (!theme->isLegacyTheme()) { + if (elem->has("itemScale")) + mLogoScale = glm::clamp(elem->get("itemScale"), 0.5f, 3.0f); + if (elem->has("itemSize")) { + // Keep size within a 0.05 and 1.0 multiple of the screen size. + glm::vec2 logoSize {elem->get("itemSize")}; + if (std::max(logoSize.x, logoSize.y) > 1.0f) { + logoSize /= std::max(logoSize.x, logoSize.y); + } + else if (std::min(logoSize.x, logoSize.y) < 0.005f) { + float ratio {std::min(logoSize.x, logoSize.y) / 0.005f}; + logoSize /= ratio; + // Just an extra precaution if a crazy ratio was used. + logoSize.x = glm::clamp(logoSize.x, 0.005f, 1.0f); + logoSize.y = glm::clamp(logoSize.y, 0.005f, 1.0f); + } + mLogoSize = + logoSize * glm::vec2(Renderer::getScreenWidth(), Renderer::getScreenHeight()); + } + + if (elem->has("maxItemCount")) + mMaxLogoCount = glm::clamp(elem->get("maxItemCount"), 0.5f, 30.0f); + + if (elem->has("itemRotation")) + mLogoRotation = elem->get("itemRotation"); + if (elem->has("itemRotationOrigin")) + mLogoRotationOrigin = elem->get("itemRotationOrigin"); + + if (elem->has("itemHorizontalAlignment")) { + const std::string alignment {elem->get("itemHorizontalAlignment")}; + if (alignment == "left" && mType != CarouselType::HORIZONTAL) { + mLogoHorizontalAlignment = ALIGN_LEFT; + } + else if (alignment == "right" && mType != CarouselType::HORIZONTAL) { + mLogoHorizontalAlignment = ALIGN_RIGHT; + } + else if (alignment == "center") { + mLogoHorizontalAlignment = ALIGN_CENTER; + } + else { + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + " defined as \"" + << alignment << "\""; + mLogoHorizontalAlignment = ALIGN_CENTER; + } + } + + if (elem->has("itemVerticalAlignment")) { + const std::string alignment {elem->get("itemVerticalAlignment")}; + if (alignment == "top" && mType != CarouselType::VERTICAL) { + mLogoVerticalAlignment = ALIGN_TOP; + } + else if (alignment == "bottom" && mType != CarouselType::VERTICAL) { + mLogoVerticalAlignment = ALIGN_BOTTOM; + } + else if (alignment == "center") { + mLogoVerticalAlignment = ALIGN_CENTER; + } + else { + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + " defined as \"" + << alignment << "\""; + mLogoVerticalAlignment = ALIGN_CENTER; + } + } + } + + // Start of legacy themes only section. + if (elem->has("logoScale")) mLogoScale = glm::clamp(elem->get("logoScale"), 0.5f, 3.0f); if (elem->has("logoSize")) { @@ -577,45 +652,6 @@ void CarouselComponent::applyTheme(const std::shared_ptr& theme, if (elem->has("logoRotationOrigin")) mLogoRotationOrigin = elem->get("logoRotationOrigin"); - if (elem->has("logoHorizontalAlignment")) { - const std::string alignment {elem->get("logoHorizontalAlignment")}; - if (alignment == "left" && mType != CarouselType::HORIZONTAL) { - mLogoHorizontalAlignment = ALIGN_LEFT; - } - else if (alignment == "right" && mType != CarouselType::HORIZONTAL) { - mLogoHorizontalAlignment = ALIGN_RIGHT; - } - else if (alignment == "center") { - mLogoHorizontalAlignment = ALIGN_CENTER; - } - else { - LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " - " defined as \"" - << alignment << "\""; - mLogoHorizontalAlignment = ALIGN_CENTER; - } - } - - if (elem->has("logoVerticalAlignment")) { - const std::string alignment {elem->get("logoVerticalAlignment")}; - if (alignment == "top" && mType != CarouselType::VERTICAL) { - mLogoVerticalAlignment = ALIGN_TOP; - } - else if (alignment == "bottom" && mType != CarouselType::VERTICAL) { - mLogoVerticalAlignment = ALIGN_BOTTOM; - } - else if (alignment == "center") { - mLogoVerticalAlignment = ALIGN_CENTER; - } - else { - LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " - " defined as \"" - << alignment << "\""; - mLogoVerticalAlignment = ALIGN_CENTER; - } - } - - // Legacy themes only. if (elem->has("logoAlignment")) { const std::string alignment {elem->get("logoAlignment")}; if (alignment == "left" && mType != CarouselType::HORIZONTAL) { @@ -647,6 +683,8 @@ void CarouselComponent::applyTheme(const std::shared_ptr& theme, } } + // End of legacy theme section. + mFont = Font::getFromTheme(elem, properties, mFont); if (elem->has("textColor"))