From de59d793887187ab4a49a1ed7f1bba641848c171 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 10 Jul 2024 20:13:09 +0200 Subject: [PATCH] Update the menu video from a separate thread and respect window resizes --- CHANGELOG.md | 1 + apps/openmw/mwgui/mainmenu.cpp | 92 +++++++++++++++++++++------------- apps/openmw/mwgui/mainmenu.hpp | 21 ++++++-- 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0558186b3d..d0fa5305d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -185,6 +185,7 @@ Bug #8018: Potion effects should never explode and always apply on self Bug #8021: Player's scale doesn't reset when starting a new game Bug #8048: Actors can generate negative collision extents and have no collision + Bug #8063: menu_background.bik video with audio freezes the game forever Bug #8064: Lua move360 script doesn't respect the enableZoom/disableZoom Camera interface setting Feature #1415: Infinite fall failsafe Feature #2566: Handle NAM9 records for manual cell references diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 4ea31778ce..da747dd7a2 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,56 @@ namespace MWGui { + void MenuVideo::run() + { + Misc::FrameRateLimiter frameRateLimiter + = Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit()); + while (mRunning) + { + // If finished playing, start again + if (!mVideo->update()) + mVideo->playVideo("video\\menu_background.bik"); + frameRateLimiter.limit(); + } + } + + MenuVideo::MenuVideo(const VFS::Manager* vfs) + : mRunning(true) + { + // Use black background to correct aspect ratio + mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal( + "ImageBox", 0, 0, 1, 1, MyGUI::Align::Default, "MainMenuBackground"); + mVideoBackground->setImageTexture("black"); + + mVideo = mVideoBackground->createWidget( + "ImageBox", 0, 0, 1, 1, MyGUI::Align::Stretch, "MainMenuBackground"); + mVideo->setVFS(vfs); + + mVideo->playVideo("video\\menu_background.bik"); + mThread = std::thread([this] { run(); }); + } + + void MenuVideo::resize(int screenWidth, int screenHeight) + { + const bool stretch = Settings::gui().mStretchMenuBackground; + mVideoBackground->setSize(screenWidth, screenHeight); + mVideo->autoResize(stretch); + mVideo->setVisible(true); + } + + MenuVideo::~MenuVideo() + { + mRunning = false; + mThread.join(); + try + { + MyGUI::Gui::getInstance().destroyWidget(mVideoBackground); + } + catch (const MyGUI::Exception& e) + { + Log(Debug::Error) << "Error in the destructor: " << e.what(); + } + } MainMenu::MainMenu(int w, int h, const VFS::Manager* vfs, const std::string& versionDescription) : WindowBase("openmw_mainmenu.layout") @@ -32,8 +83,6 @@ namespace MWGui , mVFS(vfs) , mButtonBox(nullptr) , mBackground(nullptr) - , mVideoBackground(nullptr) - , mVideo(nullptr) { getWidget(mVersionText, "VersionText"); mVersionText->setCaption(versionDescription); @@ -51,6 +100,8 @@ namespace MWGui mHeight = h; updateMenu(); + if (mVideo) + mVideo->resize(w, h); } void MainMenu::setVisible(bool visible) @@ -146,9 +197,7 @@ namespace MWGui { if (mVideo && !show) { - MyGUI::Gui::getInstance().destroyWidget(mVideoBackground); - mVideoBackground = nullptr; - mVideo = nullptr; + mVideo.reset(); } if (mBackground && !show) { @@ -164,27 +213,12 @@ namespace MWGui if (mHasAnimatedMenu) { if (!mVideo) - { - // Use black background to correct aspect ratio - mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal( - "ImageBox", 0, 0, 1, 1, MyGUI::Align::Default, "MainMenuBackground"); - mVideoBackground->setImageTexture("black"); - - mVideo = mVideoBackground->createWidget( - "ImageBox", 0, 0, 1, 1, MyGUI::Align::Stretch, "MainMenuBackground"); - mVideo->setVFS(mVFS); + mVideo.emplace(mVFS); - mVideo->playVideo("video\\menu_background.bik"); - } - - MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + const auto& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); int screenWidth = viewSize.width; int screenHeight = viewSize.height; - mVideoBackground->setSize(screenWidth, screenHeight); - - mVideo->autoResize(stretch); - - mVideo->setVisible(true); + mVideo->resize(screenWidth, screenHeight); } else { @@ -198,18 +232,6 @@ namespace MWGui } } - void MainMenu::onFrame(float dt) - { - if (mVideo) - { - if (!mVideo->update()) - { - // If finished playing, start again - mVideo->playVideo("video\\menu_background.bik"); - } - } - } - bool MainMenu::exit() { if (MWBase::Environment::get().getWindowManager()->isSettingsWindowVisible()) diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index ee6a5cdb16..06a8c945c1 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -2,6 +2,8 @@ #define OPENMW_GAME_MWGUI_MAINMENU_H #include +#include +#include #include "savegamedialog.hpp" #include "windowbase.hpp" @@ -21,6 +23,20 @@ namespace MWGui class BackgroundImage; class VideoWidget; + class MenuVideo + { + MyGUI::ImageBox* mVideoBackground; + VideoWidget* mVideo; + std::thread mThread; + bool mRunning; + + void run(); + + public: + MenuVideo(const VFS::Manager* vfs); + void resize(int w, int h); + ~MenuVideo(); + }; class MainMenu : public WindowBase { @@ -36,8 +52,6 @@ namespace MWGui void setVisible(bool visible) override; - void onFrame(float dt) override; - bool exit() override; private: @@ -48,8 +62,7 @@ namespace MWGui BackgroundImage* mBackground; - MyGUI::ImageBox* mVideoBackground; - VideoWidget* mVideo; // For animated main menus + std::optional mVideo; // For animated main menus std::map> mButtons;