From 9bea6bb17e91987976ccc02f260fecbacff7fa47 Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Thu, 12 Nov 2020 00:46:59 +0100 Subject: [PATCH] Added a game info overlay to the screensaver. Also refactored Window and SystemScreensaver and added a fade-in effect for the shaded background when opening menus. --- INSTALL.md | 7 + NEWS.md | 1 + USERGUIDE.md | 12 +- es-app/src/SystemScreensaver.cpp | 215 +++++++++++++++++++--- es-app/src/SystemScreensaver.h | 26 ++- es-app/src/guis/GuiScreensaverOptions.cpp | 108 +++++------ es-core/src/Settings.cpp | 7 +- es-core/src/Window.cpp | 99 ++++------ es-core/src/Window.h | 10 +- es-core/src/renderers/Renderer.cpp | 3 +- es-core/src/renderers/Renderer_GL21.cpp | 2 + 11 files changed, 317 insertions(+), 173 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index d6526dc83..dde735b6c 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -92,6 +92,13 @@ make ``` I have however not been able to test the CEC support and I'm not entirely sure how it's supposed to work. +To build ES with the GLES renderer, run the following: +``` +cmake -DCMAKE_BUILD_TYPE=Debug -DGLES=on . +make +``` +Note that the GLES renderer is quite limited as there is no shader support for it, so ES will definitely not look as pretty as when using the default OpenGL renderer. + Running multiple compile jobs in parallel is a good thing as it speeds up the build time a lot (scaling almost linearly). Here's an example telling make to run 6 parallel jobs: ``` diff --git a/NEWS.md b/NEWS.md index 9a370a4d5..5ea50bc48 100644 --- a/NEWS.md +++ b/NEWS.md @@ -27,6 +27,7 @@ Many bugs have been fixed, and numerous features that were only partially implem * Files or folders can now be flagged for exclusion when scraping with the multi-scraper, and for folders it can be set to apply recursively * Gamelist sorting is now working as expected and is persistent throughout the application session * Overhaul of the game collection functionality including many bug fixes and optimizations +* Overhaul of the screensaver (the game info overlay now works correctly for instance) * Added ability to delete custom collections from the GUI menu * Game counting is now done during sorting instead of every time a system is selected. This should make the UI more responsive in case of large game libraries * Added a system view counter for favorite games in addition to the total number of games diff --git a/USERGUIDE.md b/USERGUIDE.md index 3761a1c7d..89c021418 100644 --- a/USERGUIDE.md +++ b/USERGUIDE.md @@ -693,6 +693,10 @@ For how long to display images before changing to the next game. Allowed range i This will fill the entire screen surface but will possibly break the aspect ratio of the image. +**Display game info overlay** + +This will display an overlay in the bottom left corner, showing the game name and the game system name. + **Render scanlines** _(OpenGL renderer only)_ Whether to use a shader to render scanlines on top of the images. @@ -717,17 +721,17 @@ Options specific to the video screensaver. For how long to play videos before changing to the next game. Allowed range is between 5 and 120 seconds. -**Show game info overlay** +**Play audio for screensaver videos** -This will display an overlay on top of the videos, showing the game name and game system name. +Muting or playing the audio. **Stretch videos to screen resolution** This will fill the entire screen surface but will possibly break the aspect ratio of the video. -**Play audio for screensaver video files** +**Display game info overlay** -Muting or playing the audio. +This will display an overlay in the bottom left corner, showing the game name and the game system name. **Render scanlines** _(OpenGL renderer only)_ diff --git a/es-app/src/SystemScreensaver.cpp b/es-app/src/SystemScreensaver.cpp index bdb43404d..b66df4ae5 100644 --- a/es-app/src/SystemScreensaver.cpp +++ b/es-app/src/SystemScreensaver.cpp @@ -13,7 +13,9 @@ #include "components/VideoPlayerComponent.h" #endif #include "components/VideoVlcComponent.h" +#include "resources/Font.h" #include "utils/FileSystemUtil.h" +#include "utils/StringUtil.h" #include "views/gamelist/IGameListView.h" #include "views/ViewController.h" #include "FileData.h" @@ -33,19 +35,22 @@ SystemScreensaver::SystemScreensaver( Window* window) - : mImageScreensaver(nullptr), - mVideoScreensaver(nullptr), - mWindow(window), + : mWindow(window), mState(STATE_INACTIVE), - mOpacity(0.0f), - mTimer(0), - mSystemName(""), - mGameName(""), + mImageScreensaver(nullptr), + mVideoScreensaver(nullptr), mCurrentGame(nullptr), - mHasMediaFiles(false) + mPreviousGame(nullptr), + mTimer(0), + mVideoChangeTime(30000), + mHasMediaFiles(false), + mOpacity(0.0f), + mDimValue(1.0), + mRectangleFadeIn(50), + mTextFadeIn(0), + mSaturationAmount(1.0) { mWindow->setScreensaver(this); - mVideoChangeTime = 30000; } SystemScreensaver::~SystemScreensaver() @@ -70,11 +75,18 @@ void SystemScreensaver::startScreensaver(bool generateMediaList) std::string path = ""; std::string screensaverType = Settings::getInstance()->getString("ScreensaverType"); mHasMediaFiles = false; + mOpacity = 0.0f; + + // Keep a reference to the default fonts, so they don't keep getting destroyed/recreated. + if (mGameOverlayFont.empty()) { + mGameOverlayFont.push_back(Font::get(FONT_SIZE_SMALL)); + mGameOverlayFont.push_back(Font::get(FONT_SIZE_MEDIUM)); + mGameOverlayFont.push_back(Font::get(FONT_SIZE_LARGE)); + } // Set mPreviousGame which will be used to avoid showing the same game again during // the random selection. - if ((screensaverType == "video" || screensaverType == "slideshow") && - mCurrentGame != nullptr) + if ((screensaverType == "slideshow" || screensaverType == "video") && mCurrentGame != nullptr) mPreviousGame = mCurrentGame; if (screensaverType == "slideshow") { @@ -87,7 +99,6 @@ void SystemScreensaver::startScreensaver(bool generateMediaList) mState = STATE_FADE_OUT_WINDOW; mVideoChangeTime = Settings::getInstance()->getInt("ScreensaverSwapImageTimeout"); - mOpacity = 0.0f; // Load a random image. if (Settings::getInstance()->getBool("ScreensaverSlideshowCustomImages")) { @@ -110,9 +121,12 @@ void SystemScreensaver::startScreensaver(bool generateMediaList) mHasMediaFiles = true; // Don't attempt to render the screensaver if there are no images available, but - // do flag it as running. This way Window::render() will fade to a black screen, i.e. - // it will activate the 'Black' screensaver type. + // do flag it as running. This way render() will fade to a black screen, i.e. it + // will activate the 'Black' screensaver type. if (mImageFiles.size() > 0 || mImageCustomFiles.size() > 0) { + if (Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo")) + generateOverlayInfo(); + if (!mImageScreensaver) mImageScreensaver = new ImageComponent(mWindow, false, false); @@ -142,7 +156,6 @@ void SystemScreensaver::startScreensaver(bool generateMediaList) mState = STATE_FADE_OUT_WINDOW; mVideoChangeTime = Settings::getInstance()->getInt("ScreensaverSwapVideoTimeout"); - mOpacity = 0.0f; // Load a random video. if (generateMediaList) @@ -153,8 +166,11 @@ void SystemScreensaver::startScreensaver(bool generateMediaList) mHasMediaFiles = true; if (!path.empty() && Utils::FileSystem::exists(path)) { + if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo")) + generateOverlayInfo(); + #if defined(_RPI_) - // Create the correct type of video component + // Create the correct type of video component. if (Settings::getInstance()->getBool("ScreensaverOmxPlayer")) mVideoScreensaver = new VideoPlayerComponent(mWindow); else @@ -197,6 +213,14 @@ void SystemScreensaver::stopScreensaver() mState = STATE_INACTIVE; PowerSaver::runningScreensaver(false); + + mDimValue = 1.0; + mRectangleFadeIn = 50; + mTextFadeIn = 0; + mSaturationAmount = 1.0; + + if (mGameOverlay) + mGameOverlay.release(); } void SystemScreensaver::nextGame() { @@ -221,7 +245,7 @@ void SystemScreensaver::renderScreensaver() { std::string screensaverType = Settings::getInstance()->getString("ScreensaverType"); if (mVideoScreensaver && screensaverType == "video") { - // Render black background. + // Render a black background below the video. Renderer::setMatrix(Transform4x4f::Identity()); Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x000000FF, 0x000000FF); @@ -233,12 +257,12 @@ void SystemScreensaver::renderScreensaver() } } else if (mImageScreensaver && screensaverType == "slideshow") { - // Render a black background. + // Render a black background below the image. Renderer::setMatrix(Transform4x4f::Identity()); Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x000000FF, 0x000000FF); - // Only render the video if the state requires it. + // Only render the image if the state requires it. if (static_cast(mState) >= STATE_FADE_IN_VIDEO) { if (mImageScreensaver->hasImage()) { mImageScreensaver->setOpacity(255 - static_cast(mOpacity * 255)); @@ -248,14 +272,117 @@ void SystemScreensaver::renderScreensaver() } } } - #if !defined(USE_OPENGL_21) - else if (mState != STATE_INACTIVE) { + + if (isScreensaverActive()) { Renderer::setMatrix(Transform4x4f::Identity()); - unsigned char color = screensaverType == "dim" ? 0x000000A0 : 0x000000FF; - Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), - Renderer::getScreenHeight(), color, color); + if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") { + if (mHasMediaFiles) { + #if defined(USE_OPENGL_21) + if (Settings::getInstance()->getBool("ScreensaverSlideshowScanlines")) + Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); + #endif + if (Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo") && + mGameOverlay) { + if (mGameOverlayRectangleCoords.size() == 4) { + Renderer::drawRect(mGameOverlayRectangleCoords[0], + mGameOverlayRectangleCoords[1], mGameOverlayRectangleCoords[2], + mGameOverlayRectangleCoords[3], 0x00000000 | mRectangleFadeIn, + 0x00000000 | mRectangleFadeIn ); + } + if (mRectangleFadeIn < 180) + mRectangleFadeIn = Math::clamp(mRectangleFadeIn + 4, 0, 255); + + mGameOverlay.get()->setColor(0xFFFFFF00 | mTextFadeIn); + mGameOverlayFont.at(0)->renderTextCache(mGameOverlay.get()); + if (mTextFadeIn < 255) + mTextFadeIn = Math::clamp(mTextFadeIn + 8, 0, 255); + } + } + else { + // If there are no images, fade in a black screen. + #if defined(USE_OPENGL_21) + Renderer::shaderParameters blackParameters; + blackParameters.fragmentDimValue = mDimValue; + Renderer::shaderPostprocessing(Renderer::SHADER_DIM, blackParameters); + #else + Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), + Renderer::getScreenHeight(), 0x000000FF, 0x000000FF, mDimValue); + #endif + if (mDimValue > 0.0) + mDimValue = Math::clamp(mDimValue-0.045, 0.0, 1.0); + } + } + if (Settings::getInstance()->getString("ScreensaverType") == "video") { + if (mHasMediaFiles) { + #if defined(USE_OPENGL_21) + if (Settings::getInstance()->getBool("ScreensaverVideoBlur")) + Renderer::shaderPostprocessing(Renderer::SHADER_BLUR_HORIZONTAL); + if (Settings::getInstance()->getBool("ScreensaverVideoScanlines")) + Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); + #endif + if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo") && mGameOverlay) { + if (mGameOverlayRectangleCoords.size() == 4) { + #if defined(USE_OPENGL_21) + Renderer::shaderPostprocessing(Renderer::SHADER_OPACITY); + #endif + Renderer::drawRect(mGameOverlayRectangleCoords[0], + mGameOverlayRectangleCoords[1], mGameOverlayRectangleCoords[2], + mGameOverlayRectangleCoords[3], 0x00000000 | mRectangleFadeIn, + 0x00000000 | mRectangleFadeIn ); + } + if (mRectangleFadeIn < 180) + mRectangleFadeIn = Math::clamp(mRectangleFadeIn + 4, 0, 255); + + mGameOverlay.get()->setColor(0xFFFFFF00 | mTextFadeIn); + mGameOverlayFont.at(0)->renderTextCache(mGameOverlay.get()); + if (mTextFadeIn < 255) + mTextFadeIn = Math::clamp(mTextFadeIn + 8, 0, 255); + } + } + else { + // If there are no videos, fade in a black screen. + #if defined(USE_OPENGL_21) + Renderer::shaderParameters blackParameters; + blackParameters.fragmentDimValue = mDimValue; + Renderer::shaderPostprocessing(Renderer::SHADER_DIM, blackParameters); + #else + Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), + Renderer::getScreenHeight(), 0x000000FF, 0x000000FF, mDimValue); + #endif + if (mDimValue > 0.0) + mDimValue = Math::clamp(mDimValue-0.045, 0.0, 1.0); + } + } + + else if (Settings::getInstance()->getString("ScreensaverType") == "dim") { + #if defined(USE_OPENGL_21) + Renderer::shaderParameters dimParameters; + dimParameters.fragmentDimValue = mDimValue; + Renderer::shaderPostprocessing(Renderer::SHADER_DIM, dimParameters); + if (mDimValue > 0.4) + mDimValue = Math::clamp(mDimValue-0.021, 0.4, 1.0); + dimParameters.fragmentSaturation = mSaturationAmount; + Renderer::shaderPostprocessing(Renderer::SHADER_DESATURATE, dimParameters); + if (mSaturationAmount > 0.0) + mSaturationAmount = Math::clamp(mSaturationAmount-0.035, 0.0, 1.0); + #else + Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), + Renderer::getScreenHeight(), 0x000000A0, 0x000000A0); + #endif + } + else if (Settings::getInstance()->getString("ScreensaverType") == "black") { + #if defined(USE_OPENGL_21) + Renderer::shaderParameters blackParameters; + blackParameters.fragmentDimValue = mDimValue; + Renderer::shaderPostprocessing(Renderer::SHADER_DIM, blackParameters); + if (mDimValue > 0.0) + mDimValue = Math::clamp(mDimValue-0.045, 0.0, 1.0); + #else + Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), + Renderer::getScreenHeight(), 0x000000FF, 0x000000FF); + #endif + } } - #endif } void SystemScreensaver::update(int deltaTime) @@ -438,3 +565,41 @@ void SystemScreensaver::pickRandomCustomImage(std::string& path) mGameName = ""; mSystemName = ""; } + +void SystemScreensaver::generateOverlayInfo() +{ + if (mGameName == "" || mSystemName == "") + return; + + float posX = static_cast(Renderer::getWindowWidth()) * 0.03; + float posY = static_cast(Renderer::getWindowHeight()) * 0.87; + + const std::string gameName = Utils::String::toUpper(mGameName); + const std::string systemName = Utils::String::toUpper(mSystemName); + const std::string overlayText = gameName + "\n" + systemName; + + mGameOverlay = std::unique_ptr(mGameOverlayFont.at(0)-> + buildTextCache(overlayText, posX, posY, 0xFFFFFFFF)); + + float textSizeX; + float textSizeY = mGameOverlayFont[0].get()->sizeText(overlayText).y(); + + // There is a weird issue with sizeText() where the X size value is returned + // as too large if there are two rows in a string and the second row is longer + // than the first row. Possibly it's the newline character that is somehow + // injected in the size calculation. Regardless, this workaround is working + // fine for the time being. + if (mGameOverlayFont[0].get()->sizeText(gameName).x() > + mGameOverlayFont[0].get()->sizeText(systemName).x()) + textSizeX = mGameOverlayFont[0].get()->sizeText(gameName).x(); + else + textSizeX = mGameOverlayFont[0].get()->sizeText(systemName).x(); + + float marginX = Renderer::getWindowWidth() * 0.01; + + mGameOverlayRectangleCoords.clear(); + mGameOverlayRectangleCoords.push_back(posX - marginX); + mGameOverlayRectangleCoords.push_back(posY); + mGameOverlayRectangleCoords.push_back(textSizeX + marginX * 2); + mGameOverlayRectangleCoords.push_back(textSizeY); +} diff --git a/es-app/src/SystemScreensaver.h b/es-app/src/SystemScreensaver.h index fed6d5127..260ab0196 100644 --- a/es-app/src/SystemScreensaver.h +++ b/es-app/src/SystemScreensaver.h @@ -13,7 +13,6 @@ #include "Window.h" class ImageComponent; -class Sound; class VideoComponent; // Screensaver implementation. @@ -34,7 +33,6 @@ public: virtual void renderScreensaver(); virtual void update(int deltaTime); - virtual bool getHasMediaFiles() { return mHasMediaFiles; }; virtual FileData* getCurrentGame() { return mCurrentGame; }; private: @@ -44,6 +42,7 @@ private: void pickRandomImage(std::string& path); void pickRandomVideo(std::string& path); void pickRandomCustomImage(std::string& path); + void generateOverlayInfo(); enum STATE { STATE_INACTIVE, @@ -52,22 +51,33 @@ private: STATE_SCREENSAVER_ACTIVE }; + Window* mWindow; + STATE mState; + std::vector mImageFiles; std::vector mVideoFiles; std::vector mImageCustomFiles; - bool mHasMediaFiles; - VideoComponent* mVideoScreensaver; ImageComponent* mImageScreensaver; - Window* mWindow; - STATE mState; - float mOpacity; - int mTimer; + VideoComponent* mVideoScreensaver; + FileData* mCurrentGame; FileData* mPreviousGame; std::string mPreviousCustomImage; std::string mGameName; std::string mSystemName; + + int mTimer; int mVideoChangeTime; + bool mHasMediaFiles; + float mOpacity; + float mDimValue; + unsigned char mRectangleFadeIn; + unsigned char mTextFadeIn; + float mSaturationAmount; + + std::unique_ptr mGameOverlay; + std::vector> mGameOverlayFont; + std::vector mGameOverlayRectangleCoords; }; #endif // ES_APP_SYSTEM_SCREEN_SAVER_H diff --git a/es-app/src/guis/GuiScreensaverOptions.cpp b/es-app/src/guis/GuiScreensaverOptions.cpp index 32edec379..66e8c8b52 100644 --- a/es-app/src/guis/GuiScreensaverOptions.cpp +++ b/es-app/src/guis/GuiScreensaverOptions.cpp @@ -131,17 +131,31 @@ void GuiScreensaverOptions::openSlideshowScreensaverOptions() } }); + // Show game info overlay for slideshow screensaver. + auto screensaver_slideshow_game_info = std::make_shared(mWindow); + screensaver_slideshow_game_info-> + setState(Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo")); + s->addWithLabel("DISPLAY GAME INFO OVERLAY", screensaver_slideshow_game_info); + s->addSaveFunc([screensaver_slideshow_game_info, s] { + if (screensaver_slideshow_game_info->getState() != + Settings::getInstance()->getBool("ScreensaverSlideshowGameInfo")) { + Settings::getInstance()->setBool("ScreensaverSlideshowGameInfo", + screensaver_slideshow_game_info->getState()); + s->setNeedsSaving(); + } + }); + #if defined(USE_OPENGL_21) // Render scanlines using a shader. - auto screensaver_image_scanlines = std::make_shared(mWindow); - screensaver_image_scanlines-> - setState(Settings::getInstance()->getBool("ScreensaverImageScanlines")); - s->addWithLabel("RENDER SCANLINES", screensaver_image_scanlines); - s->addSaveFunc([screensaver_image_scanlines, s] { - if (screensaver_image_scanlines->getState() != - Settings::getInstance()->getBool("ScreensaverImageScanlines")) { - Settings::getInstance()-> - setBool("ScreensaverImageScanlines", screensaver_image_scanlines->getState()); + auto screensaver_slideshow_scanlines = std::make_shared(mWindow); + screensaver_slideshow_scanlines-> + setState(Settings::getInstance()->getBool("ScreensaverSlideshowScanlines")); + s->addWithLabel("RENDER SCANLINES", screensaver_slideshow_scanlines); + s->addSaveFunc([screensaver_slideshow_scanlines, s] { + if (screensaver_slideshow_scanlines->getState() != + Settings::getInstance()->getBool("ScreensaverSlideshowScanlines")) { + Settings::getInstance()->setBool("ScreensaverSlideshowScanlines", + screensaver_slideshow_scanlines->getState()); s->setNeedsSaving(); } }); @@ -215,22 +229,15 @@ void GuiScreensaverOptions::openVideoScreensaverOptions() } }); - // Show game info overlay. - auto screensaver_video_game_info = std::make_shared> - (mWindow,getHelpStyle(), "SHOW GAME INFO OVERLAY", false); - std::vector info_type; - info_type.push_back("always"); - info_type.push_back("start & end"); - info_type.push_back("never"); - for (auto it = info_type.cbegin(); it != info_type.cend(); it++) - screensaver_video_game_info->add(*it, *it, - Settings::getInstance()->getString("ScreensaverVideoGameInfo") == *it); - s->addWithLabel("SHOW GAME INFO OVERLAY", screensaver_video_game_info); - s->addSaveFunc([screensaver_video_game_info, s] { - if (screensaver_video_game_info->getSelected() != - Settings::getInstance()->getString("ScreensaverVideoGameInfo")) { - Settings::getInstance()->setString("ScreensaverVideoGameInfo", - screensaver_video_game_info->getSelected()); + // PLay audio for screensaver videos. + auto screensaver_video_audio = std::make_shared(mWindow); + screensaver_video_audio->setState(Settings::getInstance()->getBool("ScreensaverVideoAudio")); + s->addWithLabel("PLAY AUDIO FOR SCREENSAVER VIDEOS", screensaver_video_audio); + s->addSaveFunc([screensaver_video_audio, s] { + if (screensaver_video_audio->getState() != + Settings::getInstance()->getBool("ScreensaverVideoAudio")) { + Settings::getInstance()->setBool("ScreensaverVideoAudio", + screensaver_video_audio->getState()); s->setNeedsSaving(); } }); @@ -249,7 +256,22 @@ void GuiScreensaverOptions::openVideoScreensaverOptions() } }); + // Show game info overlay for video screensaver. + auto screensaver_video_game_info = std::make_shared(mWindow); + screensaver_video_game_info-> + setState(Settings::getInstance()->getBool("ScreensaverVideoGameInfo")); + s->addWithLabel("DISPLAY GAME INFO OVERLAY", screensaver_video_game_info); + s->addSaveFunc([screensaver_video_game_info, s] { + if (screensaver_video_game_info->getState() != + Settings::getInstance()->getBool("ScreensaverVideoGameInfo")) { + Settings::getInstance()->setBool("ScreensaverVideoGameInfo", + screensaver_video_game_info->getState()); + s->setNeedsSaving(); + } + }); + #if defined(_RPI_) + // Use OMX player for screensaver. auto screensaver_omx_player = std::make_shared(mWindow); screensaver_omx_player->setState(Settings::getInstance()->getBool("ScreensaverOmxPlayer")); s->addWithLabel("USE OMX PLAYER FOR SCREENSAVER", screensaver_omx_player); @@ -263,42 +285,6 @@ void GuiScreensaverOptions::openVideoScreensaverOptions() }); #endif -// ComponentListRow row; - - // Set subtitle position. -// auto ss_omx_subs_align = std::make_shared> -// (mWindow, getHelpStyle(), "GAME INFO ALIGNMENT", false); -// std::vector align_mode; -// align_mode.push_back("left"); -// align_mode.push_back("center"); -// for (auto it = align_mode.cbegin(); it != align_mode.cend(); it++) -// ss_omx_subs_align->add(*it, *it, Settings::getInstance()-> -// getString("SubtitleAlignment") == *it); -// addWithLabel("GAME INFO ALIGNMENT", ss_omx_subs_align); -// addSaveFunc([ss_omx_subs_align, this] { Settings::getInstance()-> -// setString("SubtitleAlignment", ss_omx_subs_align->getSelected()); }); - - // Set font size. -// auto ss_omx_font_size = std::make_shared(mWindow, 1.f, 64.f, 1.f, "h"); -// ss_omx_font_size->setValue((float)(Settings::getInstance()->getInt("SubtitleSize"))); -// addWithLabel("GAME INFO FONT SIZE", ss_omx_font_size); -// addSaveFunc([ss_omx_font_size] { -// int subSize = (int)Math::round(ss_omx_font_size->getValue()); -// Settings::getInstance()->setInt("SubtitleSize", subSize); -// }); - - auto screensaver_video_audio = std::make_shared(mWindow); - screensaver_video_audio->setState(Settings::getInstance()->getBool("ScreensaverVideoAudio")); - s->addWithLabel("PLAY AUDIO FOR SCREENSAVER VIDEOS", screensaver_video_audio); - s->addSaveFunc([screensaver_video_audio, s] { - if (screensaver_video_audio->getState() != - Settings::getInstance()->getBool("ScreensaverVideoAudio")) { - Settings::getInstance()->setBool("ScreensaverVideoAudio", - screensaver_video_audio->getState()); - s->setNeedsSaving(); - } - }); - #if defined(USE_OPENGL_21) // Render scanlines using a shader. auto screensaver_video_scanlines = std::make_shared(mWindow); diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 8aa1adff2..9074b4742 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -130,7 +130,8 @@ void Settings::setDefaults() // UI settings -> screensaver settings -> slideshow screensaver settings. mIntMap["ScreensaverSwapImageTimeout"] = 8000; mBoolMap["ScreensaverStretchImages"] = false; - mBoolMap["ScreensaverImageScanlines"] = true; + mBoolMap["ScreensaverSlideshowGameInfo"] = true; + mBoolMap["ScreensaverSlideshowScanlines"] = true; mBoolMap["ScreensaverSlideshowCustomImages"] = false; mBoolMap["ScreensaverSlideshowRecurse"] = false; mStringMap["ScreensaverSlideshowImageDir"] = @@ -138,9 +139,9 @@ void Settings::setDefaults() // UI settings -> screensaver settings -> video screensaver settings. mIntMap["ScreensaverSwapVideoTimeout"] = 25000; - mBoolMap["ScreensaverStretchVideos"] = false; - mStringMap["ScreensaverVideoGameInfo"] = "always"; mBoolMap["ScreensaverVideoAudio"] = false; + mBoolMap["ScreensaverStretchVideos"] = false; + mBoolMap["ScreensaverVideoGameInfo"] = true; mBoolMap["ScreensaverVideoScanlines"] = true; mBoolMap["ScreensaverVideoBlur"] = false; diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 388a5c3c3..74faaa52c 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -3,7 +3,7 @@ // EmulationStation Desktop Edition // Window.cpp // -// Window management, screensaver and help prompts. +// Window management, screensaver management, and help prompts. // The input stack starts here as well, as this is the first instance called by InputManager. // @@ -33,10 +33,9 @@ Window::Window() mGameLaunchedState(false), mAllowTextScrolling(true), mCachedBackground(false), - mSaturationAmount(1.0), + mInvalidatedCachedBackground(false), mTopOpacity(0), - mTopScale(0.5), - mDimValue(1.0) + mTopScale(0.5) { mHelp = new HelpComponent(this); mBackgroundOverlay = new ImageComponent(this); @@ -266,7 +265,8 @@ void Window::update(int deltaTime) textureVramUsageMiB << " MiB\nMax Texture VRAM: " << textureTotalUsageMiB << " MiB"; mFrameDataText = std::unique_ptr - (mDefaultFonts.at(1)->buildTextCache(ss.str(), 30.f, 30.f, 0xFF00FFFF)); + (mDefaultFonts.at(1)->buildTextCache(ss.str(), Renderer::getScreenWidth() * + 0.02 , Renderer::getScreenHeight() * 0.02, 0xFF00FFFF)); } mFrameTimeElapsed = 0; @@ -322,17 +322,43 @@ void Window::render() Renderer::getScreenWidth(), Renderer::getScreenHeight()); mBackgroundOverlay->setImage(mPostprocessedBackground); + mBackgroundOverlay->render(transform); + + // Dim the background. We need to do this as a separate step as combining + // it with the blurring leads to very strange and severe artifacts. + // This is for sure a bug that needs to be resolved at some later date. + Renderer::shaderParameters blackParameters; + blackParameters.fragmentDimValue = 0.6; + Renderer::shaderPostprocessing(Renderer::SHADER_DIM, + blackParameters, processedTexture); + + mPostprocessedBackground->initFromPixels(processedTexture, + Renderer::getScreenWidth(), Renderer::getScreenHeight()); + + mBackgroundOverlay->setImage(mPostprocessedBackground); + + // The following is done to avoid fading in if the cached image was + // invalidated (rather than the menu being opened). + if (mInvalidatedCachedBackground) { + mBackgroundOverlayOpacity = 255; + mInvalidatedCachedBackground = false; + } + else { + mBackgroundOverlayOpacity = 25; + } delete[] processedTexture; mCachedBackground = true; } + // Fade in the cached background. + mBackgroundOverlay->setOpacity(mBackgroundOverlayOpacity); + if (mBackgroundOverlayOpacity < 255) + mBackgroundOverlayOpacity = Math::clamp(mBackgroundOverlayOpacity + 30, 0, 255); #endif + mBackgroundOverlay->render(transform); #if defined(USE_OPENGL_21) - Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), - Renderer::getScreenHeight(), 0x00000070, 0x00000070); - // Menu opening effects (scale-up and fade-in). if (Settings::getInstance()->getString("MenuOpeningEffect") == "scale-up") { if (mTopScale < 1.0) @@ -394,60 +420,6 @@ void Window::render() } } - #if defined(USE_OPENGL_21) - // Shaders for the screensavers. - if (mScreensaver->isScreensaverActive()) { - if (Settings::getInstance()->getString("ScreensaverType") == "video") { - if (mScreensaver->getHasMediaFiles()) { - if (Settings::getInstance()->getBool("ScreensaverVideoBlur")) - Renderer::shaderPostprocessing(Renderer::SHADER_BLUR_HORIZONTAL); - if (Settings::getInstance()->getBool("ScreensaverVideoScanlines")) - Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); - } - else { - // If there are no videos, fade in a black screen. - Renderer::shaderParameters blackParameters; - blackParameters.fragmentDimValue = mDimValue; - Renderer::shaderPostprocessing(Renderer::SHADER_DIM, blackParameters); - if (mDimValue > 0.0) - mDimValue = Math::clamp(mDimValue-0.045, 0.0, 1.0); - } - } - else if (Settings::getInstance()->getString("ScreensaverType") == "slideshow") { - if (mScreensaver->getHasMediaFiles()) { - if (Settings::getInstance()->getBool("ScreensaverImageScanlines")) - Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); - } - else { - // If there are no images, fade in a black screen. - Renderer::shaderParameters blackParameters; - blackParameters.fragmentDimValue = mDimValue; - Renderer::shaderPostprocessing(Renderer::SHADER_DIM, blackParameters); - if (mDimValue > 0.0) - mDimValue = Math::clamp(mDimValue-0.045, 0.0, 1.0); - } - } - else if (Settings::getInstance()->getString("ScreensaverType") == "dim") { - Renderer::shaderParameters dimParameters; - dimParameters.fragmentDimValue = mDimValue; - Renderer::shaderPostprocessing(Renderer::SHADER_DIM, dimParameters); - if (mDimValue > 0.4) - mDimValue = Math::clamp(mDimValue-0.021, 0.4, 1.0); - dimParameters.fragmentSaturation = mSaturationAmount; - Renderer::shaderPostprocessing(Renderer::SHADER_DESATURATE, dimParameters); - if (mSaturationAmount > 0.0) - mSaturationAmount = Math::clamp(mSaturationAmount-0.035, 0.0, 1.0); - } - else if (Settings::getInstance()->getString("ScreensaverType") == "black") { - Renderer::shaderParameters blackParameters; - blackParameters.fragmentDimValue = mDimValue; - Renderer::shaderPostprocessing(Renderer::SHADER_DIM, blackParameters); - if (mDimValue > 0.0) - mDimValue = Math::clamp(mDimValue-0.045, 0.0, 1.0); - } - } - #endif - if (Settings::getInstance()->getBool("DisplayGPUStatistics") && mFrameDataText) { Renderer::setMatrix(Transform4x4f::Identity()); mDefaultFonts.at(1)->renderTextCache(mFrameDataText.get()); @@ -632,9 +604,6 @@ bool Window::cancelScreensaver() (*it)->onPauseVideo(); } - mSaturationAmount = 1.0; - mDimValue = 1.0; - return true; } diff --git a/es-core/src/Window.h b/es-core/src/Window.h index b1ddb34cd..567ba8f71 100644 --- a/es-core/src/Window.h +++ b/es-core/src/Window.h @@ -3,7 +3,7 @@ // EmulationStation Desktop Edition // Window.h // -// Window management, screensaver and help prompts. +// Window management, screensaver management, and help prompts. // The input stack starts here as well, as this is the first instance called by InputManager. // @@ -42,7 +42,6 @@ public: virtual bool isScreensaverActive() = 0; virtual FileData* getCurrentGame() = 0; virtual void launchGame() = 0; - virtual bool getHasMediaFiles() = 0; }; class InfoPopup @@ -96,7 +95,8 @@ public: void setAllowTextScrolling(bool setting) { mAllowTextScrolling = setting; }; bool getAllowTextScrolling() { return mAllowTextScrolling; }; - void invalidateCachedBackground() { mCachedBackground = false; }; + void invalidateCachedBackground() + { mCachedBackground = false; mInvalidatedCachedBackground = true;}; private: void onSleep(); @@ -107,6 +107,7 @@ private: HelpComponent* mHelp; ImageComponent* mBackgroundOverlay; + unsigned char mBackgroundOverlayOpacity; Screensaver* mScreensaver; InfoPopup* mInfoPopup; std::vector mGuiStack; @@ -125,11 +126,10 @@ private: bool mGameLaunchedState; bool mAllowTextScrolling; bool mCachedBackground; + bool mInvalidatedCachedBackground; - float mSaturationAmount; unsigned char mTopOpacity; float mTopScale; - float mDimValue; bool mRenderedHelpPrompts; }; diff --git a/es-core/src/renderers/Renderer.cpp b/es-core/src/renderers/Renderer.cpp index d4e56b836..7dec73b6d 100644 --- a/es-core/src/renderers/Renderer.cpp +++ b/es-core/src/renderers/Renderer.cpp @@ -370,8 +370,7 @@ namespace Renderer else { bindTexture(0); } - drawTriangleStrips(vertices, 4, _trans, - _srcBlendFactor, _dstBlendFactor); + drawTriangleStrips(vertices, 4, _trans, _srcBlendFactor, _dstBlendFactor); } unsigned int rgbaToABGR(const unsigned int _color) diff --git a/es-core/src/renderers/Renderer_GL21.cpp b/es-core/src/renderers/Renderer_GL21.cpp index 2adeca94f..157c8b3d0 100644 --- a/es-core/src/renderers/Renderer_GL21.cpp +++ b/es-core/src/renderers/Renderer_GL21.cpp @@ -266,6 +266,7 @@ namespace Renderer GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor), convertBlendFactor(_dstBlendFactor))); + #if defined(USE_OPENGL_21) if (_vertices[0].shaders == 0) { GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices)); } @@ -348,6 +349,7 @@ namespace Renderer } } } + #endif } void setProjection(const Transform4x4f& _projection)