diff --git a/AUTHORS.md b/AUTHORS.md index e5caf5fa58..156d526917 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -232,6 +232,7 @@ Programmers Tess (tescoShoppah) thegriglat Thomas Luppi (Digmaster) + Tim Hagberg (hazardMan) tlmullis trav tri4ng1e diff --git a/CHANGELOG.md b/CHANGELOG.md index 8656f792df..7429aa2ddd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -231,7 +231,9 @@ Bug #8378: Korean bitmap fonts are unusable Bug #8439: Creatures without models can crash the game Bug #8441: Freeze when using video main menu replacers + Bug #8445: Launcher crashes on exit when cell name loading thread is still running Bug #8462: Crashes when resizing the window on macOS + Bug #8465: Blue screen w/ antialiasing and post-processing on macOS Feature #1415: Infinite fall failsafe Feature #2566: Handle NAM9 records for manual cell references Feature #3501: OpenMW-CS: Instance Editing - Shortcuts for axial locking diff --git a/CMakeLists.txt b/CMakeLists.txt index bd66eb2c48..1c84e06c86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,7 +82,7 @@ message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MINOR 49) set(OPENMW_VERSION_RELEASE 0) -set(OPENMW_LUA_API_REVISION 72) +set(OPENMW_LUA_API_REVISION 73) set(OPENMW_POSTPROCESSING_API_REVISION 2) set(OPENMW_VERSION_COMMITHASH "") diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index c1bcc8f944..f5c0694a3b 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -159,6 +159,7 @@ Launcher::DataFilesPage::DataFilesPage(const Files::ConfigurationManager& cfg, C , mGameSettings(gameSettings) , mLauncherSettings(launcherSettings) , mNavMeshToolInvoker(new Process::ProcessInvoker(this)) + , mReloadCellsThread(&DataFilesPage::reloadCells, this) { ui.setupUi(this); setObjectName("DataFilesPage"); @@ -205,6 +206,16 @@ Launcher::DataFilesPage::DataFilesPage(const Files::ConfigurationManager& cfg, C slotAddonDataChanged(); } +Launcher::DataFilesPage::~DataFilesPage() +{ + { + const std::lock_guard lock(mReloadCellsMutex); + mAbortReloadCells = true; + mStartReloadCells.notify_one(); + } + mReloadCellsThread.join(); +} + void Launcher::DataFilesPage::buildView() { QToolButton* refreshButton = mSelector->refreshButton(); @@ -991,31 +1002,45 @@ bool Launcher::DataFilesPage::showDeleteMessageBox(const QString& text) void Launcher::DataFilesPage::slotAddonDataChanged() { QStringList selectedFiles = selectedFilePaths(); - if (previousSelectedFiles != selectedFiles) + if (mSelectedFiles != selectedFiles) { - previousSelectedFiles = selectedFiles; - // Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a - // barely perceptible UI lag. Splitting into its own thread to alleviate that. - std::thread loadCellsThread(&DataFilesPage::reloadCells, this, selectedFiles); - loadCellsThread.detach(); + const std::lock_guard lock(mReloadCellsMutex); + mSelectedFiles = std::move(selectedFiles); + mReloadCells = true; + mStartReloadCells.notify_one(); } } -// Mutex lock to run reloadCells synchronously. -static std::mutex reloadCellsMutex; - -void Launcher::DataFilesPage::reloadCells(QStringList selectedFiles) +void Launcher::DataFilesPage::reloadCells() { - // Use a mutex lock so that we can prevent two threads from executing the rest of this code at the same time - // Based on https://stackoverflow.com/a/5429695/531762 - std::unique_lock lock(reloadCellsMutex); + std::unique_lock lock(mReloadCellsMutex); - // The following code will run only if there is not another thread currently running it - CellNameLoader cellNameLoader; - QSet set = cellNameLoader.getCellNames(selectedFiles); - QStringList cellNamesList(set.begin(), set.end()); - std::sort(cellNamesList.begin(), cellNamesList.end()); - emit signalLoadedCellsChanged(cellNamesList); + while (true) + { + mStartReloadCells.wait(lock); + + if (mAbortReloadCells) + return; + + if (!std::exchange(mReloadCells, false)) + continue; + + QStringList selectedFiles = mSelectedFiles; + + lock.unlock(); + + CellNameLoader cellNameLoader; + QSet set = cellNameLoader.getCellNames(selectedFiles); + QStringList cellNamesList(set.begin(), set.end()); + std::sort(cellNamesList.begin(), cellNamesList.end()); + + emit signalLoadedCellsChanged(std::move(cellNamesList)); + + lock.lock(); + + if (mAbortReloadCells) + return; + } } void Launcher::DataFilesPage::startNavMeshTool() diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 5d03cdf800..ac98743dab 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -10,6 +10,10 @@ #include #include +#include +#include +#include + class QSortFilterProxyModel; class QAbstractItemModel; class QMenu; @@ -47,6 +51,7 @@ namespace Launcher public: explicit DataFilesPage(const Files::ConfigurationManager& cfg, Config::GameSettings& gameSettings, Config::LauncherSettings& launcherSettings, MainDialog* parent = nullptr); + ~DataFilesPage(); QAbstractItemModel* profilesModel() const; @@ -119,7 +124,7 @@ namespace Launcher Config::LauncherSettings& mLauncherSettings; QString mPreviousProfile; - QStringList previousSelectedFiles; + QStringList mSelectedFiles; QString mDataLocal; QStringList mKnownArchives; QStringList mNewDataDirs; @@ -127,6 +132,12 @@ namespace Launcher Process::ProcessInvoker* mNavMeshToolInvoker; NavMeshToolProgress mNavMeshToolProgress; + bool mReloadCells = false; + bool mAbortReloadCells = false; + std::mutex mReloadCellsMutex; + std::condition_variable mStartReloadCells; + std::thread mReloadCellsThread; + void addArchive(const QString& name, Qt::CheckState selected, int row = -1); void addArchivesFromDir(const QString& dir); void buildView(); @@ -140,7 +151,7 @@ namespace Launcher void addProfile(const QString& profile, bool setAsCurrent); void checkForDefaultProfile(); void populateFileViews(const QString& contentModelName); - void reloadCells(QStringList selectedFiles); + void reloadCells(); void refreshDataFilesView(); void updateNavMeshProgress(int minDataSize); void slotCopySelectedItemsPaths(); diff --git a/apps/openmw/mwlua/localscripts.cpp b/apps/openmw/mwlua/localscripts.cpp index 7a3e9ff23a..4bdfb0d13a 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -64,7 +64,7 @@ namespace MWLua = [](SelfObject& self) { return "openmw.self[" + self.toString() + "]"; }; selfAPI["object"] = sol::readonly_property([](SelfObject& self) -> LObject { return LObject(self); }); selfAPI["controls"] = sol::readonly_property([](SelfObject& self) { return &self.mControls; }); - selfAPI["isActive"] = [](SelfObject& self) { return &self.mIsActive; }; + selfAPI["isActive"] = [](SelfObject& self) -> bool { return self.mIsActive; }; selfAPI["enableAI"] = [](SelfObject& self, bool v) { self.mControls.mDisableAI = !v; }; selfAPI["ATTACK_TYPE"] = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs(lua, diff --git a/apps/openmw/mwrender/postprocessor.cpp b/apps/openmw/mwrender/postprocessor.cpp index 4847da9cee..8b835a4d47 100644 --- a/apps/openmw/mwrender/postprocessor.cpp +++ b/apps/openmw/mwrender/postprocessor.cpp @@ -503,6 +503,7 @@ namespace MWRender if (mSamples > 1) { fbos[FBO_Multisample] = new osg::FrameBufferObject; + fbos[FBO_Intercept] = new osg::FrameBufferObject; auto colorRB = createFrameBufferAttachmentFromTemplate( Usage::RENDER_BUFFER, width, height, textures[Tex_Scene], mSamples); if (mNormals && mNormalsSupported) @@ -511,6 +512,8 @@ namespace MWRender Usage::RENDER_BUFFER, width, height, textures[Tex_Normal], mSamples); fbos[FBO_Multisample]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, normalRB); fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, normalRB); + fbos[FBO_Intercept]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, + Stereo::createMultiviewCompatibleAttachment(textures[Tex_Normal])); } auto depthRB = createFrameBufferAttachmentFromTemplate( Usage::RENDER_BUFFER, width, height, textures[Tex_Depth], mSamples); @@ -519,11 +522,8 @@ namespace MWRender osg::FrameBufferObject::BufferComponent::PACKED_DEPTH_STENCIL_BUFFER, depthRB); fbos[FBO_FirstPerson]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, colorRB); - fbos[FBO_Intercept] = new osg::FrameBufferObject; fbos[FBO_Intercept]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER0, Stereo::createMultiviewCompatibleAttachment(textures[Tex_Scene])); - fbos[FBO_Intercept]->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER1, - Stereo::createMultiviewCompatibleAttachment(textures[Tex_Normal])); } else { diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index 5963e274ec..aaaf56e18a 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -245,11 +245,7 @@ namespace fx else if (key == "author") mAuthor = parseString(); else if (key == "glsl_version") - { - int version = parseInteger(); - if (mUBO && version > 330) - mGLSLVersion = version; - } + mGLSLVersion = std::max(mGLSLVersion, parseInteger()); else if (key == "flags") mFlags = parseFlags(); else if (key == "hdr")