diff --git a/es-app/src/views/GamelistView.cpp b/es-app/src/views/GamelistView.cpp index 93998d1c2..675a2b0c7 100644 --- a/es-app/src/views/GamelistView.cpp +++ b/es-app/src/views/GamelistView.cpp @@ -61,13 +61,15 @@ void GamelistView::onFileChanged(FileData* file, bool reloadGamelist) void GamelistView::onShow() { - // Reset any GIF and Lottie animations. for (auto& animation : mLottieAnimComponents) animation->resetFileAnimation(); for (auto& animation : mGIFAnimComponents) animation->resetFileAnimation(); + for (auto& video : mStaticVideoComponents) + video->stopVideoPlayer(); + mLastUpdated = nullptr; GuiComponent::onShow(); @@ -172,15 +174,28 @@ void GamelistView::onThemeChanged(const std::shared_ptr& theme) mImageComponents.back()->applyTheme(theme, "gamelist", element.first, ALL); if (mImageComponents.back()->getThemeImageTypes().size() != 0) mImageComponents.back()->setScrollHide(true); + else if (mImageComponents.back()->getMetadataElement()) + mImageComponents.back()->setScrollHide(true); addChild(mImageComponents.back().get()); } else if (element.second.type == "video") { - mVideoComponents.push_back(std::make_unique()); - mVideoComponents.back()->setDefaultZIndex(30.0f); - addChild(mVideoComponents.back().get()); - mVideoComponents.back()->applyTheme(theme, "gamelist", element.first, ALL); - if (mVideoComponents.back()->getThemeImageTypes().size() != 0) - mVideoComponents.back()->setScrollHide(true); + if (element.second.has("path")) { + mStaticVideoComponents.push_back(std::make_unique()); + mStaticVideoComponents.back()->setDefaultZIndex(30.0f); + addChild(mStaticVideoComponents.back().get()); + mStaticVideoComponents.back()->applyTheme(theme, "gamelist", element.first, + ALL); + if (mStaticVideoComponents.back()->getMetadataElement()) + mStaticVideoComponents.back()->setScrollHide(true); + } + else { + mVideoComponents.push_back(std::make_unique()); + mVideoComponents.back()->setDefaultZIndex(30.0f); + addChild(mVideoComponents.back().get()); + mVideoComponents.back()->applyTheme(theme, "gamelist", element.first, ALL); + if (mVideoComponents.back()->getThemeImageTypes().size() != 0) + mVideoComponents.back()->setScrollHide(true); + } } else if (element.second.type == "animation" && element.second.has("path")) { const std::string extension { @@ -189,12 +204,16 @@ void GamelistView::onThemeChanged(const std::shared_ptr& theme) mLottieAnimComponents.push_back(std::make_unique()); mLottieAnimComponents.back()->setDefaultZIndex(35.0f); mLottieAnimComponents.back()->applyTheme(theme, "gamelist", element.first, ALL); + if (mLottieAnimComponents.back()->getMetadataElement()) + mLottieAnimComponents.back()->setScrollHide(true); addChild(mLottieAnimComponents.back().get()); } else if (extension == ".gif") { mGIFAnimComponents.push_back(std::make_unique()); mGIFAnimComponents.back()->setDefaultZIndex(35.0f); mGIFAnimComponents.back()->applyTheme(theme, "gamelist", element.first, ALL); + if (mGIFAnimComponents.back()->getMetadataElement()) + mGIFAnimComponents.back()->setScrollHide(true); addChild(mGIFAnimComponents.back().get()); } else if (extension == ".") { @@ -233,14 +252,21 @@ void GamelistView::onThemeChanged(const std::shared_ptr& theme) mContainerTextComponents.back()->applyTheme( theme, "gamelist", element.first, ALL ^ POSITION ^ Z_INDEX ^ ThemeFlags::SIZE ^ VISIBLE ^ ROTATION); - mContainerComponents.back()->setScrollHide(true); + if (mContainerTextComponents.back()->getThemeMetadata() != "") + mContainerComponents.back()->setScrollHide(true); + else if (mContainerTextComponents.back()->getMetadataElement()) + mContainerComponents.back()->setScrollHide(true); } else { mTextComponents.push_back(std::make_unique()); mTextComponents.back()->setDefaultZIndex(40.0f); mTextComponents.back()->applyTheme(theme, "gamelist", element.first, ALL); - if (mTextComponents.back()->getThemeMetadata() != "") + if (mTextComponents.back()->getThemeMetadata() != "") { mTextComponents.back()->setScrollHide(true); + } + else if (mTextComponents.back()->getMetadataElement()) { + mTextComponents.back()->setScrollHide(true); + } addChild(mTextComponents.back().get()); } } @@ -294,6 +320,11 @@ void GamelistView::onThemeChanged(const std::shared_ptr& theme) mLeftRightAvailable = false; } + for (auto& video : mStaticVideoComponents) { + if (video->hasStaticVideo()) + video->setStaticVideo(); + } + sortChildren(); } @@ -311,6 +342,17 @@ void GamelistView::update(int deltaTime) } } + // We need to manually advance fade-in and fade-out animations since they will not get updated + // via GuiComponent as these components override the update() function. + for (auto& anim : mLottieAnimComponents) { + if (anim->isAnimationPlaying(0)) + anim->advanceAnimation(0, deltaTime); + } + for (auto& anim : mGIFAnimComponents) { + if (anim->isAnimationPlaying(0)) + anim->advanceAnimation(0, deltaTime); + } + updateChildren(deltaTime); } @@ -392,7 +434,8 @@ void GamelistView::updateInfoPanel(const CursorState& state) if (mCarousel != nullptr) mCarousel->onDemandTextureLoad(); - // 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 view, then skip it this time. + // This also happens when fast-scrolling. if (file == mLastUpdated) return; @@ -427,25 +470,57 @@ void GamelistView::updateInfoPanel(const CursorState& state) if (hideMetaDataFields) { for (auto& text : mTextComponents) { - if (text->getThemeMetadata() != "") + if (text->getMetadataElement() || text->getThemeMetadata() != "") text->setVisible(false); } for (auto& date : mDateTimeComponents) date->setVisible(false); + for (auto& image : mImageComponents) { + if (image->getMetadataElement()) + image->setVisible(false); + } + for (auto& video : mStaticVideoComponents) { + if (video->getMetadataElement()) + video->setVisible(false); + } + for (auto& anim : mLottieAnimComponents) { + if (anim->getMetadataElement()) + anim->setVisible(false); + } + for (auto& anim : mGIFAnimComponents) { + if (anim->getMetadataElement()) + anim->setVisible(false); + } for (auto& badge : mBadgeComponents) badge->setVisible(false); for (auto& rating : mRatingComponents) rating->setVisible(false); for (auto& cText : mContainerTextComponents) { - if (cText->getThemeMetadata() != "description") + if (cText->getThemeMetadata() != "description" || cText->getMetadataElement()) cText->setVisible(false); } } else { for (auto& text : mTextComponents) { - if (text->getThemeMetadata() != "") + if (text->getMetadataElement() || text->getThemeMetadata() != "") text->setVisible(true); } + for (auto& image : mImageComponents) { + if (image->getMetadataElement()) + image->setVisible(true); + } + for (auto& video : mStaticVideoComponents) { + if (video->getMetadataElement()) + video->setVisible(true); + } + for (auto& anim : mLottieAnimComponents) { + if (anim->getMetadataElement()) + anim->setVisible(true); + } + for (auto& anim : mGIFAnimComponents) { + if (anim->getMetadataElement()) + anim->setVisible(true); + } for (auto& date : mDateTimeComponents) date->setVisible(true); for (auto& badge : mBadgeComponents) @@ -453,7 +528,7 @@ void GamelistView::updateInfoPanel(const CursorState& state) for (auto& rating : mRatingComponents) rating->setVisible(true); for (auto& cText : mContainerTextComponents) { - if (cText->getThemeMetadata() != "description") + if (cText->getThemeMetadata() != "description" || cText->getMetadataElement()) cText->setVisible(true); } } @@ -763,10 +838,22 @@ void GamelistView::updateInfoPanel(const CursorState& state) if (image->getScrollHide()) comps.emplace_back(image.get()); } + for (auto& video : mStaticVideoComponents) { + if (video->getScrollHide()) + comps.emplace_back(video.get()); + } for (auto& video : mVideoComponents) { if (video->getScrollHide()) comps.emplace_back(video.get()); } + for (auto& anim : mLottieAnimComponents) { + if (anim->getScrollHide()) + comps.emplace_back(anim.get()); + } + for (auto& anim : mGIFAnimComponents) { + if (anim->getScrollHide()) + comps.emplace_back(anim.get()); + } for (auto& badge : mBadgeComponents) { if (badge->getScrollHide()) comps.emplace_back(badge.get()); diff --git a/es-app/src/views/GamelistView.h b/es-app/src/views/GamelistView.h index 99248f730..7288b25b1 100644 --- a/es-app/src/views/GamelistView.h +++ b/es-app/src/views/GamelistView.h @@ -44,22 +44,29 @@ public: { for (auto& video : mVideoComponents) video->startVideoPlayer(); + for (auto& video : mStaticVideoComponents) + video->startVideoPlayer(); } void stopViewVideos() override { for (auto& video : mVideoComponents) video->stopVideoPlayer(); + for (auto& video : mStaticVideoComponents) + video->stopVideoPlayer(); } void pauseViewVideos() override { - for (auto& video : mVideoComponents) { + for (auto& video : mVideoComponents) + video->pauseVideoPlayer(); + for (auto& video : mStaticVideoComponents) video->pauseVideoPlayer(); - } } void muteViewVideos() override { for (auto& video : mVideoComponents) video->muteVideoPlayer(); + for (auto& video : mStaticVideoComponents) + video->muteVideoPlayer(); } void stopScrollFadeIn() override @@ -111,6 +118,7 @@ private: std::vector> mTextComponents; std::vector> mDateTimeComponents; std::vector> mImageComponents; + std::vector> mStaticVideoComponents; std::vector> mVideoComponents; std::vector> mLottieAnimComponents; std::vector> mGIFAnimComponents; diff --git a/es-core/src/GuiComponent.h b/es-core/src/GuiComponent.h index 14cb8a4c1..a6d141f65 100644 --- a/es-core/src/GuiComponent.h +++ b/es-core/src/GuiComponent.h @@ -114,8 +114,9 @@ public: // clang-format off enum ComponentThemeFlags : unsigned int { - SCROLL_HIDE = 0x00000001, - SCROLL_FADE_IN = 0x00000002 + SCROLL_HIDE = 0x00000001, + SCROLL_FADE_IN = 0x00000002, + METADATA_ELEMENT = 0x00000004 }; // clang-format on @@ -138,6 +139,17 @@ public: else mComponentThemeFlags ^= ComponentThemeFlags::SCROLL_FADE_IN; } + const bool getMetadataElement() + { + return mComponentThemeFlags & ComponentThemeFlags::METADATA_ELEMENT; + } + void setMetadataElement(bool state) + { + if (state) + mComponentThemeFlags |= ComponentThemeFlags::METADATA_ELEMENT; + else + mComponentThemeFlags ^= ComponentThemeFlags::METADATA_ELEMENT; + } // Returns the center point of the image (takes origin into account). const glm::vec2 getCenter() const; diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index dabc606fe..c753ac970 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -94,6 +94,7 @@ std::map> {"path", PATH}, {"default", PATH}, {"imageType", STRING}, + {"metadataElement", BOOLEAN}, {"gameselector", STRING}, {"tile", BOOLEAN}, {"interpolation", STRING}, @@ -110,6 +111,7 @@ std::map> {"size", NORMALIZED_PAIR}, {"maxSize", NORMALIZED_PAIR}, {"origin", NORMALIZED_PAIR}, + {"metadataElement", BOOLEAN}, {"path", PATH}, {"default", PATH}, {"defaultImage", PATH}, @@ -134,6 +136,7 @@ std::map> {"origin", NORMALIZED_PAIR}, {"rotation", FLOAT}, {"rotationOrigin", NORMALIZED_PAIR}, + {"metadataElement", BOOLEAN}, {"path", PATH}, {"speed", FLOAT}, {"direction", STRING}, @@ -175,6 +178,7 @@ std::map> {"text", STRING}, {"systemdata", STRING}, {"metadata", STRING}, + {"metadataElement", BOOLEAN}, {"gameselector", STRING}, {"container", BOOLEAN}, {"containerScrollSpeed", FLOAT}, diff --git a/es-core/src/components/GIFAnimComponent.cpp b/es-core/src/components/GIFAnimComponent.cpp index 1f6a882dc..131b75dbc 100644 --- a/es-core/src/components/GIFAnimComponent.cpp +++ b/es-core/src/components/GIFAnimComponent.cpp @@ -267,6 +267,9 @@ void GIFAnimComponent::applyTheme(const std::shared_ptr& theme, } } + if (elem->has("metadataElement") && elem->get("metadataElement")) + mComponentThemeFlags |= ComponentThemeFlags::METADATA_ELEMENT; + if (elem->has("speed")) { const float speed {elem->get("speed")}; if (speed < 0.2f || speed > 3.0f) { diff --git a/es-core/src/components/ImageComponent.cpp b/es-core/src/components/ImageComponent.cpp index df6f7e912..cc069634d 100644 --- a/es-core/src/components/ImageComponent.cpp +++ b/es-core/src/components/ImageComponent.cpp @@ -557,6 +557,9 @@ void ImageComponent::applyTheme(const std::shared_ptr& theme, mThemeImageTypes = Utils::String::delimitedStringToVector(imageTypes, ","); } + if (elem->has("metadataElement") && elem->get("metadataElement")) + mComponentThemeFlags |= ComponentThemeFlags::METADATA_ELEMENT; + if (properties & COLOR) { if (elem->has("color")) setColorShift(elem->get("color")); diff --git a/es-core/src/components/LottieAnimComponent.cpp b/es-core/src/components/LottieAnimComponent.cpp index 1d4533f67..6ab191c71 100644 --- a/es-core/src/components/LottieAnimComponent.cpp +++ b/es-core/src/components/LottieAnimComponent.cpp @@ -238,6 +238,9 @@ void LottieAnimComponent::applyTheme(const std::shared_ptr& theme, } } + if (elem->has("metadataElement") && elem->get("metadataElement")) + mComponentThemeFlags |= ComponentThemeFlags::METADATA_ELEMENT; + if (elem->has("speed")) { const float speed {elem->get("speed")}; if (speed < 0.2f || speed > 3.0f) { diff --git a/es-core/src/components/TextComponent.cpp b/es-core/src/components/TextComponent.cpp index 708aab85d..7b0c1cee9 100644 --- a/es-core/src/components/TextComponent.cpp +++ b/es-core/src/components/TextComponent.cpp @@ -389,6 +389,9 @@ void TextComponent::applyTheme(const std::shared_ptr& theme, if (!elem) return; + if (elem->has("metadataElement") && elem->get("metadataElement")) + mComponentThemeFlags |= ComponentThemeFlags::METADATA_ELEMENT; + if (properties & COLOR && elem->has("color")) setColor(elem->get("color")); diff --git a/es-core/src/components/VideoComponent.cpp b/es-core/src/components/VideoComponent.cpp index ad1a4c00d..bb64930b9 100644 --- a/es-core/src/components/VideoComponent.cpp +++ b/es-core/src/components/VideoComponent.cpp @@ -147,6 +147,9 @@ void VideoComponent::applyTheme(const std::shared_ptr& theme, mVideoAreaPos = elem->get("pos") * scale; } + if (elem->has("metadataElement") && elem->get("metadataElement")) + mComponentThemeFlags |= ComponentThemeFlags::METADATA_ELEMENT; + if (elem->has("audio")) mPlayAudio = elem->get("audio");