From 8a8b4986da14c5b80d5d5ecebbb8ef2718c3f0c1 Mon Sep 17 00:00:00 2001 From: Giovanni Bodega Date: Wed, 6 May 2020 16:39:32 +0100 Subject: [PATCH 001/107] Fixed passed indexes for object deletion #5384 --- apps/opencs/model/world/idtable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index a0dbd7bad..8ae2fce54 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -94,7 +94,7 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value // views that the whole row has changed. emit dataChanged(this->index(index.row(), 0), - this->index(index.row(), columnCount(index.parent()))); + this->index(index.row(), columnCount(index.parent()) - 1)); } else { From 411b6dcd8e581a58106b16e12c2b8e4dcae7a796 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Mon, 18 May 2020 14:46:20 +0300 Subject: [PATCH 002/107] Don't clear spells for a dead player, preventing resurrection problems --- apps/openmw/mwmechanics/actors.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 223d9fc34..55f8feb87 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1865,13 +1865,17 @@ namespace MWMechanics } else if (killResult == CharacterController::Result_DeathAnimJustFinished) { + bool isPlayer = iter->first == getPlayer(); notifyDied(iter->first); // Reset magic effects and recalculate derived effects // One case where we need this is to make sure bound items are removed upon death stats.modifyMagicEffects(MWMechanics::MagicEffects()); stats.getActiveSpells().clear(); - stats.getSpells().clear(); + + if (!isPlayer) + stats.getSpells().clear(); + // Make sure spell effects are removed purgeSpellEffects(stats.getActorId()); @@ -1880,7 +1884,7 @@ namespace MWMechanics if (iter->first.getClass().isNpc()) calculateNpcStatModifiers(iter->first, 0); - if( iter->first == getPlayer()) + if (isPlayer) { //player's death animation is over MWBase::Environment::get().getStateManager()->askLoadRecent(); From 487bfed67256b7c4b8862716965905439c745216 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 24 Jun 2020 14:51:26 +0400 Subject: [PATCH 003/107] Use QMultiMap instead of QMap --- components/config/gamesettings.cpp | 11 ++++------- components/config/gamesettings.hpp | 14 ++++++++------ components/config/launchersettings.cpp | 6 +++--- components/config/launchersettings.hpp | 2 +- components/config/settingsbase.hpp | 7 ++++--- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index fc1d81368..b771b7fc8 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -2,11 +2,8 @@ #include "launchersettings.hpp" #include -#include #include -#include #include -#include #include @@ -105,9 +102,9 @@ bool Config::GameSettings::readUserFile(QTextStream &stream) return readFile(stream, mUserSettings); } -bool Config::GameSettings::readFile(QTextStream &stream, QMap &settings) +bool Config::GameSettings::readFile(QTextStream &stream, QMultiMap &settings) { - QMap cache; + QMultiMap cache; QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); while (!stream.atEnd()) { @@ -151,7 +148,7 @@ bool Config::GameSettings::readFile(QTextStream &stream, QMap values.append(settings.values(key)); if (!values.contains(value)) { - cache.insertMulti(key, value); + cache.insert(key, value); } } } @@ -368,7 +365,7 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) *iter = QString(); // assume no match QString key = settingRegex.cap(1); QString keyVal = settingRegex.cap(1)+"="+settingRegex.cap(2); - QMap::const_iterator i = mUserSettings.find(key); + QMultiMap::const_iterator i = mUserSettings.find(key); while (i != mUserSettings.end() && i.key() == key) { QString settingLine = i.key() + "=" + i.value(); diff --git a/components/config/gamesettings.hpp b/components/config/gamesettings.hpp index eeac893c2..a6876b83d 100644 --- a/components/config/gamesettings.hpp +++ b/components/config/gamesettings.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include @@ -31,7 +31,9 @@ namespace Config inline void setValue(const QString &key, const QString &value) { + mSettings.remove(key); mSettings.insert(key, value); + mUserSettings.remove(key); mUserSettings.insert(key, value); } @@ -39,11 +41,11 @@ namespace Config { QStringList values = mSettings.values(key); if (!values.contains(value)) - mSettings.insertMulti(key, value); + mSettings.insert(key, value); values = mUserSettings.values(key); if (!values.contains(value)) - mUserSettings.insertMulti(key, value); + mUserSettings.insert(key, value); } inline void remove(const QString &key) @@ -63,7 +65,7 @@ namespace Config QStringList values(const QString &key, const QStringList &defaultValues = QStringList()) const; bool readFile(QTextStream &stream); - bool readFile(QTextStream &stream, QMap &settings); + bool readFile(QTextStream &stream, QMultiMap &settings); bool readUserFile(QTextStream &stream); bool writeFile(QTextStream &stream); @@ -78,8 +80,8 @@ namespace Config Files::ConfigurationManager &mCfgMgr; void validatePaths(); - QMap mSettings; - QMap mUserSettings; + QMultiMap mSettings; + QMultiMap mUserSettings; QStringList mDataDirs; QString mDataLocal; diff --git a/components/config/launchersettings.cpp b/components/config/launchersettings.cpp index 91bf450f4..ae591ef58 100644 --- a/components/config/launchersettings.cpp +++ b/components/config/launchersettings.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include @@ -22,7 +22,7 @@ Config::LauncherSettings::~LauncherSettings() QStringList Config::LauncherSettings::subKeys(const QString &key) { - QMap settings = SettingsBase::getSettings(); + QMultiMap settings = SettingsBase::getSettings(); QStringList keys = settings.uniqueKeys(); QRegExp keyRe("(.+)/"); @@ -54,7 +54,7 @@ bool Config::LauncherSettings::writeFile(QTextStream &stream) { QString sectionPrefix; QRegExp sectionRe("([^/]+)/(.+)$"); - QMap settings = SettingsBase::getSettings(); + QMultiMap settings = SettingsBase::getSettings(); QMapIterator i(settings); i.toBack(); diff --git a/components/config/launchersettings.hpp b/components/config/launchersettings.hpp index c5eefb22a..1483052bb 100644 --- a/components/config/launchersettings.hpp +++ b/components/config/launchersettings.hpp @@ -6,7 +6,7 @@ namespace Config { - class LauncherSettings : public SettingsBase > + class LauncherSettings : public SettingsBase > { public: LauncherSettings(); diff --git a/components/config/settingsbase.hpp b/components/config/settingsbase.hpp index 08cd0bfc6..119971716 100644 --- a/components/config/settingsbase.hpp +++ b/components/config/settingsbase.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace Config { @@ -33,7 +33,7 @@ namespace Config { QStringList values = mSettings.values(key); if (!values.contains(value)) - mSettings.insertMulti(key, value); + mSettings.insert(key, value); } inline void setMultiValueEnabled(bool enable) @@ -83,8 +83,9 @@ namespace Config if (!values.contains(value)) { if (mMultiValue) { - cache.insertMulti(key, value); + cache.insert(key, value); } else { + cache.remove(key); cache.insert(key, value); } } From 40ad87bc4de2c43be913d822e185c28537ad06e0 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 25 Jun 2020 21:46:07 +0200 Subject: [PATCH 004/107] Replace OpenThreads by std types --- apps/opencs/CMakeLists.txt | 1 - apps/opencs/view/render/scenewidget.cpp | 5 +- apps/openmw/CMakeLists.txt | 1 - apps/openmw/engine.cpp | 4 +- apps/openmw/mwbase/environment.cpp | 6 +-- apps/openmw/mwgui/windowmanagerimp.cpp | 6 ++- apps/openmw/mwrender/objectpaging.cpp | 16 +++--- apps/openmw/mwrender/objectpaging.hpp | 6 +-- apps/openmw/mwrender/renderingmanager.cpp | 14 ++--- apps/openmw/mwsound/openal_output.cpp | 43 ++++++++-------- apps/openmw/mwworld/scene.cpp | 4 +- components/esmterrain/storage.cpp | 4 +- components/esmterrain/storage.hpp | 5 +- components/nifosg/nifloader.cpp | 6 ++- components/resource/multiobjectcache.cpp | 12 ++--- components/resource/multiobjectcache.hpp | 3 +- components/resource/objectcache.hpp | 25 ++++----- components/resource/scenemanager.cpp | 12 ++--- components/resource/scenemanager.hpp | 3 +- components/sceneutil/mwshadowtechnique.cpp | 10 ++-- components/sceneutil/mwshadowtechnique.hpp | 6 ++- components/shader/shadermanager.cpp | 6 +-- components/shader/shadermanager.hpp | 5 +- components/terrain/buffercache.cpp | 14 +++-- components/terrain/buffercache.hpp | 5 +- components/terrain/compositemaprenderer.cpp | 10 ++-- components/terrain/compositemaprenderer.hpp | 5 +- components/terrain/quadtreeworld.cpp | 2 +- components/terrain/quadtreeworld.hpp | 4 +- extern/osg-ffmpeg-videoplayer/videostate.cpp | 54 ++++++++++++-------- extern/osg-ffmpeg-videoplayer/videostate.hpp | 16 +++--- 31 files changed, 166 insertions(+), 147 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 401e7896d..dc9b98596 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -216,7 +216,6 @@ endif(APPLE) target_link_libraries(openmw-cs ${OSG_LIBRARIES} - ${OPENTHREADS_LIBRARIES} ${OSGTEXT_LIBRARIES} ${OSGUTIL_LIBRARIES} ${OSGVIEWER_LIBRARIES} diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 9747c3de0..f3186e76a 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -1,5 +1,8 @@ #include "scenewidget.hpp" +#include +#include + #include #include #include @@ -184,7 +187,7 @@ void CompositeViewer::update() double minFrameTime = _runMaxFrameRate > 0.0 ? 1.0 / _runMaxFrameRate : 0.0; if (dt < minFrameTime) { - OpenThreads::Thread::microSleep(1000*1000*(minFrameTime-dt)); + std::this_thread::sleep_for(std::chrono::duration(minFrameTime - dt)); } } diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a9f3d24e2..f6c99778e 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -123,7 +123,6 @@ include_directories( target_link_libraries(openmw ${OSG_LIBRARIES} - ${OPENTHREADS_LIBRARIES} ${OSGPARTICLE_LIBRARIES} ${OSGUTIL_LIBRARIES} ${OSGDB_LIBRARIES} diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 0792f4eaf..4ce0edc5c 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include @@ -762,7 +764,7 @@ void OMW::Engine::go() if (!frame(dt)) { - OpenThreads::Thread::microSleep(5000); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); continue; } else diff --git a/apps/openmw/mwbase/environment.cpp b/apps/openmw/mwbase/environment.cpp index c70debda1..764a07ec9 100644 --- a/apps/openmw/mwbase/environment.cpp +++ b/apps/openmw/mwbase/environment.cpp @@ -1,8 +1,8 @@ #include "environment.hpp" #include - -#include +#include +#include #include "world.hpp" #include "scriptmanager.hpp" @@ -99,7 +99,7 @@ void MWBase::Environment::limitFrameRate(double dt) const double minFrameTime = 1.0 / static_cast(mFrameRateLimit); if (thisFrameTime < minFrameTime) { - OpenThreads::Thread::microSleep(1000*1000*(minFrameTime-thisFrameTime)); + std::this_thread::sleep_for(std::chrono::duration(minFrameTime - thisFrameTime)); } } } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e1f7a4fbf..d49a51576 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1,6 +1,8 @@ #include "windowmanagerimp.hpp" #include +#include +#include #include @@ -751,7 +753,7 @@ namespace MWGui MWBase::Environment::get().getInputManager()->update(dt, true, false); if (!mWindowVisible) - OpenThreads::Thread::microSleep(5000); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); else { mViewer->eventTraversal(); @@ -1788,7 +1790,7 @@ namespace MWGui if (!mWindowVisible) { mVideoWidget->pause(); - OpenThreads::Thread::microSleep(5000); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); } else { diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 202541ea5..f7b0e20e3 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -428,7 +428,7 @@ namespace MWRender if (activeGrid) { - OpenThreads::ScopedLock lock(mRefTrackerMutex); + std::lock_guard lock(mRefTrackerMutex); for (auto ref : getRefTracker().mBlacklist) refs.erase(ref); } @@ -464,7 +464,7 @@ namespace MWRender float dSqr = (viewPoint - pos).length2(); if (!activeGrid) { - OpenThreads::ScopedLock lock(mSizeCacheMutex); + std::lock_guard lock(mSizeCacheMutex); SizeCache::iterator found = mSizeCache.find(pair.first); if (found != mSizeCache.end() && found->second < dSqr*minSize*minSize) continue; @@ -501,7 +501,7 @@ namespace MWRender } { - OpenThreads::ScopedLock lock(mRefTrackerMutex); + std::lock_guard lock(mRefTrackerMutex); if (getRefTracker().mDisabled.count(pair.first)) continue; } @@ -509,7 +509,7 @@ namespace MWRender float radius2 = cnode->getBound().radius2() * ref.mScale*ref.mScale; if (radius2 < dSqr*minSize*minSize && !activeGrid) { - OpenThreads::ScopedLock lock(mSizeCacheMutex); + std::lock_guard lock(mSizeCacheMutex); mSizeCache[pair.first] = radius2; continue; } @@ -685,7 +685,7 @@ namespace MWRender return false; { - OpenThreads::ScopedLock lock(mRefTrackerMutex); + std::lock_guard lock(mRefTrackerMutex); if (enabled && !getWritableRefTracker().mDisabled.erase(refnum)) return false; if (!enabled && !getWritableRefTracker().mDisabled.insert(refnum).second) return false; if (mRefTrackerLocked) return false; @@ -706,7 +706,7 @@ namespace MWRender return false; { - OpenThreads::ScopedLock lock(mRefTrackerMutex); + std::lock_guard lock(mRefTrackerMutex); if (!getWritableRefTracker().mBlacklist.insert(refnum).second) return false; if (mRefTrackerLocked) return false; } @@ -724,7 +724,7 @@ namespace MWRender void ObjectPaging::clear() { - OpenThreads::ScopedLock lock(mRefTrackerMutex); + std::lock_guard lock(mRefTrackerMutex); mRefTrackerNew.mDisabled.clear(); mRefTrackerNew.mBlacklist.clear(); mRefTrackerLocked = true; @@ -734,7 +734,7 @@ namespace MWRender { if (!mRefTrackerLocked) return false; { - OpenThreads::ScopedLock lock(mRefTrackerMutex); + std::lock_guard lock(mRefTrackerMutex); mRefTrackerLocked = false; if (mRefTracker == mRefTrackerNew) return false; diff --git a/apps/openmw/mwrender/objectpaging.hpp b/apps/openmw/mwrender/objectpaging.hpp index 9c2c54f65..2ca302038 100644 --- a/apps/openmw/mwrender/objectpaging.hpp +++ b/apps/openmw/mwrender/objectpaging.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include namespace Resource { @@ -58,7 +58,7 @@ namespace MWRender float mMinSizeMergeFactor; float mMinSizeCostMultiplier; - OpenThreads::Mutex mRefTrackerMutex; + std::mutex mRefTrackerMutex; struct RefTracker { std::set mDisabled; @@ -72,7 +72,7 @@ namespace MWRender const RefTracker& getRefTracker() const { return mRefTracker; } RefTracker& getWritableRefTracker() { return mRefTrackerLocked ? mRefTrackerNew : mRefTracker; } - OpenThreads::Mutex mSizeCacheMutex; + std::mutex mSizeCacheMutex; typedef std::map SizeCache; SizeCache mSizeCache; }; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index fc78b6ebb..0c6e48645 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include @@ -709,24 +711,24 @@ namespace MWRender virtual void operator () (osg::RenderInfo& renderInfo) const { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); if (renderInfo.getState()->getFrameStamp()->getFrameNumber() >= mFrame) { mDone = true; - mCondition.signal(); + mCondition.notify_one(); } } void waitTillDone() { - OpenThreads::ScopedLock lock(mMutex); + std::unique_lock lock(mMutex); if (mDone) return; - mCondition.wait(&mMutex); + mCondition.wait(lock); } - mutable OpenThreads::Condition mCondition; - mutable OpenThreads::Mutex mMutex; + mutable std::condition_variable mCondition; + mutable std::mutex mMutex; mutable bool mDone; unsigned int mFrame; }; diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 595518726..1606b2979 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -11,11 +15,6 @@ #include #include -#include -#include -#include -#include - #include "openal_output.hpp" #include "sound_decoder.hpp" #include "sound.hpp" @@ -309,31 +308,33 @@ const ALfloat OpenAL_SoundStream::sBufferLength = 0.125f; // // A background streaming thread (keeps active streams processed) // -struct OpenAL_Output::StreamThread : public OpenThreads::Thread { +struct OpenAL_Output::StreamThread +{ typedef std::vector StreamVec; StreamVec mStreams; std::atomic mQuitNow; - OpenThreads::Mutex mMutex; - OpenThreads::Condition mCondVar; + std::mutex mMutex; + std::condition_variable mCondVar; + std::thread mThread; StreamThread() : mQuitNow(false) + , mThread([this] { run(); }) { - start(); } ~StreamThread() { mQuitNow = true; mMutex.lock(); mMutex.unlock(); - mCondVar.broadcast(); - join(); + mCondVar.notify_all(); + mThread.join(); } // thread entry point - virtual void run() + void run() { - OpenThreads::ScopedLock lock(mMutex); + std::unique_lock lock(mMutex); while(!mQuitNow) { StreamVec::iterator iter = mStreams.begin(); @@ -345,30 +346,30 @@ struct OpenAL_Output::StreamThread : public OpenThreads::Thread { ++iter; } - mCondVar.wait(&mMutex, 50); + mCondVar.wait_for(lock, std::chrono::milliseconds(50)); } } void add(OpenAL_SoundStream *stream) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); if(std::find(mStreams.begin(), mStreams.end(), stream) == mStreams.end()) { mStreams.push_back(stream); - mCondVar.broadcast(); + mCondVar.notify_all(); } } void remove(OpenAL_SoundStream *stream) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); StreamVec::iterator iter = std::find(mStreams.begin(), mStreams.end(), stream); if(iter != mStreams.end()) mStreams.erase(iter); } void removeAll() { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); mStreams.clear(); } @@ -1341,7 +1342,7 @@ double OpenAL_Output::getStreamOffset(Stream *sound) { if(!sound->mHandle) return 0.0; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); - OpenThreads::ScopedLock lock(mStreamThread->mMutex); + std::lock_guard lock(mStreamThread->mMutex); return stream->getStreamOffset(); } @@ -1349,7 +1350,7 @@ float OpenAL_Output::getStreamLoudness(Stream *sound) { if(!sound->mHandle) return 0.0; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); - OpenThreads::ScopedLock lock(mStreamThread->mMutex); + std::lock_guard lock(mStreamThread->mMutex); return stream->getCurrentLoudness(); } @@ -1357,7 +1358,7 @@ bool OpenAL_Output::isStreamPlaying(Stream *sound) { if(!sound->mHandle) return false; OpenAL_SoundStream *stream = reinterpret_cast(sound->mHandle); - OpenThreads::ScopedLock lock(mStreamThread->mMutex); + std::lock_guard lock(mStreamThread->mMutex); return stream->isPlaying(); } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 42fe1a960..5808a6bac 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -1,6 +1,8 @@ #include "scene.hpp" #include +#include +#include #include #include @@ -1143,7 +1145,7 @@ namespace MWWorld } else loadingListener->setProgress(0); - OpenThreads::Thread::microSleep(5000); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); } } diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index fc93706a3..cf27b7128 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -2,8 +2,6 @@ #include -#include - #include #include @@ -548,7 +546,7 @@ namespace ESMTerrain Terrain::LayerInfo Storage::getLayerInfo(const std::string& texture) { - OpenThreads::ScopedLock lock(mLayerInfoMutex); + std::lock_guard lock(mLayerInfoMutex); // Already have this cached? std::map::iterator found = mLayerInfoMap.find(texture); diff --git a/components/esmterrain/storage.hpp b/components/esmterrain/storage.hpp index a5f62ba48..c64531140 100644 --- a/components/esmterrain/storage.hpp +++ b/components/esmterrain/storage.hpp @@ -2,8 +2,7 @@ #define COMPONENTS_ESM_TERRAIN_STORAGE_H #include - -#include +#include #include @@ -138,7 +137,7 @@ namespace ESMTerrain std::string getTextureName (UniqueTextureId id); std::map mLayerInfoMap; - OpenThreads::Mutex mLayerInfoMutex; + std::mutex mLayerInfoMutex; std::string mNormalMapPattern; std::string mNormalHeightMapPattern; diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 88e89b400..dc2d50e15 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1,5 +1,7 @@ #include "nifloader.hpp" +#include + #include #include #include @@ -1725,8 +1727,8 @@ namespace NifOsg { typedef std::set, CompareStateAttribute> Cache; static Cache sCache; - static OpenThreads::Mutex sMutex; - OpenThreads::ScopedLock lock(sMutex); + static std::mutex sMutex; + std::lock_guard lock(sMutex); typename Cache::iterator found = sCache.find(attr); if (found == sCache.end()) found = sCache.insert(attr).first; diff --git a/components/resource/multiobjectcache.cpp b/components/resource/multiobjectcache.cpp index d6639d3ae..9d75d2480 100644 --- a/components/resource/multiobjectcache.cpp +++ b/components/resource/multiobjectcache.cpp @@ -21,7 +21,7 @@ namespace Resource { std::vector > objectsToRemove; { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); // Remove unreferenced entries from object cache ObjectCacheMap::iterator oitr = _objectCache.begin(); @@ -45,7 +45,7 @@ namespace Resource void MultiObjectCache::clear() { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); _objectCache.clear(); } @@ -56,13 +56,13 @@ namespace Resource OSG_ALWAYS << " trying to add NULL object to cache for " << filename << std::endl; return; } - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); _objectCache.insert(std::make_pair(filename, object)); } osg::ref_ptr MultiObjectCache::takeFromObjectCache(const std::string &fileName) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); ObjectCacheMap::iterator found = _objectCache.find(fileName); if (found == _objectCache.end()) return osg::ref_ptr(); @@ -76,7 +76,7 @@ namespace Resource void MultiObjectCache::releaseGLObjects(osg::State *state) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); for(ObjectCacheMap::iterator itr = _objectCache.begin(); itr != _objectCache.end(); @@ -89,7 +89,7 @@ namespace Resource unsigned int MultiObjectCache::getCacheSize() const { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); return _objectCache.size(); } diff --git a/components/resource/multiobjectcache.hpp b/components/resource/multiobjectcache.hpp index b73e29d50..543406ebd 100644 --- a/components/resource/multiobjectcache.hpp +++ b/components/resource/multiobjectcache.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -43,7 +44,7 @@ namespace Resource typedef std::multimap > ObjectCacheMap; ObjectCacheMap _objectCache; - mutable OpenThreads::Mutex _objectCacheMutex; + mutable std::mutex _objectCacheMutex; }; diff --git a/components/resource/objectcache.hpp b/components/resource/objectcache.hpp index 24d7d04a9..6e309a7f7 100644 --- a/components/resource/objectcache.hpp +++ b/components/resource/objectcache.hpp @@ -26,6 +26,7 @@ #include #include +#include namespace osg { @@ -53,7 +54,7 @@ class GenericObjectCache : public osg::Referenced void updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime) { // look for objects with external references and update their time stamp. - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); for(typename ObjectCacheMap::iterator itr=_objectCache.begin(); itr!=_objectCache.end(); ++itr) { // If ref count is greater than 1, the object has an external reference. @@ -71,7 +72,7 @@ class GenericObjectCache : public osg::Referenced { std::vector > objectsToRemove; { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); // Remove expired entries from object cache typename ObjectCacheMap::iterator oitr = _objectCache.begin(); while(oitr != _objectCache.end()) @@ -92,21 +93,21 @@ class GenericObjectCache : public osg::Referenced /** Remove all objects in the cache regardless of having external references or expiry times.*/ void clear() { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); _objectCache.clear(); } /** Add a key,object,timestamp triple to the Registry::ObjectCache.*/ void addEntryToObjectCache(const KeyType& key, osg::Object* object, double timestamp = 0.0) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); _objectCache[key]=ObjectTimeStampPair(object,timestamp); } /** Remove Object from cache.*/ void removeFromObjectCache(const KeyType& key) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); typename ObjectCacheMap::iterator itr = _objectCache.find(key); if (itr!=_objectCache.end()) _objectCache.erase(itr); } @@ -114,7 +115,7 @@ class GenericObjectCache : public osg::Referenced /** Get an ref_ptr from the object cache*/ osg::ref_ptr getRefFromObjectCache(const KeyType& key) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); typename ObjectCacheMap::iterator itr = _objectCache.find(key); if (itr!=_objectCache.end()) return itr->second.first; @@ -124,7 +125,7 @@ class GenericObjectCache : public osg::Referenced /** Check if an object is in the cache, and if it is, update its usage time stamp. */ bool checkInObjectCache(const KeyType& key, double timeStamp) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); typename ObjectCacheMap::iterator itr = _objectCache.find(key); if (itr!=_objectCache.end()) { @@ -137,7 +138,7 @@ class GenericObjectCache : public osg::Referenced /** call releaseGLObjects on all objects attached to the object cache.*/ void releaseGLObjects(osg::State* state) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); for(typename ObjectCacheMap::iterator itr = _objectCache.begin(); itr != _objectCache.end(); ++itr) { osg::Object* object = itr->second.first.get(); @@ -148,7 +149,7 @@ class GenericObjectCache : public osg::Referenced /** call node->accept(nv); for all nodes in the objectCache. */ void accept(osg::NodeVisitor& nv) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); for(typename ObjectCacheMap::iterator itr = _objectCache.begin(); itr != _objectCache.end(); ++itr) { osg::Object* object = itr->second.first.get(); @@ -165,7 +166,7 @@ class GenericObjectCache : public osg::Referenced template void call(Functor& f) { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); for (typename ObjectCacheMap::iterator it = _objectCache.begin(); it != _objectCache.end(); ++it) f(it->first, it->second.first.get()); } @@ -173,7 +174,7 @@ class GenericObjectCache : public osg::Referenced /** Get the number of objects in the cache. */ unsigned int getCacheSize() const { - OpenThreads::ScopedLock lock(_objectCacheMutex); + std::lock_guard lock(_objectCacheMutex); return _objectCache.size(); } @@ -185,7 +186,7 @@ class GenericObjectCache : public osg::Referenced typedef std::map ObjectCacheMap; ObjectCacheMap _objectCache; - mutable OpenThreads::Mutex _objectCacheMutex; + mutable std::mutex _objectCacheMutex; }; diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 8264e3b1e..ca6c7c895 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -126,7 +126,7 @@ namespace Resource void clearCache() { - OpenThreads::ScopedLock lock(_listMutex); + std::lock_guard lock(_listMutex); _sharedTextureList.clear(); _sharedStateSetList.clear(); } @@ -625,7 +625,7 @@ namespace Resource mShaderManager->releaseGLObjects(state); - OpenThreads::ScopedLock lock(mSharedStateMutex); + std::lock_guard lock(mSharedStateMutex); mSharedStateManager->releaseGLObjects(state); } @@ -717,7 +717,7 @@ namespace Resource if (mIncrementalCompileOperation) { - OpenThreads::ScopedLock lock(*mIncrementalCompileOperation->getToCompiledMutex()); + std::lock_guard lock(*mIncrementalCompileOperation->getToCompiledMutex()); osgUtil::IncrementalCompileOperation::CompileSets& sets = mIncrementalCompileOperation->getToCompile(); for(osgUtil::IncrementalCompileOperation::CompileSets::iterator it = sets.begin(); it != sets.end();) { @@ -738,7 +738,7 @@ namespace Resource { ResourceManager::clearCache(); - OpenThreads::ScopedLock lock(mSharedStateMutex); + std::lock_guard lock(mSharedStateMutex); mSharedStateManager->clearCache(); mInstanceCache->clear(); } @@ -747,12 +747,12 @@ namespace Resource { if (mIncrementalCompileOperation) { - OpenThreads::ScopedLock lock(*mIncrementalCompileOperation->getToCompiledMutex()); + std::lock_guard lock(*mIncrementalCompileOperation->getToCompiledMutex()); stats->setAttribute(frameNumber, "Compiling", mIncrementalCompileOperation->getToCompile().size()); } { - OpenThreads::ScopedLock lock(mSharedStateMutex); + std::lock_guard lock(mSharedStateMutex); stats->setAttribute(frameNumber, "Texture", mSharedStateManager->getNumSharedTextures()); stats->setAttribute(frameNumber, "StateSet", mSharedStateManager->getNumSharedStateSets()); } diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index bbe88c9a0..3a72caf6a 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -159,7 +160,7 @@ namespace Resource osg::ref_ptr mInstanceCache; osg::ref_ptr mSharedStateManager; - mutable OpenThreads::Mutex mSharedStateMutex; + mutable std::mutex mSharedStateMutex; Resource::ImageManager* mImageManager; Resource::NifFileManager* mNifFileManager; diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 98771bbb4..fa38da54e 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -891,7 +891,7 @@ MWShadowTechnique::ViewDependentData* MWShadowTechnique::createViewDependentData MWShadowTechnique::ViewDependentData* MWShadowTechnique::getViewDependentData(osgUtil::CullVisitor* cv) { - OpenThreads::ScopedLock lock(_viewDependentDataMapMutex); + std::lock_guard lock(_viewDependentDataMapMutex); ViewDependentDataMap::iterator itr = _viewDependentDataMap.find(cv); if (itr!=_viewDependentDataMap.end()) return itr->second.get(); @@ -1343,7 +1343,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) std::string validRegionUniformName = "validRegionMatrix" + std::to_string(sm_i); osg::ref_ptr validRegionUniform; - OpenThreads::ScopedLock lock(_accessUniformsAndProgramMutex); + std::lock_guard lock(_accessUniformsAndProgramMutex); for (auto uniform : _uniforms) { @@ -1467,7 +1467,7 @@ void MWShadowTechnique::createShaders() unsigned int _baseTextureUnit = 0; - OpenThreads::ScopedLock lock(_accessUniformsAndProgramMutex); + std::lock_guard lock(_accessUniformsAndProgramMutex); _shadowCastingStateSet = new osg::StateSet; @@ -2980,7 +2980,7 @@ osg::StateSet* MWShadowTechnique::selectStateSetForRenderingShadow(ViewDependent osg::ref_ptr stateset = vdd.getStateSet(); - OpenThreads::ScopedLock lock(_accessUniformsAndProgramMutex); + std::lock_guard lock(_accessUniformsAndProgramMutex); vdd.getStateSet()->clear(); @@ -3057,7 +3057,7 @@ void MWShadowTechnique::resizeGLObjectBuffers(unsigned int /*maxSize*/) void MWShadowTechnique::releaseGLObjects(osg::State* state) const { - OpenThreads::ScopedLock lock(_viewDependentDataMapMutex); + std::lock_guard lock(_viewDependentDataMapMutex); for(ViewDependentDataMap::const_iterator itr = _viewDependentDataMap.begin(); itr != _viewDependentDataMap.end(); ++itr) diff --git a/components/sceneutil/mwshadowtechnique.hpp b/components/sceneutil/mwshadowtechnique.hpp index 85e548b4b..77d0bd2b2 100644 --- a/components/sceneutil/mwshadowtechnique.hpp +++ b/components/sceneutil/mwshadowtechnique.hpp @@ -19,6 +19,8 @@ #ifndef COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H #define COMPONENTS_SCENEUTIL_MWSHADOWTECHNIQUE_H 1 +#include + #include #include #include @@ -234,7 +236,7 @@ namespace SceneUtil { virtual ~MWShadowTechnique(); typedef std::map< osgUtil::CullVisitor*, osg::ref_ptr > ViewDependentDataMap; - mutable OpenThreads::Mutex _viewDependentDataMapMutex; + mutable std::mutex _viewDependentDataMapMutex; ViewDependentDataMap _viewDependentDataMap; osg::ref_ptr _shadowRecievingPlaceholderStateSet; @@ -245,7 +247,7 @@ namespace SceneUtil { osg::ref_ptr _fallbackShadowMapTexture; typedef std::vector< osg::ref_ptr > Uniforms; - mutable OpenThreads::Mutex _accessUniformsAndProgramMutex; + mutable std::mutex _accessUniformsAndProgramMutex; Uniforms _uniforms; osg::ref_ptr _program; diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 4495e5b2e..490c9d438 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -273,7 +273,7 @@ namespace Shader osg::ref_ptr ShaderManager::getShader(const std::string &templateName, const ShaderManager::DefineMap &defines, osg::Shader::Type shaderType) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); // read the template if we haven't already TemplateMap::iterator templateIt = mShaderTemplates.find(templateName); @@ -323,7 +323,7 @@ namespace Shader osg::ref_ptr ShaderManager::getProgram(osg::ref_ptr vertexShader, osg::ref_ptr fragmentShader) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); ProgramMap::iterator found = mPrograms.find(std::make_pair(vertexShader, fragmentShader)); if (found == mPrograms.end()) { @@ -362,7 +362,7 @@ namespace Shader void ShaderManager::releaseGLObjects(osg::State *state) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); for (auto shader : mShaders) { if (shader.second != nullptr) diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index 8c5d6dfac..ed5bbc907 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -10,8 +11,6 @@ #include -#include - namespace Shader { @@ -63,7 +62,7 @@ namespace Shader typedef std::map, osg::ref_ptr >, osg::ref_ptr > ProgramMap; ProgramMap mPrograms; - OpenThreads::Mutex mMutex; + std::mutex mMutex; const osg::ref_ptr mShadowMapAlphaTestEnableUniform = new osg::Uniform(); const osg::ref_ptr mShadowMapAlphaTestDisableUniform = new osg::Uniform(); diff --git a/components/terrain/buffercache.cpp b/components/terrain/buffercache.cpp index 1734686de..5871b96bc 100644 --- a/components/terrain/buffercache.cpp +++ b/components/terrain/buffercache.cpp @@ -2,8 +2,6 @@ #include -#include - #include #include "defs.hpp" @@ -180,7 +178,7 @@ namespace Terrain osg::ref_ptr BufferCache::getUVBuffer(unsigned int numVerts) { - OpenThreads::ScopedLock lock(mUvBufferMutex); + std::lock_guard lock(mUvBufferMutex); if (mUvBufferMap.find(numVerts) != mUvBufferMap.end()) { return mUvBufferMap[numVerts]; @@ -210,7 +208,7 @@ namespace Terrain osg::ref_ptr BufferCache::getIndexBuffer(unsigned int numVerts, unsigned int flags) { std::pair id = std::make_pair(numVerts, flags); - OpenThreads::ScopedLock lock(mIndexBufferMutex); + std::lock_guard lock(mIndexBufferMutex); if (mIndexBufferMap.find(id) != mIndexBufferMap.end()) { @@ -234,11 +232,11 @@ namespace Terrain void BufferCache::clearCache() { { - OpenThreads::ScopedLock lock(mIndexBufferMutex); + std::lock_guard lock(mIndexBufferMutex); mIndexBufferMap.clear(); } { - OpenThreads::ScopedLock lock(mUvBufferMutex); + std::lock_guard lock(mUvBufferMutex); mUvBufferMap.clear(); } } @@ -246,12 +244,12 @@ namespace Terrain void BufferCache::releaseGLObjects(osg::State *state) { { - OpenThreads::ScopedLock lock(mIndexBufferMutex); + std::lock_guard lock(mIndexBufferMutex); for (auto indexbuffer : mIndexBufferMap) indexbuffer.second->releaseGLObjects(state); } { - OpenThreads::ScopedLock lock(mUvBufferMutex); + std::lock_guard lock(mUvBufferMutex); for (auto uvbuffer : mUvBufferMap) uvbuffer.second->releaseGLObjects(state); } diff --git a/components/terrain/buffercache.hpp b/components/terrain/buffercache.hpp index 37563d2c6..929dbad6f 100644 --- a/components/terrain/buffercache.hpp +++ b/components/terrain/buffercache.hpp @@ -6,6 +6,7 @@ #include #include +#include namespace Terrain { @@ -30,10 +31,10 @@ namespace Terrain // Index buffers are shared across terrain batches where possible. There is one index buffer for each // combination of LOD deltas and index buffer LOD we may need. std::map, osg::ref_ptr > mIndexBufferMap; - OpenThreads::Mutex mIndexBufferMutex; + std::mutex mIndexBufferMutex; std::map > mUvBufferMap; - OpenThreads::Mutex mUvBufferMutex; + std::mutex mUvBufferMutex; }; } diff --git a/components/terrain/compositemaprenderer.cpp b/components/terrain/compositemaprenderer.cpp index ee4a66fcd..2a3fa47da 100644 --- a/components/terrain/compositemaprenderer.cpp +++ b/components/terrain/compositemaprenderer.cpp @@ -1,7 +1,5 @@ #include "compositemaprenderer.hpp" -#include - #include #include #include @@ -50,7 +48,7 @@ void CompositeMapRenderer::drawImplementation(osg::RenderInfo &renderInfo) const if (mWorkQueue) mUnrefQueue->flush(mWorkQueue.get()); - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); if (mImmediateCompileSet.empty() && mCompileSet.empty()) return; @@ -177,7 +175,7 @@ void CompositeMapRenderer::setTargetFrameRate(float framerate) void CompositeMapRenderer::addCompositeMap(CompositeMap* compositeMap, bool immediate) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); if (immediate) mImmediateCompileSet.insert(compositeMap); else @@ -186,7 +184,7 @@ void CompositeMapRenderer::addCompositeMap(CompositeMap* compositeMap, bool imme void CompositeMapRenderer::setImmediate(CompositeMap* compositeMap) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); CompileSet::iterator found = mCompileSet.find(compositeMap); if (found == mCompileSet.end()) return; @@ -199,7 +197,7 @@ void CompositeMapRenderer::setImmediate(CompositeMap* compositeMap) unsigned int CompositeMapRenderer::getCompileSetSize() const { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); return mCompileSet.size(); } diff --git a/components/terrain/compositemaprenderer.hpp b/components/terrain/compositemaprenderer.hpp index 201130e30..9d5719c23 100644 --- a/components/terrain/compositemaprenderer.hpp +++ b/components/terrain/compositemaprenderer.hpp @@ -3,9 +3,8 @@ #include -#include - #include +#include namespace osg { @@ -76,7 +75,7 @@ namespace Terrain mutable CompileSet mCompileSet; mutable CompileSet mImmediateCompileSet; - mutable OpenThreads::Mutex mMutex; + mutable std::mutex mMutex; osg::ref_ptr mFBO; }; diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index e09433061..ca1dcb08c 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -453,7 +453,7 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv) void QuadTreeWorld::ensureQuadTreeBuilt() { - OpenThreads::ScopedLock lock(mQuadTreeMutex); + std::lock_guard lock(mQuadTreeMutex); if (mQuadTreeBuilt) return; diff --git a/components/terrain/quadtreeworld.hpp b/components/terrain/quadtreeworld.hpp index 47cf46138..4c05efe64 100644 --- a/components/terrain/quadtreeworld.hpp +++ b/components/terrain/quadtreeworld.hpp @@ -4,7 +4,7 @@ #include "world.hpp" #include "terraingrid.hpp" -#include +#include namespace osg { @@ -61,7 +61,7 @@ namespace Terrain std::vector mChunkManagers; - OpenThreads::Mutex mQuadTreeMutex; + std::mutex mQuadTreeMutex; bool mQuadTreeBuilt; float mLodFactor; int mVertexLodMod; diff --git a/extern/osg-ffmpeg-videoplayer/videostate.cpp b/extern/osg-ffmpeg-videoplayer/videostate.cpp index 014c5c4f5..c176fe0f2 100644 --- a/extern/osg-ffmpeg-videoplayer/videostate.cpp +++ b/extern/osg-ffmpeg-videoplayer/videostate.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include @@ -95,14 +97,14 @@ void PacketQueue::put(AVPacket *pkt) this->last_pkt = pkt1; this->nb_packets++; this->size += pkt1->pkt.size; - this->cond.signal(); + this->cond.notify_one(); this->mutex.unlock(); } int PacketQueue::get(AVPacket *pkt, VideoState *is) { - OpenThreads::ScopedLock lock(this->mutex); + std::unique_lock lock(this->mutex); while(!is->mQuit) { AVPacketList *pkt1 = this->first_pkt; @@ -122,7 +124,7 @@ int PacketQueue::get(AVPacket *pkt, VideoState *is) if(this->flushing) break; - this->cond.wait(&this->mutex); + this->cond.wait(lock); } return -1; @@ -131,7 +133,7 @@ int PacketQueue::get(AVPacket *pkt, VideoState *is) void PacketQueue::flush() { this->flushing = true; - this->cond.signal(); + this->cond.notify_one(); } void PacketQueue::clear() @@ -226,7 +228,7 @@ void VideoState::video_display(VideoPicture *vp) void VideoState::video_refresh() { - OpenThreads::ScopedLock lock(this->pictq_mutex); + std::lock_guard lock(this->pictq_mutex); if(this->pictq_size == 0) return; @@ -238,7 +240,7 @@ void VideoState::video_refresh() this->pictq_rindex = (pictq_rindex+1) % VIDEO_PICTURE_ARRAY_SIZE; this->frame_last_pts = vp->pts; this->pictq_size--; - this->pictq_cond.signal(); + this->pictq_cond.notify_one(); } else { @@ -268,7 +270,7 @@ void VideoState::video_refresh() // update queue for next picture this->pictq_size--; this->pictq_rindex = (this->pictq_rindex+1) % VIDEO_PICTURE_ARRAY_SIZE; - this->pictq_cond.signal(); + this->pictq_cond.notify_one(); } } @@ -279,9 +281,9 @@ int VideoState::queue_picture(AVFrame *pFrame, double pts) /* wait until we have a new pic */ { - OpenThreads::ScopedLock lock(this->pictq_mutex); + std::unique_lock lock(this->pictq_mutex); while(this->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !this->mQuit) - this->pictq_cond.wait(&this->pictq_mutex, 1); + this->pictq_cond.wait_for(lock, std::chrono::milliseconds(1)); } if(this->mQuit) return -1; @@ -340,16 +342,21 @@ double VideoState::synchronize_video(AVFrame *src_frame, double pts) return pts; } -class VideoThread : public OpenThreads::Thread +class VideoThread { public: VideoThread(VideoState* self) : mVideoState(self) + , mThread([this] { run(); }) { - start(); } - virtual void run() + ~VideoThread() + { + mThread.join(); + } + + void run() { VideoState* self = mVideoState; AVPacket pkt1, *packet = &pkt1; @@ -408,18 +415,24 @@ public: private: VideoState* mVideoState; + std::thread mThread; }; -class ParseThread : public OpenThreads::Thread +class ParseThread { public: ParseThread(VideoState* self) : mVideoState(self) + , mThread([this] { run(); }) + { + } + + ~ParseThread() { - start(); + mThread.join(); } - virtual void run() + void run() { VideoState* self = mVideoState; @@ -503,7 +516,7 @@ public: if((self->audio_st && self->audioq.size > MAX_AUDIOQ_SIZE) || (self->video_st && self->videoq.size > MAX_VIDEOQ_SIZE)) { - OpenThreads::Thread::microSleep(10 * 1000); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); continue; } @@ -534,6 +547,7 @@ public: private: VideoState* mVideoState; + std::thread mThread; }; @@ -712,12 +726,10 @@ void VideoState::deinit() if (this->parse_thread.get()) { - this->parse_thread->join(); this->parse_thread.reset(); } if (this->video_thread.get()) { - this->video_thread->join(); this->video_thread.reset(); } @@ -816,7 +828,7 @@ ExternalClock::ExternalClock() void ExternalClock::setPaused(bool paused) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); if (mPaused == paused) return; if (paused) @@ -830,7 +842,7 @@ void ExternalClock::setPaused(bool paused) uint64_t ExternalClock::get() { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); if (mPaused) return mPausedAt; else @@ -839,7 +851,7 @@ uint64_t ExternalClock::get() void ExternalClock::set(uint64_t time) { - OpenThreads::ScopedLock lock(mMutex); + std::lock_guard lock(mMutex); mTimeBase = av_gettime() - time; mPausedAt = time; } diff --git a/extern/osg-ffmpeg-videoplayer/videostate.hpp b/extern/osg-ffmpeg-videoplayer/videostate.hpp index 54519f428..984050cd6 100644 --- a/extern/osg-ffmpeg-videoplayer/videostate.hpp +++ b/extern/osg-ffmpeg-videoplayer/videostate.hpp @@ -6,10 +6,8 @@ #include #include #include - -#include -#include -#include +#include +#include #include namespace osg @@ -64,7 +62,7 @@ struct ExternalClock uint64_t mPausedAt; bool mPaused; - OpenThreads::Mutex mMutex; + std::mutex mMutex; void setPaused(bool paused); uint64_t get(); @@ -83,8 +81,8 @@ struct PacketQueue { std::atomic nb_packets; std::atomic size; - OpenThreads::Mutex mutex; - OpenThreads::Condition cond; + std::mutex mutex; + std::condition_variable cond; void put(AVPacket *pkt); int get(AVPacket *pkt, VideoState *is); @@ -164,8 +162,8 @@ struct VideoState { VideoPicture pictq[VIDEO_PICTURE_ARRAY_SIZE]; AVFrame* rgbaFrame; // used as buffer for the frame converted from its native format to RGBA int pictq_size, pictq_rindex, pictq_windex; - OpenThreads::Mutex pictq_mutex; - OpenThreads::Condition pictq_cond; + std::mutex pictq_mutex; + std::condition_variable pictq_cond; std::unique_ptr parse_thread; std::unique_ptr video_thread; From edd6df1857ab373bd0d369efa9edf6252ca5c7ee Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 02:05:17 +0100 Subject: [PATCH 005/107] Try enabling Windows Shared Runners again. Hopefully this will work now https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/merge_requests/99 is merged. --- .gitlab-ci.yml | 94 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1f8bc6417..c1d6b5753 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -41,26 +41,98 @@ MacOS: paths: - build/OpenMW-*.dmg -Windows: +Windows_Ninja_RelWithDebInfo: tags: - windows + before_script: + - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco install git --force --params "/GitAndUnixToolsOnPath" -y + - choco install 7zip -y + - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y + - choco install vswhere -y + - choco install ninja -y + - choco install python -y + - refreshenv + stage: build + allow_failure: true + script: + - $time = (Get-Date -Format "HH:mm:ss") + - $config = "RelWithDebInfo" + - echo ${time} + - echo "started by ${GITLAB_USER_NAME}" + - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N + - cd MSVC2019_64_Ninja + - .\ActivateMSVC.ps1 + - cmake --build . --config $config + - cd $config + - | + if (Get-ChildItem -Recurse *.pdb) { + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + Get-ChildItem -Recurse *.pdb | Remove-Item + } + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}.zip '*' + cache: + paths: + - deps + - MSVC2019_64_Ninja/deps + artifacts: + when: always + paths: + - "*.zip" - "*.log" + - MSVC2019_64_Ninja/* + - MSVC2019_64_Ninja/*.log + - MSVC2019_64_Ninja/*/*.log + - MSVC2019_64_Ninja/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log + + +Windows_MSBuild_RelWithDebInfo: + tags: + - windows + before_script: + - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco install git --force --params "/GitAndUnixToolsOnPath" -y + - choco install 7zip -y + - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y + - choco install vswhere -y + - choco install python -y + - refreshenv stage: build allow_failure: true script: - - Set-Variable -Name "time" -Value (date -Format "%H:%m") + - $time = (Get-Date -Format "HH:mm:ss") + - $config = "RelWithDebInfo" - echo ${time} - echo "started by ${GITLAB_USER_NAME}" -# TODO: to anyone wanting to do further work here, we need to figure out how to get the below working -# TODO: on gitlab's new shared windows runners. They currently don't have bash or anything else installed -# TODO: it is currently just a bare windows 10 with powershell. -# - env # turn on for debugging -# - sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V -# - SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" -# - call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% -# - 7z a OpenMW_MSVC2017_64_%CI_BUILD_REF_NAME%_%CI_BUILD_ID%.zip %CI_PROJECT_DIR%\MSVC2017_64\Release\ + - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V + - cd MSVC2019_64 + - .\ActivateMSVC.ps1 + - cmake --build . --config $config + - cd $config + - | + if (Get-ChildItem -Recurse *.pdb) { + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + Get-ChildItem -Recurse *.pdb | Remove-Item + } + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}.zip '*' cache: paths: - deps + - MSVC2019_64/deps artifacts: + when: always paths: - - "*.zip" + - "*.zip" - "*.log" + - MSVC2019_64/* + - MSVC2019_64/*.log + - MSVC2019_64/*/*.log + - MSVC2019_64/*/*/*.log + - MSVC2019_64/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*/*/*.log \ No newline at end of file From 82882beee68ef4098b94e684e2a510891d474733 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 02:08:25 +0100 Subject: [PATCH 006/107] Fix missing line breaks --- .gitlab-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c1d6b5753..086107db2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -78,7 +78,8 @@ Windows_Ninja_RelWithDebInfo: artifacts: when: always paths: - - "*.zip" - "*.log" + - "*.zip" + - "*.log" - MSVC2019_64_Ninja/* - MSVC2019_64_Ninja/*.log - MSVC2019_64_Ninja/*/*.log @@ -126,7 +127,8 @@ Windows_MSBuild_RelWithDebInfo: artifacts: when: always paths: - - "*.zip" - "*.log" + - "*.zip" + - "*.log" - MSVC2019_64/* - MSVC2019_64/*.log - MSVC2019_64/*/*.log From decf59d20e3f277ac0fbd558abf9005c52ac7196 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 02:30:51 +0100 Subject: [PATCH 007/107] Don't try and activate MSVC when using MSBuild --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 086107db2..ac84ed953 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -111,7 +111,6 @@ Windows_MSBuild_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - .\ActivateMSVC.ps1 - cmake --build . --config $config - cd $config - | From c7cf163667510f1d9d0ee4decf6f549b9d304b86 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 03:23:12 +0100 Subject: [PATCH 008/107] Don't keep whole build directory. --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ac84ed953..774a163fb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -80,7 +80,6 @@ Windows_Ninja_RelWithDebInfo: paths: - "*.zip" - "*.log" - - MSVC2019_64_Ninja/* - MSVC2019_64_Ninja/*.log - MSVC2019_64_Ninja/*/*.log - MSVC2019_64_Ninja/*/*/*.log @@ -128,7 +127,6 @@ Windows_MSBuild_RelWithDebInfo: paths: - "*.zip" - "*.log" - - MSVC2019_64/* - MSVC2019_64/*.log - MSVC2019_64/*/*.log - MSVC2019_64/*/*/*.log From d6ab2f965955eb88f988b3d3b301664c979b8c84 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 03:23:59 +0100 Subject: [PATCH 009/107] Disallow failure --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 774a163fb..61e389f19 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,7 +54,6 @@ Windows_Ninja_RelWithDebInfo: - choco install python -y - refreshenv stage: build - allow_failure: true script: - $time = (Get-Date -Format "HH:mm:ss") - $config = "RelWithDebInfo" @@ -102,7 +101,6 @@ Windows_MSBuild_RelWithDebInfo: - choco install python -y - refreshenv stage: build - allow_failure: true script: - $time = (Get-Date -Format "HH:mm:ss") - $config = "RelWithDebInfo" From 53be725df264dea2d44bae6f3c80d17e865abe4c Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 03:26:42 +0100 Subject: [PATCH 010/107] Make build succeed so cache is kept --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 61e389f19..d252236ac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -60,6 +60,7 @@ Windows_Ninja_RelWithDebInfo: - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N + - exit 0 - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - cmake --build . --config $config @@ -107,6 +108,7 @@ Windows_MSBuild_RelWithDebInfo: - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V + - exit 0 - cd MSVC2019_64 - cmake --build . --config $config - cd $config From bf69f90f8001e0951332d3390b8e71f2fdc5584f Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 27 Jun 2020 03:28:42 +0100 Subject: [PATCH 011/107] Revert "Make build succeed so cache is kept" This reverts commit 53be725df264dea2d44bae6f3c80d17e865abe4c. It was only needed for CI reasons. --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d252236ac..61e389f19 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -60,7 +60,6 @@ Windows_Ninja_RelWithDebInfo: - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - - exit 0 - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - cmake --build . --config $config @@ -108,7 +107,6 @@ Windows_MSBuild_RelWithDebInfo: - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - - exit 0 - cd MSVC2019_64 - cmake --build . --config $config - cd $config From 0d7b9c51fd9403b2c76f88b5879920d7dd0be7bc Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 28 Jun 2020 03:51:41 +0100 Subject: [PATCH 012/107] Log misparsed stuff as it caused an unexpected CI failure --- CI/activate_msvc.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CI/activate_msvc.sh b/CI/activate_msvc.sh index 0764cd02f..1641f6b3e 100644 --- a/CI/activate_msvc.sh +++ b/CI/activate_msvc.sh @@ -39,6 +39,10 @@ originalIFS="$IFS" IFS=$'\n\r' for pair in $(cmd //c "set"); do IFS='=' read -r -a separatedPair <<< "${pair}" + if [ ${#separatedPair[@]} -ne 2 ]; then + echo "Parsed '$pair' as ${#separatedPair[@]} parts, expected 2." + continue + fi originalCmdEnv["${separatedPair[0]}"]="${separatedPair[1]}" done @@ -49,6 +53,10 @@ declare -A cmdEnvChanges for pair in $cmdEnv; do if [ -n "$pair" ]; then IFS='=' read -r -a separatedPair <<< "${pair}" + if [ ${#separatedPair[@]} -ne 2 ]; then + echo "Parsed '$pair' as ${#separatedPair[@]} parts, expected 2." + continue + fi key="${separatedPair[0]}" value="${separatedPair[1]}" if ! [ ${originalCmdEnv[$key]+_} ] || [ "${originalCmdEnv[$key]}" != "$value" ]; then From 230e06dec73eb1bac45e19327c976b9e540d6a2f Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 28 Jun 2020 13:03:47 +0400 Subject: [PATCH 013/107] Make joysticks dead zone configurable (bug #5502) --- CHANGELOG.md | 1 + apps/openmw/mwinput/bindingsmanager.cpp | 5 +++++ apps/openmw/mwinput/bindingsmanager.hpp | 2 ++ apps/openmw/mwinput/controllermanager.cpp | 4 ++++ docs/source/reference/modding/settings/input.rst | 12 ++++++++++++ extern/oics/ICSInputControlSystem.cpp | 1 + extern/oics/ICSInputControlSystem.h | 4 ++++ extern/oics/ICSInputControlSystem_joystick.cpp | 11 +++++------ files/settings-default.cfg | 3 +++ 9 files changed, 37 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce2966cbf..ab1b61a7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ Bug #5485: Intimidate doesn't increase disposition on marginal wins Bug #5490: Hits to carried left slot aren't redistributed if there's no shield equipped Bug #5499: Faction advance is available when requirements not met + Bug #5502: Dead zone for analogue stick movement is too small Feature #390: 3rd person look "over the shoulder" Feature #2386: Distant Statics in the form of Object Paging Feature #5297: Add a search function to the "Datafiles" tab of the OpenMW launcher diff --git a/apps/openmw/mwinput/bindingsmanager.cpp b/apps/openmw/mwinput/bindingsmanager.cpp index 11f714205..9d77ec99c 100644 --- a/apps/openmw/mwinput/bindingsmanager.cpp +++ b/apps/openmw/mwinput/bindingsmanager.cpp @@ -226,6 +226,11 @@ namespace MWInput } } + void BindingsManager::setJoystickDeadZone(float deadZone) + { + mInputBinder->setJoystickDeadZone(deadZone); + } + float BindingsManager::getActionValue (int id) const { return mInputBinder->getChannel(id)->getValue(); diff --git a/apps/openmw/mwinput/bindingsmanager.hpp b/apps/openmw/mwinput/bindingsmanager.hpp index 35b26c877..7a44a1a33 100644 --- a/apps/openmw/mwinput/bindingsmanager.hpp +++ b/apps/openmw/mwinput/bindingsmanager.hpp @@ -36,6 +36,8 @@ namespace MWInput void setPlayerControlsEnabled(bool enabled); + void setJoystickDeadZone(float deadZone); + bool isLeftOrRightButton(int action, bool joystick) const; bool actionIsActive(int id) const; diff --git a/apps/openmw/mwinput/controllermanager.cpp b/apps/openmw/mwinput/controllermanager.cpp index 3b1f587ce..11e1c6350 100644 --- a/apps/openmw/mwinput/controllermanager.cpp +++ b/apps/openmw/mwinput/controllermanager.cpp @@ -72,6 +72,10 @@ namespace MWInput float uiScale = Settings::Manager::getFloat("scaling factor", "GUI"); if (uiScale != 0.f) mInvUiScalingFactor = 1.f / uiScale; + + float deadZoneRadius = Settings::Manager::getFloat("joystick dead zone", "Input"); + deadZoneRadius = std::min(std::max(deadZoneRadius, 0.0f), 0.5f); + mBindingsManager->setJoystickDeadZone(deadZoneRadius); } void ControllerManager::processChangedSettings(const Settings::CategorySettingVector& changed) diff --git a/docs/source/reference/modding/settings/input.rst b/docs/source/reference/modding/settings/input.rst index 090b27958..8a95686cf 100644 --- a/docs/source/reference/modding/settings/input.rst +++ b/docs/source/reference/modding/settings/input.rst @@ -135,6 +135,18 @@ camera sensitivity setting. This setting can only be configured by editing the settings configuration file. +joystick dead zone +------------------ + +:Type: floating point +:Range: 0.0 to 0.5 +:Default: 0.1 + +This setting controls the radius of dead zone (where an input is discarded) for joystick axes. +Note that third-party software can provide its own dead zones. In this case OpenmW-specific setting dead zone can be disabled (0.0). + +This setting can only be configured by editing the settings configuration file. + enable gyroscope ---------------- diff --git a/extern/oics/ICSInputControlSystem.cpp b/extern/oics/ICSInputControlSystem.cpp index ccd09a04e..c03c039a4 100644 --- a/extern/oics/ICSInputControlSystem.cpp +++ b/extern/oics/ICSInputControlSystem.cpp @@ -34,6 +34,7 @@ namespace ICS , DetectingBindingListener* detectingBindingListener , InputControlSystemLog* log, size_t channelCount) : mFileName(file) + , mDeadZone(0.1f) , mLog(log) , mDetectingBindingListener(detectingBindingListener) , mDetectingBindingControl(NULL) diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h index 43e659d0a..c49224dc2 100644 --- a/extern/oics/ICSInputControlSystem.h +++ b/extern/oics/ICSInputControlSystem.h @@ -79,6 +79,8 @@ namespace ICS void setDetectingBindingListener(DetectingBindingListener* detectingBindingListener){ mDetectingBindingListener = detectingBindingListener; }; DetectingBindingListener* getDetectingBindingListener(){ return mDetectingBindingListener; }; + void setJoystickDeadZone(float deadZone){ mDeadZone = deadZone; }; + // in seconds void update(float timeSinceLastFrame); @@ -180,6 +182,8 @@ namespace ICS std::string mFileName; + float mDeadZone; + typedef std::map ControlsKeyBinderMapType; // typedef std::map ControlsAxisBinderMapType; // typedef std::map ControlsButtonBinderMapType; // diff --git a/extern/oics/ICSInputControlSystem_joystick.cpp b/extern/oics/ICSInputControlSystem_joystick.cpp index ed6e2f664..38199436b 100644 --- a/extern/oics/ICSInputControlSystem_joystick.cpp +++ b/extern/oics/ICSInputControlSystem_joystick.cpp @@ -27,8 +27,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "ICSInputControlSystem.h" #define SDL_JOY_AXIS_MIN -32768 -#define SDL_JOY_AXIS_MAX 32767 -#define DEADZONE 0.1f +#define SDL_JOY_AXIS_MAX 32767 namespace ICS { @@ -263,13 +262,13 @@ namespace ICS float axisRange = SDL_JOY_AXIS_MAX - SDL_JOY_AXIS_MIN; float valDisplaced = (float)(evt.value - SDL_JOY_AXIS_MIN); - float percent = valDisplaced / axisRange * (1+DEADZONE*2) - DEADZONE; //Assures all values, 0 through 1, are seen - if(percent > .5-DEADZONE && percent < .5+DEADZONE) //close enough to center + float percent = valDisplaced / axisRange * (1+mDeadZone*2) - mDeadZone; //Assures all values, 0 through 1, are seen + if(percent > .5-mDeadZone && percent < .5+mDeadZone) //close enough to center percent = .5; else if(percent > .5) - percent -= DEADZONE; + percent -= mDeadZone; else - percent += DEADZONE; + percent += mDeadZone; if(joystickBinderItem.direction == Control::INCREASE) { diff --git a/files/settings-default.cfg b/files/settings-default.cfg index c48c8baf4..72accf9c9 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -421,6 +421,9 @@ enable controller = true # Emulated gamepad cursor sensitivity. gamepad cursor speed = 1.0 +# Set dead zone for joysticks (gamepad or on-screen ones) +joystick dead zone = 0.1 + # Enable gyroscope support. enable gyroscope = false From 0ff5e9bfb9970872a9b61ee67db9c1ab321a347e Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 22:16:45 +0200 Subject: [PATCH 014/107] Lookup sound when need to stop Instead of loading. --- apps/openmw/mwsound/soundmanagerimp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 162c176e6..65214e5ff 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -772,7 +772,7 @@ namespace MWSound if(!mOutput->isInitialized()) return; - Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); + Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); if (!sfx) return; stopSound(sfx, MWWorld::ConstPtr()); @@ -783,7 +783,7 @@ namespace MWSound if(!mOutput->isInitialized()) return; - Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); + Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); if (!sfx) return; stopSound(sfx, ptr); From 02587ed1e9eea69871390b84f12b958ff5211f8b Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 22:55:21 +0200 Subject: [PATCH 015/107] Remove unused SoundManager::stopSound overload --- apps/openmw/mwbase/soundmanager.hpp | 3 --- apps/openmw/mwsound/soundmanagerimp.cpp | 11 ----------- apps/openmw/mwsound/soundmanagerimp.hpp | 3 --- 3 files changed, 17 deletions(-) diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index cc933d4bb..81b54c566 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -163,9 +163,6 @@ namespace MWBase virtual void stopSound(const MWWorld::CellStore *cell) = 0; ///< Stop all sounds for the given cell. - virtual void stopSound(const std::string& soundId) = 0; - ///< Stop a non-3d looping sound - virtual void fadeOutSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, float duration) = 0; ///< Fade out given sound (that is already playing) of given object ///< @param reference Reference to object, whose sound is faded out diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 65214e5ff..64e8f0ddb 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -767,17 +767,6 @@ namespace MWSound } } - void SoundManager::stopSound(const std::string& soundId) - { - if(!mOutput->isInitialized()) - return; - - Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); - if (!sfx) return; - - stopSound(sfx, MWWorld::ConstPtr()); - } - void SoundManager::stopSound3D(const MWWorld::ConstPtr &ptr, const std::string& soundId) { if(!mOutput->isInitialized()) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 55588d06f..56c993d3c 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -233,9 +233,6 @@ namespace MWSound virtual void stopSound(const MWWorld::CellStore *cell); ///< Stop all sounds for the given cell. - virtual void stopSound(const std::string& soundId); - ///< Stop a non-3d looping sound - virtual void fadeOutSound3D(const MWWorld::ConstPtr &reference, const std::string& soundId, float duration); ///< Fade out given sound (that is already playing) of given object ///< @param reference Reference to object, whose sound is faded out From ef6fe8d52a32ad33e0b4387b1171688cc6c0dbcd Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 30 Jun 2020 08:59:21 +0400 Subject: [PATCH 016/107] Fix crash in the stateset updater (regression #5478) --- components/sceneutil/statesetupdater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/sceneutil/statesetupdater.cpp b/components/sceneutil/statesetupdater.cpp index 08418f331..9fb9ba496 100644 --- a/components/sceneutil/statesetupdater.cpp +++ b/components/sceneutil/statesetupdater.cpp @@ -22,7 +22,7 @@ namespace SceneUtil } } - osg::StateSet* stateset = mStateSets[nv->getTraversalNumber()%2]; + osg::ref_ptr stateset = mStateSets[nv->getTraversalNumber()%2]; apply(stateset, nv); if (!isCullVisitor) From eb68df1a37456b5b371625f7d828faa58d5589a3 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 01:44:56 +0200 Subject: [PATCH 017/107] Add stats for all updates --- apps/openmw/engine.cpp | 292 +++++++++++++++++++++++++++++------------ apps/openmw/engine.hpp | 2 - 2 files changed, 208 insertions(+), 86 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 0792f4eaf..b1c5bcfde 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -67,6 +67,140 @@ namespace if (ret != 0) Log(Debug::Error) << "SDL error: " << SDL_GetError(); } + + struct UserStats + { + const std::string mLabel; + const std::string mBegin; + const std::string mEnd; + const std::string mTaken; + + UserStats(const std::string& label, const std::string& prefix) + : mLabel(label), + mBegin(prefix + "_time_begin"), + mEnd(prefix + "_time_end"), + mTaken(prefix + "_time_taken") + {} + }; + + enum class UserStatsType : std::size_t + { + Input, + Sound, + State, + Script, + Mechanics, + Physics, + World, + Gui, + + Number, + }; + + template + struct UserStatsValue + { + static const UserStats sValue; + }; + + template <> + const UserStats UserStatsValue::sValue {"Input", "input"}; + + template <> + const UserStats UserStatsValue::sValue {"Sound", "sound"}; + + template <> + const UserStats UserStatsValue::sValue {"State", "state"}; + + template <> + const UserStats UserStatsValue::sValue {"Script", "script"}; + + template <> + const UserStats UserStatsValue::sValue {"Mech", "mechanics"}; + + template <> + const UserStats UserStatsValue::sValue {"Phys", "physics"}; + + template <> + const UserStats UserStatsValue::sValue {"World", "world"}; + + template <> + const UserStats UserStatsValue::sValue {"Gui", "gui"}; + + template + struct ForEachUserStatsValue + { + template + static void apply(F&& f) + { + f(UserStatsValue::sValue); + using Next = ForEachUserStatsValue(static_cast(type) + 1)>; + Next::apply(std::forward(f)); + } + }; + + template <> + struct ForEachUserStatsValue + { + template + static void apply(F&&) {} + }; + + template + void forEachUserStatsValue(F&& f) + { + ForEachUserStatsValue(0)>::apply(std::forward(f)); + } + + template + class ScopedProfile + { + public: + ScopedProfile(osg::Timer_t frameStart, unsigned int frameNumber, const osg::Timer& timer, osg::Stats& stats) + : mScopeStart(timer.tick()), + mFrameStart(frameStart), + mFrameNumber(frameNumber), + mTimer(timer), + mStats(stats) + { + } + + ScopedProfile(const ScopedProfile&) = delete; + ScopedProfile& operator=(const ScopedProfile&) = delete; + + ~ScopedProfile() + { + const osg::Timer_t end = mTimer.tick(); + const UserStats& stats = UserStatsValue::sValue; + + mStats.setAttribute(mFrameNumber, stats.mBegin, mTimer.delta_s(mFrameStart, mScopeStart)); + mStats.setAttribute(mFrameNumber, stats.mTaken, mTimer.delta_s(mScopeStart, end)); + mStats.setAttribute(mFrameNumber, stats.mEnd, mTimer.delta_s(mFrameStart, end)); + } + + private: + const osg::Timer_t mScopeStart; + const osg::Timer_t mFrameStart; + const unsigned int mFrameNumber; + const osg::Timer& mTimer; + osg::Stats& mStats; + }; + + void initStatsHandler(Resource::Profiler& profiler) + { + const osg::Vec4f textColor(1.f, 1.f, 1.f, 1.f); + const osg::Vec4f barColor(1.f, 1.f, 1.f, 1.f); + const float multiplier = 1000; + const bool average = true; + const bool averageInInverseSpace = false; + const float maxValue = 10000; + + forEachUserStatsValue([&] (const UserStats& v) + { + profiler.addUserStatsLine(v.mLabel, textColor, barColor, v.mTaken, multiplier, + average, averageInInverseSpace, v.mBegin, v.mEnd, maxValue); + }); + } } void OMW::Engine::executeLocalScripts() @@ -87,119 +221,119 @@ bool OMW::Engine::frame(float frametime) { try { - mStartTick = mViewer->getStartTick(); + const osg::Timer_t frameStart = mViewer->getStartTick(); + const unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber(); + const osg::Timer* const timer = osg::Timer::instance(); + osg::Stats* const stats = mViewer->getViewerStats(); mEnvironment.setFrameDuration(frametime); // update input - mEnvironment.getInputManager()->update(frametime, false); + { + ScopedProfile profile(frameStart, frameNumber, *timer, *stats); + mEnvironment.getInputManager()->update(frametime, false); + } // When the window is minimized, pause the game. Currently this *has* to be here to work around a MyGUI bug. // If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2), // and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21) - if (!mEnvironment.getWindowManager()->isWindowVisible()) { - mEnvironment.getSoundManager()->pausePlayback(); - return false; - } - else - mEnvironment.getSoundManager()->resumePlayback(); + ScopedProfile profile(frameStart, frameNumber, *timer, *stats); + + if (!mEnvironment.getWindowManager()->isWindowVisible()) + { + mEnvironment.getSoundManager()->pausePlayback(); + return false; + } + else + mEnvironment.getSoundManager()->resumePlayback(); - // sound - if (mUseSound) - mEnvironment.getSoundManager()->update(frametime); + // sound + if (mUseSound) + mEnvironment.getSoundManager()->update(frametime); + } // Main menu opened? Then scripts are also paused. bool paused = mEnvironment.getWindowManager()->containsMode(MWGui::GM_MainMenu); // update game state - mEnvironment.getStateManager()->update (frametime); + { + ScopedProfile profile(frameStart, frameNumber, *timer, *stats); + mEnvironment.getStateManager()->update (frametime); + } bool guiActive = mEnvironment.getWindowManager()->isGuiMode(); - osg::Timer_t beforeScriptTick = osg::Timer::instance()->tick(); - if (mEnvironment.getStateManager()->getState()!= - MWBase::StateManager::State_NoGame) { - if (!paused) + ScopedProfile profile(frameStart, frameNumber, *timer, *stats); + + if (mEnvironment.getStateManager()->getState() != MWBase::StateManager::State_NoGame) { - if (mEnvironment.getWorld()->getScriptsEnabled()) + if (!paused) { - // local scripts - executeLocalScripts(); + if (mEnvironment.getWorld()->getScriptsEnabled()) + { + // local scripts + executeLocalScripts(); - // global scripts - mEnvironment.getScriptManager()->getGlobalScripts().run(); - } + // global scripts + mEnvironment.getScriptManager()->getGlobalScripts().run(); + } - mEnvironment.getWorld()->markCellAsUnchanged(); - } + mEnvironment.getWorld()->markCellAsUnchanged(); + } - if (!guiActive) - { - double hours = (frametime * mEnvironment.getWorld()->getTimeScaleFactor()) / 3600.0; - mEnvironment.getWorld()->advanceTime(hours, true); - mEnvironment.getWorld()->rechargeItems(frametime, true); + if (!guiActive) + { + double hours = (frametime * mEnvironment.getWorld()->getTimeScaleFactor()) / 3600.0; + mEnvironment.getWorld()->advanceTime(hours, true); + mEnvironment.getWorld()->rechargeItems(frametime, true); + } } } - osg::Timer_t afterScriptTick = osg::Timer::instance()->tick(); - // update actors - osg::Timer_t beforeMechanicsTick = osg::Timer::instance()->tick(); - if (mEnvironment.getStateManager()->getState()!= - MWBase::StateManager::State_NoGame) + // update mechanics { - mEnvironment.getMechanicsManager()->update(frametime, - guiActive); - } - osg::Timer_t afterMechanicsTick = osg::Timer::instance()->tick(); + ScopedProfile profile(frameStart, frameNumber, *timer, *stats); - if (mEnvironment.getStateManager()->getState()== - MWBase::StateManager::State_Running) - { - MWWorld::Ptr player = mEnvironment.getWorld()->getPlayerPtr(); - if(!guiActive && player.getClass().getCreatureStats(player).isDead()) - mEnvironment.getStateManager()->endGame(); + if (mEnvironment.getStateManager()->getState() != MWBase::StateManager::State_NoGame) + { + mEnvironment.getMechanicsManager()->update(frametime, guiActive); + } + + if (mEnvironment.getStateManager()->getState() == MWBase::StateManager::State_Running) + { + MWWorld::Ptr player = mEnvironment.getWorld()->getPlayerPtr(); + if(!guiActive && player.getClass().getCreatureStats(player).isDead()) + mEnvironment.getStateManager()->endGame(); + } } // update physics - osg::Timer_t beforePhysicsTick = osg::Timer::instance()->tick(); - if (mEnvironment.getStateManager()->getState()!= - MWBase::StateManager::State_NoGame) { - mEnvironment.getWorld()->updatePhysics(frametime, guiActive); + ScopedProfile profile(frameStart, frameNumber, *timer, *stats); + + if (mEnvironment.getStateManager()->getState() != MWBase::StateManager::State_NoGame) + { + mEnvironment.getWorld()->updatePhysics(frametime, guiActive); + } } - osg::Timer_t afterPhysicsTick = osg::Timer::instance()->tick(); // update world - osg::Timer_t beforeWorldTick = osg::Timer::instance()->tick(); - if (mEnvironment.getStateManager()->getState()!= - MWBase::StateManager::State_NoGame) { - mEnvironment.getWorld()->update(frametime, guiActive); + ScopedProfile profile(frameStart, frameNumber, *timer, *stats); + + if (mEnvironment.getStateManager()->getState() != MWBase::StateManager::State_NoGame) + { + mEnvironment.getWorld()->update(frametime, guiActive); + } } - osg::Timer_t afterWorldTick = osg::Timer::instance()->tick(); // update GUI - mEnvironment.getWindowManager()->update(frametime); - - unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber(); - osg::Stats* stats = mViewer->getViewerStats(); - stats->setAttribute(frameNumber, "script_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforeScriptTick)); - stats->setAttribute(frameNumber, "script_time_taken", osg::Timer::instance()->delta_s(beforeScriptTick, afterScriptTick)); - stats->setAttribute(frameNumber, "script_time_end", osg::Timer::instance()->delta_s(mStartTick, afterScriptTick)); - - stats->setAttribute(frameNumber, "mechanics_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforeMechanicsTick)); - stats->setAttribute(frameNumber, "mechanics_time_taken", osg::Timer::instance()->delta_s(beforeMechanicsTick, afterMechanicsTick)); - stats->setAttribute(frameNumber, "mechanics_time_end", osg::Timer::instance()->delta_s(mStartTick, afterMechanicsTick)); - - stats->setAttribute(frameNumber, "physics_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforePhysicsTick)); - stats->setAttribute(frameNumber, "physics_time_taken", osg::Timer::instance()->delta_s(beforePhysicsTick, afterPhysicsTick)); - stats->setAttribute(frameNumber, "physics_time_end", osg::Timer::instance()->delta_s(mStartTick, afterPhysicsTick)); - - stats->setAttribute(frameNumber, "world_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforeWorldTick)); - stats->setAttribute(frameNumber, "world_time_taken", osg::Timer::instance()->delta_s(beforeWorldTick, afterWorldTick)); - stats->setAttribute(frameNumber, "world_time_end", osg::Timer::instance()->delta_s(mStartTick, afterWorldTick)); + { + ScopedProfile profile(frameStart, frameNumber, *timer, *stats); + mEnvironment.getWindowManager()->update(frametime); + } if (stats->collectStats("resource")) { @@ -212,7 +346,6 @@ bool OMW::Engine::frame(float frametime) mEnvironment.reportStats(frameNumber, *stats); } - } catch (const std::exception& e) { @@ -255,8 +388,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) throw std::runtime_error("Could not initialize SDL! " + std::string(SDL_GetError())); } } - - mStartTick = osg::Timer::instance()->tick(); } OMW::Engine::~Engine() @@ -703,14 +834,7 @@ void OMW::Engine::go() // Setup profiler osg::ref_ptr statshandler = new Resource::Profiler; - statshandler->addUserStatsLine("Script", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), - "script_time_taken", 1000.0, true, false, "script_time_begin", "script_time_end", 10000); - statshandler->addUserStatsLine("Mech", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), - "mechanics_time_taken", 1000.0, true, false, "mechanics_time_begin", "mechanics_time_end", 10000); - statshandler->addUserStatsLine("Phys", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), - "physics_time_taken", 1000.0, true, false, "physics_time_begin", "physics_time_end", 10000); - statshandler->addUserStatsLine("World", osg::Vec4f(1.f, 1.f, 1.f, 1.f), osg::Vec4f(1.f, 1.f, 1.f, 1.f), - "world_time_taken", 1000.0, true, false, "world_time_begin", "world_time_end", 10000); + initStatsHandler(*statshandler); mViewer->addEventHandler(statshandler); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index a00cf474a..3dd1a69b2 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -111,8 +111,6 @@ namespace OMW bool mScriptBlacklistUse; bool mNewGame; - osg::Timer_t mStartTick; - // not implemented Engine (const Engine&); Engine& operator= (const Engine&); From 0594b7d1a0f42c438598deb27e4dd5633943f221 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 13:12:42 +0200 Subject: [PATCH 018/107] Put logic for the next region sound selection into a separate class --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwsound/regionsoundselector.cpp | 71 +++++++++++++++++++++ apps/openmw/mwsound/regionsoundselector.hpp | 29 +++++++++ apps/openmw/mwsound/soundmanagerimp.cpp | 45 +------------ apps/openmw/mwsound/soundmanagerimp.hpp | 4 ++ 5 files changed, 108 insertions(+), 43 deletions(-) create mode 100644 apps/openmw/mwsound/regionsoundselector.cpp create mode 100644 apps/openmw/mwsound/regionsoundselector.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a9f3d24e2..8631834c9 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -57,7 +57,7 @@ add_openmw_dir (mwscript add_openmw_dir (mwsound soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output - loudness movieaudiofactory alext efx efx-presets + loudness movieaudiofactory alext efx efx-presets regionsoundselector ) add_openmw_dir (mwworld diff --git a/apps/openmw/mwsound/regionsoundselector.cpp b/apps/openmw/mwsound/regionsoundselector.cpp new file mode 100644 index 000000000..ac5f66721 --- /dev/null +++ b/apps/openmw/mwsound/regionsoundselector.cpp @@ -0,0 +1,71 @@ +#include "regionsoundselector.hpp" + +#include + +#include +#include + +#include "../mwbase/world.hpp" +#include "../mwworld/esmstore.hpp" + +namespace MWSound +{ + namespace + { + int addChance(int result, const ESM::Region::SoundRef &v) + { + return result + v.mChance; + } + } + + boost::optional RegionSoundSelector::getNextRandom(float duration, const std::string& regionName, + const MWBase::World& world) + { + mTimePassed += duration; + + if (mTimePassed < mTimeToNextEnvSound) + return {}; + + const float a = Misc::Rng::rollClosedProbability(); + // NOTE: We should use the "Minimum Time Between Environmental Sounds" and + // "Maximum Time Between Environmental Sounds" fallback settings here. + mTimeToNextEnvSound = 5.0f * a + 15.0f * (1.0f - a); + mTimePassed = 0; + + if (mLastRegionName != regionName) + { + mLastRegionName = regionName; + mSumChance = 0; + } + + const ESM::Region* const region = world.getStore().get().search(mLastRegionName); + + if (region == nullptr) + return {}; + + if (mSumChance == 0) + { + mSumChance = std::accumulate(region->mSoundList.begin(), region->mSoundList.end(), 0, addChance); + if (mSumChance == 0) + return {}; + } + + const int r = Misc::Rng::rollDice(mSumChance); + int pos = 0; + + const auto isSelected = [&] (const ESM::Region::SoundRef& sound) + { + if (r - pos < sound.mChance) + return true; + pos += sound.mChance; + return false; + }; + + const auto it = std::find_if(region->mSoundList.begin(), region->mSoundList.end(), isSelected); + + if (it == region->mSoundList.end()) + return {}; + + return it->mSound; + } +} diff --git a/apps/openmw/mwsound/regionsoundselector.hpp b/apps/openmw/mwsound/regionsoundselector.hpp new file mode 100644 index 000000000..00a2d5ca8 --- /dev/null +++ b/apps/openmw/mwsound/regionsoundselector.hpp @@ -0,0 +1,29 @@ +#ifndef GAME_SOUND_REGIONSOUNDSELECTOR_H +#define GAME_SOUND_REGIONSOUNDSELECTOR_H + +#include + +#include + +namespace MWBase +{ + class World; +} + +namespace MWSound +{ + class RegionSoundSelector + { + public: + boost::optional getNextRandom(float duration, const std::string& regionName, + const MWBase::World& world); + + private: + float mTimeToNextEnvSound = 0.0f; + int mSumChance = 0; + std::string mLastRegionName; + float mTimePassed = 0.0; + }; +} + +#endif diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 162c176e6..36dbad1d5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -907,54 +907,15 @@ namespace MWSound void SoundManager::updateRegionSound(float duration) { - static float sTimeToNextEnvSound = 0.0f; - static int total = 0; - static std::string regionName = ""; - static float sTimePassed = 0.0; MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::ConstPtr player = world->getPlayerPtr(); const ESM::Cell *cell = player.getCell()->getCell(); - sTimePassed += duration; - if(!cell->isExterior() || sTimePassed < sTimeToNextEnvSound) + if (!cell->isExterior()) return; - float a = Misc::Rng::rollClosedProbability(); - // NOTE: We should use the "Minimum Time Between Environmental Sounds" and - // "Maximum Time Between Environmental Sounds" fallback settings here. - sTimeToNextEnvSound = 5.0f*a + 15.0f*(1.0f-a); - sTimePassed = 0; - - if(regionName != cell->mRegion) - { - regionName = cell->mRegion; - total = 0; - } - - const ESM::Region *regn = world->getStore().get().search(regionName); - if(regn == nullptr) - return; - - if(total == 0) - { - for(const ESM::Region::SoundRef &sndref : regn->mSoundList) - total += (int)sndref.mChance; - if(total == 0) - return; - } - - int r = Misc::Rng::rollDice(total); - int pos = 0; - - for(const ESM::Region::SoundRef &sndref : regn->mSoundList) - { - if(r - pos < sndref.mChance) - { - playSound(sndref.mSound, 1.0f, 1.0f); - break; - } - pos += sndref.mChance; - } + if (const auto next = mRegionSoundSelector.getNextRandom(duration, cell->mRegion, *world)) + playSound(*next, 1.0f, 1.0f); } void SoundManager::updateWaterSound(float /*duration*/) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 55588d06f..3974bf479 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -14,6 +14,8 @@ #include "../mwbase/soundmanager.hpp" +#include "regionsoundselector.hpp" + namespace VFS { class Manager; @@ -115,6 +117,8 @@ namespace MWSound std::string mNextMusic; bool mPlaybackPaused; + RegionSoundSelector mRegionSoundSelector; + Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound); Sound_Buffer *lookupSound(const std::string &soundId) const; From 5f0cc87a6701b01a41e5cf0892f896cf59006c94 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 1 Jul 2020 09:52:57 +0400 Subject: [PATCH 019/107] Do not discard remnants --- apps/openmw/mwinput/controllermanager.cpp | 5 ++--- apps/openmw/mwinput/mousemanager.cpp | 4 ++-- apps/openmw/mwinput/mousemanager.hpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwinput/controllermanager.cpp b/apps/openmw/mwinput/controllermanager.cpp index 11e1c6350..b0e769cc6 100644 --- a/apps/openmw/mwinput/controllermanager.cpp +++ b/apps/openmw/mwinput/controllermanager.cpp @@ -104,10 +104,9 @@ namespace MWInput // game mode does not move the position of the GUI cursor float xMove = xAxis * dt * 1500.0f * mInvUiScalingFactor * mGamepadCursorSpeed; float yMove = yAxis * dt * 1500.0f * mInvUiScalingFactor * mGamepadCursorSpeed; - if (xMove != 0 || yMove != 0 || zAxis != 0) + float mouseWheelMove = -zAxis * dt * 1500.0f; + if (xMove != 0 || yMove != 0 || mouseWheelMove != 0) { - int mouseWheelMove = static_cast(-zAxis * dt * 1500.0f); - mMouseManager->injectMouseMove(xMove, yMove, mouseWheelMove); mMouseManager->warpMouse(); MWBase::Environment::get().getWindowManager()->setCursorActive(true); diff --git a/apps/openmw/mwinput/mousemanager.cpp b/apps/openmw/mwinput/mousemanager.cpp index df38868e1..379830b1c 100644 --- a/apps/openmw/mwinput/mousemanager.cpp +++ b/apps/openmw/mwinput/mousemanager.cpp @@ -232,7 +232,7 @@ namespace MWInput return MyGUI::InputManager::getInstance().injectMousePress(static_cast(mGuiCursorX), static_cast(mGuiCursorY), sdlButtonToMyGUI(button)); } - void MouseManager::injectMouseMove(int xMove, int yMove, int mouseWheelMove) + void MouseManager::injectMouseMove(float xMove, float yMove, float mouseWheelMove) { mGuiCursorX += xMove; mGuiCursorY += yMove; @@ -242,7 +242,7 @@ namespace MWInput mGuiCursorX = std::max(0.f, std::min(mGuiCursorX, float(viewSize.width - 1))); mGuiCursorY = std::max(0.f, std::min(mGuiCursorY, float(viewSize.height - 1))); - MyGUI::InputManager::getInstance().injectMouseMove(static_cast(mGuiCursorX), static_cast(mGuiCursorY), mMouseWheel); + MyGUI::InputManager::getInstance().injectMouseMove(static_cast(mGuiCursorX), static_cast(mGuiCursorY), static_cast(mMouseWheel)); } void MouseManager::warpMouse() diff --git a/apps/openmw/mwinput/mousemanager.hpp b/apps/openmw/mwinput/mousemanager.hpp index 0f523591a..f3d16cd80 100644 --- a/apps/openmw/mwinput/mousemanager.hpp +++ b/apps/openmw/mwinput/mousemanager.hpp @@ -32,7 +32,7 @@ namespace MWInput bool injectMouseButtonPress(Uint8 button); bool injectMouseButtonRelease(Uint8 button); - void injectMouseMove(int xMove, int yMove, int mouseWheelMove); + void injectMouseMove(float xMove, float yMove, float mouseWheelMove); void warpMouse(); void setMouseLookEnabled(bool enabled) { mMouseLookEnabled = enabled; } From 7fb78e801f07a2d995e25f9199ac25b903968c4b Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 1 Jul 2020 11:02:02 +0400 Subject: [PATCH 020/107] Fix mouse release injection --- apps/openmw/mwinput/mousemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwinput/mousemanager.cpp b/apps/openmw/mwinput/mousemanager.cpp index 379830b1c..3fef62345 100644 --- a/apps/openmw/mwinput/mousemanager.cpp +++ b/apps/openmw/mwinput/mousemanager.cpp @@ -229,7 +229,7 @@ namespace MWInput bool MouseManager::injectMouseButtonRelease(Uint8 button) { - return MyGUI::InputManager::getInstance().injectMousePress(static_cast(mGuiCursorX), static_cast(mGuiCursorY), sdlButtonToMyGUI(button)); + return MyGUI::InputManager::getInstance().injectMouseRelease(static_cast(mGuiCursorX), static_cast(mGuiCursorY), sdlButtonToMyGUI(button)); } void MouseManager::injectMouseMove(float xMove, float yMove, float mouseWheelMove) From f268bc13f1e69e150e26871af2ae308615200607 Mon Sep 17 00:00:00 2001 From: Frederic Chardon Date: Wed, 1 Jul 2020 11:04:18 +0000 Subject: [PATCH 021/107] Do not set particle lifetime to 0 (#5472) --- CHANGELOG.md | 1 + components/nifosg/nifloader.cpp | 13 +++++++++---- components/nifosg/particle.cpp | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab1b61a7c..633685887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Bug #5441: Enemies can't push a player character when in critical strike stance Bug #5451: Magic projectiles don't disappear with the caster Bug #5452: Autowalk is being included in savegames + Bug #5472: Mistify mod causes CTD in 0.46 on Mac Bug #5479: NPCs who should be walking around town are standing around without walking Bug #5484: Zero value items shouldn't be able to be bought or sold for 1 gold Bug #5485: Intimidate doesn't increase disposition on marginal wins diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 88e89b400..6830e792f 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -923,15 +923,18 @@ namespace NifOsg osg::BoundingBox box; int i=0; - for (std::vector::const_iterator it = partctrl->particles.begin(); - iactiveCount && it != partctrl->particles.end(); ++it, ++i) + for (const auto& particle : partctrl->particles) { - const Nif::NiParticleSystemController::Particle& particle = *it; + if (i++ >= particledata->activeCount) + break; + + if (particle.lifespan <= 0) + continue; ParticleAgeSetter particletemplate(std::max(0.f, particle.lifetime)); osgParticle::Particle* created = partsys->createParticle(&particletemplate); - created->setLifeTime(std::max(0.f, particle.lifespan)); + created->setLifeTime(particle.lifespan); // Note this position and velocity is not correct for a particle system with absolute reference frame, // which can not be done in this loader since we are not attached to the scene yet. Will be fixed up post-load in the SceneManager. @@ -970,6 +973,8 @@ namespace NifOsg osgParticle::ConstantRateCounter* counter = new osgParticle::ConstantRateCounter; if (partctrl->emitFlags & Nif::NiParticleSystemController::NoAutoAdjust) counter->setNumberOfParticlesPerSecondToCreate(partctrl->emitRate); + else if (partctrl->lifetime == 0 && partctrl->lifetimeRandom == 0) + counter->setNumberOfParticlesPerSecondToCreate(0); else counter->setNumberOfParticlesPerSecondToCreate(partctrl->numParticles / (partctrl->lifetime + partctrl->lifetimeRandom/2)); diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index 804a8f8ab..f71dcdd96 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -125,7 +125,7 @@ void ParticleShooter::shoot(osgParticle::Particle *particle) const particle->setVelocity(dir * vel); // Not supposed to set this here, but there doesn't seem to be a better way of doing it - particle->setLifeTime(mLifetime + mLifetimeRandom * Misc::Rng::rollClosedProbability()); + particle->setLifeTime(std::max(std::numeric_limits::epsilon(), mLifetime + mLifetimeRandom * Misc::Rng::rollClosedProbability())); } GrowFadeAffector::GrowFadeAffector(float growTime, float fadeTime) @@ -184,6 +184,7 @@ ParticleColorAffector::ParticleColorAffector(const ParticleColorAffector ©, void ParticleColorAffector::operate(osgParticle::Particle* particle, double /* dt */) { + assert(particle->getLifeTime() > 0); float time = static_cast(particle->getAge()/particle->getLifeTime()); osg::Vec4f color = mData.interpKey(time); float alpha = color.a(); From 27f1a3376c01e5df2ced560d418101d672784fc9 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 5 Jun 2020 18:22:53 +0400 Subject: [PATCH 022/107] Add a separate stats watcher for GUI --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/mechanicsmanager.hpp | 4 - apps/openmw/mwbase/windowmanager.hpp | 19 +- apps/openmw/mwgui/charactercreation.cpp | 4 - apps/openmw/mwgui/charactercreation.hpp | 15 +- apps/openmw/mwgui/hud.hpp | 7 +- apps/openmw/mwgui/statswatcher.cpp | 209 ++++++++++++++++++ apps/openmw/mwgui/statswatcher.hpp | 69 ++++++ apps/openmw/mwgui/statswindow.hpp | 18 +- apps/openmw/mwgui/windowmanagerimp.cpp | 72 ++---- apps/openmw/mwgui/windowmanagerimp.hpp | 18 +- .../mwmechanics/mechanicsmanagerimp.cpp | 146 +----------- .../mwmechanics/mechanicsmanagerimp.hpp | 18 -- apps/openmw/mwworld/scene.cpp | 9 +- apps/openmw/mwworld/worldimp.cpp | 2 +- 15 files changed, 340 insertions(+), 272 deletions(-) create mode 100644 apps/openmw/mwgui/statswatcher.cpp create mode 100644 apps/openmw/mwgui/statswatcher.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 8631834c9..2f45d4fe7 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -41,7 +41,7 @@ add_openmw_dir (mwgui itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview - draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation textcolours + draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation textcolours statswatcher ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index c9ce43e01..b6ce4d061 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -67,10 +67,6 @@ namespace MWBase virtual void drop (const MWWorld::CellStore *cellStore) = 0; ///< Deregister all objects in the given cell. - virtual void watchActor (const MWWorld::Ptr& ptr) = 0; - ///< On each update look for changes in a previously registered actor and update the - /// GUI accordingly. - virtual void update (float duration, bool paused) = 0; ///< Update objects /// diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index d6afe9243..f35df7881 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -154,27 +154,11 @@ namespace MWBase virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0; - /// Set value for the given ID. - virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0; - virtual void setValue (int parSkill, const MWMechanics::SkillValue& value) = 0; - virtual void setValue (const std::string& id, const MWMechanics::DynamicStat& value) = 0; - virtual void setValue (const std::string& id, const std::string& value) = 0; - virtual void setValue (const std::string& id, int value) = 0; - /// Set time left for the player to start drowning (update the drowning bar) /// @param time time left to start drowning /// @param maxTime how long we can be underwater (in total) until drowning starts virtual void setDrowningTimeLeft (float time, float maxTime) = 0; - virtual void setPlayerClass (const ESM::Class &class_) = 0; - ///< set current class of player - - virtual void configureSkills (const SkillList& major, const SkillList& minor) = 0; - ///< configure skill groups, each set contains the skill ID for that group. - - virtual void updateSkillArea() = 0; - ///< update display of skills, factions, birth sign, reputation and bounty - virtual void changeCell(const MWWorld::CellStore* cell) = 0; ///< change the active cell @@ -359,6 +343,9 @@ namespace MWBase virtual void windowResized(int x, int y) = 0; virtual void windowClosed() = 0; virtual bool isWindowVisible() = 0; + + virtual void watchActor(const MWWorld::Ptr& ptr) = 0; + virtual MWWorld::Ptr getWatchedActor() const = 0; }; } diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 54e1a69a4..31fe3afb0 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -368,7 +368,6 @@ namespace MWGui if (klass) { mPlayerClass = *klass; - MWBase::Environment::get().getWindowManager()->setPlayerClass(mPlayerClass); } MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog); mPickClassDialog = 0; @@ -422,7 +421,6 @@ namespace MWGui if (mNameDialog) { mPlayerName = mNameDialog->getTextInput(); - MWBase::Environment::get().getWindowManager()->setValue("name", mPlayerName); MWBase::Environment::get().getMechanicsManager()->setPlayerName(mPlayerName); MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog); mNameDialog = 0; @@ -525,7 +523,6 @@ namespace MWGui MWBase::Environment::get().getMechanicsManager()->setPlayerClass(klass); mPlayerClass = klass; - MWBase::Environment::get().getWindowManager()->setPlayerClass(klass); // Do not delete dialog, so that choices are remembered in case we want to go back and adjust them later mCreateClassDialog->setVisible(false); @@ -722,7 +719,6 @@ namespace MWGui MWBase::Environment::get().getWorld()->getStore().get().find(mGenerateClass); mPlayerClass = *klass; - MWBase::Environment::get().getWindowManager()->setPlayerClass(mPlayerClass); updatePlayerHealth(); } diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index 4f6296785..beb8715fc 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -1,13 +1,12 @@ #ifndef CHARACTER_CREATION_HPP #define CHARACTER_CREATION_HPP -#include #include #include #include -#include "../mwmechanics/stat.hpp" +#include "statswatcher.hpp" namespace osg { @@ -35,21 +34,21 @@ namespace MWGui class ReviewDialog; class MessageBoxManager; - class CharacterCreation + class CharacterCreation : public StatsListener { public: typedef std::vector SkillList; CharacterCreation(osg::Group* parent, Resource::ResourceSystem* resourceSystem); - ~CharacterCreation(); + virtual ~CharacterCreation(); //Show a dialog void spawnDialog(const char id); - void setValue (const std::string& id, const MWMechanics::AttributeValue& value); - void setValue (const std::string& id, const MWMechanics::DynamicStat& value); - void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value); - void configureSkills (const SkillList& major, const SkillList& minor); + void setValue (const std::string& id, const MWMechanics::AttributeValue& value) override; + void setValue (const std::string& id, const MWMechanics::DynamicStat& value) override; + void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value) override; + void configureSkills(const SkillList& major, const SkillList& minor) override; void onFrame(float duration); diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index c33c4efad..c28dbc6d7 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -2,8 +2,7 @@ #define OPENMW_GAME_MWGUI_HUD_H #include "mapwindow.hpp" - -#include "../mwmechanics/stat.hpp" +#include "statswatcher.hpp" namespace MWWorld { @@ -17,12 +16,12 @@ namespace MWGui class ItemWidget; class SpellWidget; - class HUD : public WindowBase, public LocalMapBase + class HUD : public WindowBase, public LocalMapBase, public StatsListener { public: HUD(CustomMarkerCollection& customMarkers, DragAndDrop* dragAndDrop, MWRender::LocalMap* localMapRender); virtual ~HUD(); - void setValue (const std::string& id, const MWMechanics::DynamicStat& value); + void setValue (const std::string& id, const MWMechanics::DynamicStat& value) override; /// Set time left for the player to start drowning /// @param time time left to start drowning diff --git a/apps/openmw/mwgui/statswatcher.cpp b/apps/openmw/mwgui/statswatcher.cpp new file mode 100644 index 000000000..7baec2f2c --- /dev/null +++ b/apps/openmw/mwgui/statswatcher.cpp @@ -0,0 +1,209 @@ +#include "statswatcher.hpp" + +#include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" + +#include "../mwmechanics/npcstats.hpp" +#include "../mwmechanics/spellutil.hpp" + +#include "../mwworld/class.hpp" +#include "../mwworld/esmstore.hpp" +#include "../mwworld/inventorystore.hpp" + +namespace MWGui +{ + // mWatchedTimeToStartDrowning = -1 for correct drowning state check, + // if stats.getTimeToStartDrowning() == 0 already on game start + StatsWatcher::StatsWatcher() + : mWatchedLevel(-1), mWatchedTimeToStartDrowning(-1), mWatchedStatsEmpty(true) + { + } + + void StatsWatcher::watchActor(const MWWorld::Ptr& ptr) + { + mWatched = ptr; + } + + void StatsWatcher::update() + { + if (mWatched.isEmpty()) + return; + + MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager(); + const MWMechanics::NpcStats &stats = mWatched.getClass().getNpcStats(mWatched); + for (int i = 0;i < ESM::Attribute::Length;++i) + { + if (stats.getAttribute(i) != mWatchedAttributes[i] || mWatchedStatsEmpty) + { + std::stringstream attrname; + attrname << "AttribVal"<<(i+1); + + mWatchedAttributes[i] = stats.getAttribute(i); + setValue(attrname.str(), stats.getAttribute(i)); + } + } + + if (stats.getHealth() != mWatchedHealth || mWatchedStatsEmpty) + { + static const std::string hbar("HBar"); + mWatchedHealth = stats.getHealth(); + setValue(hbar, stats.getHealth()); + } + if (stats.getMagicka() != mWatchedMagicka || mWatchedStatsEmpty) + { + static const std::string mbar("MBar"); + mWatchedMagicka = stats.getMagicka(); + setValue(mbar, stats.getMagicka()); + } + if (stats.getFatigue() != mWatchedFatigue || mWatchedStatsEmpty) + { + static const std::string fbar("FBar"); + mWatchedFatigue = stats.getFatigue(); + setValue(fbar, stats.getFatigue()); + } + + float timeToDrown = stats.getTimeToStartDrowning(); + + if (timeToDrown != mWatchedTimeToStartDrowning) + { + static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get() + .find("fHoldBreathTime")->mValue.getFloat(); + + mWatchedTimeToStartDrowning = timeToDrown; + + if(timeToDrown >= fHoldBreathTime || timeToDrown == -1.0) // -1.0 is a special value during initialization + winMgr->setDrowningBarVisibility(false); + else + { + winMgr->setDrowningBarVisibility(true); + winMgr->setDrowningTimeLeft(stats.getTimeToStartDrowning(), fHoldBreathTime); + } + } + + //Loop over ESM::Skill::SkillEnum + for (int i = 0; i < ESM::Skill::Length; ++i) + { + if(stats.getSkill(i) != mWatchedSkills[i] || mWatchedStatsEmpty) + { + mWatchedSkills[i] = stats.getSkill(i); + setValue((ESM::Skill::SkillEnum)i, stats.getSkill(i)); + } + } + + if (stats.getLevel() != mWatchedLevel || mWatchedStatsEmpty) + { + mWatchedLevel = stats.getLevel(); + setValue("level", mWatchedLevel); + } + + if (mWatched.getClass().isNpc()) + { + const ESM::NPC *watchedRecord = mWatched.get()->mBase; + + if (watchedRecord->mName != mWatchedName || mWatchedStatsEmpty) + { + mWatchedName = watchedRecord->mName; + setValue("name", watchedRecord->mName); + } + + if (watchedRecord->mRace != mWatchedRace || mWatchedStatsEmpty) + { + mWatchedRace = watchedRecord->mRace; + const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore() + .get().find(watchedRecord->mRace); + setValue("race", race->mName); + } + + if (watchedRecord->mClass != mWatchedClass || mWatchedStatsEmpty) + { + mWatchedClass = watchedRecord->mClass; + const ESM::Class *cls = MWBase::Environment::get().getWorld()->getStore() + .get().find(watchedRecord->mClass); + setValue("class", cls->mName); + + MWBase::WindowManager::SkillList majorSkills (5); + MWBase::WindowManager::SkillList minorSkills (5); + + for (int i=0; i<5; ++i) + { + minorSkills[i] = cls->mData.mSkills[i][0]; + majorSkills[i] = cls->mData.mSkills[i][1]; + } + + configureSkills(majorSkills, minorSkills); + } + } + + mWatchedStatsEmpty = false; + + // Update the equipped weapon icon + MWWorld::InventoryStore& inv = mWatched.getClass().getInventoryStore(mWatched); + MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weapon == inv.end()) + winMgr->unsetSelectedWeapon(); + else + winMgr->setSelectedWeapon(*weapon); + + // Update the selected spell icon + MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); + if (enchantItem != inv.end()) + winMgr->setSelectedEnchantItem(*enchantItem); + else + { + const std::string& spell = winMgr->getSelectedSpell(); + if (!spell.empty()) + winMgr->setSelectedSpell(spell, int(MWMechanics::getSpellSuccessChance(spell, mWatched))); + else + winMgr->unsetSelectedSpell(); + } + } + + void StatsWatcher::addListener(StatsListener* listener) + { + mListeners.insert(listener); + } + + void StatsWatcher::removeListener(StatsListener* listener) + { + mListeners.erase(listener); + } + + void StatsWatcher::setValue(const std::string& id, const MWMechanics::AttributeValue& value) + { + for (StatsListener* listener : mListeners) + listener->setValue(id, value); + } + + void StatsWatcher::setValue(ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value) + { + /// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we + /// allow custom skills. + for (StatsListener* listener : mListeners) + listener->setValue(parSkill, value); + } + + void StatsWatcher::setValue(const std::string& id, const MWMechanics::DynamicStat& value) + { + for (StatsListener* listener : mListeners) + listener->setValue(id, value); + } + + void StatsWatcher::setValue(const std::string& id, const std::string& value) + { + for (StatsListener* listener : mListeners) + listener->setValue(id, value); + } + + void StatsWatcher::setValue(const std::string& id, int value) + { + for (StatsListener* listener : mListeners) + listener->setValue(id, value); + } + + void StatsWatcher::configureSkills(const std::vector& major, const std::vector& minor) + { + for (StatsListener* listener : mListeners) + listener->configureSkills(major, minor); + } +} diff --git a/apps/openmw/mwgui/statswatcher.hpp b/apps/openmw/mwgui/statswatcher.hpp new file mode 100644 index 000000000..9f17e5c54 --- /dev/null +++ b/apps/openmw/mwgui/statswatcher.hpp @@ -0,0 +1,69 @@ +#ifndef MWGUI_STATSWATCHER_H +#define MWGUI_STATSWATCHER_H + +#include + +#include +#include + +#include "../mwmechanics/stat.hpp" + +#include "../mwworld/ptr.hpp" + +namespace MWGui +{ + class StatsListener + { + public: + /// Set value for the given ID. + virtual void setValue(const std::string& id, const MWMechanics::AttributeValue& value) {} + virtual void setValue(const std::string& id, const MWMechanics::DynamicStat& value) {} + virtual void setValue(const std::string& id, const std::string& value) {} + virtual void setValue(const std::string& id, int value) {} + virtual void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value) {} + virtual void configureSkills(const std::vector& major, const std::vector& minor) {} + }; + + class StatsWatcher + { + MWWorld::Ptr mWatched; + + MWMechanics::AttributeValue mWatchedAttributes[ESM::Attribute::Length]; + MWMechanics::SkillValue mWatchedSkills[ESM::Skill::Length]; + + MWMechanics::DynamicStat mWatchedHealth; + MWMechanics::DynamicStat mWatchedMagicka; + MWMechanics::DynamicStat mWatchedFatigue; + + std::string mWatchedName; + std::string mWatchedRace; + std::string mWatchedClass; + + int mWatchedLevel; + + float mWatchedTimeToStartDrowning; + + bool mWatchedStatsEmpty; + + std::set mListeners; + + void setValue(const std::string& id, const MWMechanics::AttributeValue& value); + void setValue(const std::string& id, const MWMechanics::DynamicStat& value); + void setValue(const std::string& id, const std::string& value); + void setValue(const std::string& id, int value); + void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value); + void configureSkills(const std::vector& major, const std::vector& minor); + + public: + StatsWatcher(); + + void update(); + void addListener(StatsListener* listener); + void removeListener(StatsListener* listener); + + void watchActor(const MWWorld::Ptr& ptr); + virtual MWWorld::Ptr getWatchedActor() const { return mWatched; } + }; +} + +#endif diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp index 7d1be6a15..60e17a821 100644 --- a/apps/openmw/mwgui/statswindow.hpp +++ b/apps/openmw/mwgui/statswindow.hpp @@ -1,16 +1,14 @@ #ifndef MWGUI_STATS_WINDOW_H #define MWGUI_STATS_WINDOW_H -#include "../mwmechanics/stat.hpp" +#include "statswatcher.hpp" #include "windowpinnablebase.hpp" -#include - namespace MWGui { class WindowManager; - class StatsWindow : public WindowPinnableBase, public NoDrop + class StatsWindow : public WindowPinnableBase, public NoDrop, public StatsListener { public: typedef std::map FactionList; @@ -26,13 +24,13 @@ namespace MWGui void setPlayerName(const std::string& playerName); /// Set value for the given ID. - void setValue (const std::string& id, const MWMechanics::AttributeValue& value); - void setValue (const std::string& id, const MWMechanics::DynamicStat& value); - void setValue (const std::string& id, const std::string& value); - void setValue (const std::string& id, int value); - void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value); + void setValue (const std::string& id, const MWMechanics::AttributeValue& value) override; + void setValue (const std::string& id, const MWMechanics::DynamicStat& value) override; + void setValue (const std::string& id, const std::string& value) override; + void setValue (const std::string& id, int value) override; + void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value) override; + void configureSkills(const SkillList& major, const SkillList& minor) override; - void configureSkills (const SkillList& major, const SkillList& minor); void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; } void setBounty (int bounty) { if (bounty != mBounty) mChanged = true; this->mBounty = bounty; } void updateSkillArea(); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e1f7a4fbf..8f83c165a 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -272,6 +272,8 @@ namespace MWGui mVideoWrapper = new SDLUtil::VideoWrapper(window, viewer); mVideoWrapper->setGammaContrast(Settings::Manager::getFloat("gamma", "Video"), Settings::Manager::getFloat("contrast", "Video")); + + mStatsWatcher.reset(new StatsWatcher()); } void WindowManager::loadUserFonts() @@ -466,6 +468,10 @@ namespace MWGui // Set up visibility updateVisible(); + + mStatsWatcher->addListener(mHud); + mStatsWatcher->addListener(mStatsWindow); + mStatsWatcher->addListener(mCharGen); } int WindowManager::getFontHeight() const @@ -478,8 +484,11 @@ namespace MWGui if (newgame) { disallowAll(); + + mStatsWatcher->removeListener(mCharGen); delete mCharGen; mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem); + mStatsWatcher->addListener(mCharGen); } else allow(GW_ALL); @@ -489,6 +498,8 @@ namespace MWGui { try { + mStatsWatcher.reset(); + mKeyboardNavigation.reset(); MyGUI::LanguageManager::getInstance().eventRequestTag.clear(); @@ -649,58 +660,11 @@ namespace MWGui } } - void WindowManager::setValue (const std::string& id, const MWMechanics::AttributeValue& value) - { - mStatsWindow->setValue (id, value); - mCharGen->setValue(id, value); - } - - void WindowManager::setValue (int parSkill, const MWMechanics::SkillValue& value) - { - /// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we - /// allow custom skills. - mStatsWindow->setValue(static_cast (parSkill), value); - mCharGen->setValue(static_cast (parSkill), value); - } - - void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat& value) - { - mStatsWindow->setValue (id, value); - mHud->setValue (id, value); - mCharGen->setValue(id, value); - } - - void WindowManager::setValue (const std::string& id, const std::string& value) - { - mStatsWindow->setValue (id, value); - } - - void WindowManager::setValue (const std::string& id, int value) - { - mStatsWindow->setValue (id, value); - } - void WindowManager::setDrowningTimeLeft (float time, float maxTime) { mHud->setDrowningTimeLeft(time, maxTime); } - void WindowManager::setPlayerClass (const ESM::Class &class_) - { - mStatsWindow->setValue("class", class_.mName); - } - - void WindowManager::configureSkills (const SkillList& major, const SkillList& minor) - { - mStatsWindow->configureSkills (major, minor); - mCharGen->configureSkills(major, minor); - } - - void WindowManager::updateSkillArea() - { - mStatsWindow->updateSkillArea(); - } - void WindowManager::removeDialog(Layout*dialog) { if (!dialog) @@ -904,7 +868,9 @@ namespace MWGui if (mCharGen) mCharGen->onFrame(frameDuration); - updateActivatedQuickKey (); + updateActivatedQuickKey(); + + mStatsWatcher->update(); cleanupGarbage(); } @@ -2210,4 +2176,14 @@ namespace MWGui for (unsigned int i=0; isetVisible(visible); } + + void WindowManager::watchActor(const MWWorld::Ptr& ptr) + { + mStatsWatcher->watchActor(ptr); + } + + MWWorld::Ptr WindowManager::getWatchedActor() const + { + return mStatsWatcher->getWatchedActor(); + } } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 42750705d..a8cb0b10a 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -13,13 +13,12 @@ #include "../mwbase/windowmanager.hpp" -#include "../mwworld/ptr.hpp" - #include #include #include #include "mapwindow.hpp" +#include "statswatcher.hpp" #include "textcolours.hpp" #include @@ -195,22 +194,11 @@ namespace MWGui virtual void setConsoleSelectedObject(const MWWorld::Ptr& object); - ///< Set value for the given ID. - virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value); - virtual void setValue (int parSkill, const MWMechanics::SkillValue& value); - virtual void setValue (const std::string& id, const MWMechanics::DynamicStat& value); - virtual void setValue (const std::string& id, const std::string& value); - virtual void setValue (const std::string& id, int value); - /// Set time left for the player to start drowning (update the drowning bar) /// @param time time left to start drowning /// @param maxTime how long we can be underwater (in total) until drowning starts virtual void setDrowningTimeLeft (float time, float maxTime); - virtual void setPlayerClass (const ESM::Class &class_); ///< set current class of player - virtual void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group. - virtual void updateSkillArea(); ///< update display of skills, factions, birth sign, reputation and bounty - virtual void changeCell(const MWWorld::CellStore* cell); ///< change the active cell virtual void setFocusObject(const MWWorld::Ptr& focus); @@ -298,6 +286,9 @@ namespace MWGui virtual void windowClosed(); virtual bool isWindowVisible(); + virtual void watchActor(const MWWorld::Ptr& ptr); + virtual MWWorld::Ptr getWatchedActor() const; + virtual void executeInConsole (const std::string& path); virtual void enableRest() { mRestAllowed = true; } @@ -400,6 +391,7 @@ namespace MWGui osgViewer::Viewer* mViewer; std::unique_ptr mFontLoader; + std::unique_ptr mStatsWatcher; bool mConsoleOnlyScripts; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index d7da4ebb7..fcae60c58 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -236,10 +236,8 @@ namespace MWMechanics invStore.autoEquip(ptr); } - // mWatchedTimeToStartDrowning = -1 for correct drowning state check, - // if stats.getTimeToStartDrowning() == 0 already on game start MechanicsManager::MechanicsManager() - : mWatchedLevel(-1), mWatchedTimeToStartDrowning(-1), mWatchedStatsEmpty (true), mUpdatePlayer (true), mClassSelected (false), + : mUpdatePlayer (true), mClassSelected (false), mRaceSelected (false), mAI(true) { //buildPlayer no longer here, needs to be done explicitly after all subsystems are up and running @@ -261,16 +259,16 @@ namespace MWMechanics void MechanicsManager::remove(const MWWorld::Ptr& ptr) { - if(ptr == mWatched) - mWatched = MWWorld::Ptr(); + if(ptr == MWBase::Environment::get().getWindowManager()->getWatchedActor()) + MWBase::Environment::get().getWindowManager()->watchActor(MWWorld::Ptr()); mActors.removeActor(ptr); mObjects.removeObject(ptr); } void MechanicsManager::updateCell(const MWWorld::Ptr &old, const MWWorld::Ptr &ptr) { - if(old == mWatched) - mWatched = ptr; + if(old == MWBase::Environment::get().getWindowManager()->getWatchedActor()) + MWBase::Environment::get().getWindowManager()->watchActor(ptr); if(ptr.getClass().isActor()) mActors.updateActor(old, ptr); @@ -278,19 +276,12 @@ namespace MWMechanics mObjects.updateObject(old, ptr); } - void MechanicsManager::drop(const MWWorld::CellStore *cellStore) { - mActors.dropActors(cellStore, mWatched); + mActors.dropActors(cellStore, getPlayer()); mObjects.dropObjects(cellStore); } - - void MechanicsManager::watchActor(const MWWorld::Ptr& ptr) - { - mWatched = ptr; - } - void MechanicsManager::restoreStatsAfterCorprus(const MWWorld::Ptr& actor, const std::string& sourceId) { auto& stats = actor.getClass().getCreatureStats (actor); @@ -311,133 +302,10 @@ namespace MWMechanics void MechanicsManager::update(float duration, bool paused) { - if(!mWatched.isEmpty()) - { - MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager(); - const MWMechanics::NpcStats &stats = mWatched.getClass().getNpcStats(mWatched); - for(int i = 0;i < ESM::Attribute::Length;++i) - { - if(stats.getAttribute(i) != mWatchedAttributes[i] || mWatchedStatsEmpty) - { - std::stringstream attrname; - attrname << "AttribVal"<<(i+1); - - mWatchedAttributes[i] = stats.getAttribute(i); - winMgr->setValue(attrname.str(), stats.getAttribute(i)); - } - } - - if(stats.getHealth() != mWatchedHealth || mWatchedStatsEmpty) - { - static const std::string hbar("HBar"); - mWatchedHealth = stats.getHealth(); - winMgr->setValue(hbar, stats.getHealth()); - } - if(stats.getMagicka() != mWatchedMagicka || mWatchedStatsEmpty) - { - static const std::string mbar("MBar"); - mWatchedMagicka = stats.getMagicka(); - winMgr->setValue(mbar, stats.getMagicka()); - } - if(stats.getFatigue() != mWatchedFatigue || mWatchedStatsEmpty) - { - static const std::string fbar("FBar"); - mWatchedFatigue = stats.getFatigue(); - winMgr->setValue(fbar, stats.getFatigue()); - } - - float timeToDrown = stats.getTimeToStartDrowning(); - - if(timeToDrown != mWatchedTimeToStartDrowning) - { - static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get() - .find("fHoldBreathTime")->mValue.getFloat(); - - mWatchedTimeToStartDrowning = timeToDrown; - - if(timeToDrown >= fHoldBreathTime || timeToDrown == -1.0) // -1.0 is a special value during initialization - winMgr->setDrowningBarVisibility(false); - else - { - winMgr->setDrowningBarVisibility(true); - winMgr->setDrowningTimeLeft(stats.getTimeToStartDrowning(), fHoldBreathTime); - } - } - - //Loop over ESM::Skill::SkillEnum - for(int i = 0; i < ESM::Skill::Length; ++i) - { - if(stats.getSkill(i) != mWatchedSkills[i] || mWatchedStatsEmpty) - { - mWatchedSkills[i] = stats.getSkill(i); - winMgr->setValue((ESM::Skill::SkillEnum)i, stats.getSkill(i)); - } - } - - if(stats.getLevel() != mWatchedLevel) - { - mWatchedLevel = stats.getLevel(); - winMgr->setValue("level", mWatchedLevel); - } - - mWatchedStatsEmpty = false; - - // Update the equipped weapon icon - MWWorld::InventoryStore& inv = mWatched.getClass().getInventoryStore(mWatched); - MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if (weapon == inv.end()) - winMgr->unsetSelectedWeapon(); - else - winMgr->setSelectedWeapon(*weapon); - - // Update the selected spell icon - MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); - if (enchantItem != inv.end()) - winMgr->setSelectedEnchantItem(*enchantItem); - else - { - const std::string& spell = winMgr->getSelectedSpell(); - if (!spell.empty()) - winMgr->setSelectedSpell(spell, int(getSpellSuccessChance(spell, mWatched))); - else - winMgr->unsetSelectedSpell(); - } - - } - if (mUpdatePlayer) { - MWBase::World *world = MWBase::Environment::get().getWorld(); - - // basic player profile; should not change anymore after the creation phase is finished. - MWBase::WindowManager *winMgr = - MWBase::Environment::get().getWindowManager(); - - const ESM::NPC *player = - world->getPlayerPtr().get()->mBase; - - const ESM::Race *race = - world->getStore().get().find(player->mRace); - const ESM::Class *cls = - world->getStore().get().find(player->mClass); - - winMgr->setValue ("name", player->mName); - winMgr->setValue ("race", race->mName); - winMgr->setValue ("class", cls->mName); - mUpdatePlayer = false; - MWBase::WindowManager::SkillList majorSkills (5); - MWBase::WindowManager::SkillList minorSkills (5); - - for (int i=0; i<5; ++i) - { - minorSkills[i] = cls->mData.mSkills[i][0]; - majorSkills[i] = cls->mData.mSkills[i][1]; - } - - winMgr->configureSkills (majorSkills, minorSkills); - // HACK? The player has been changed, so a new Animation object may // have been made for them. Make sure they're properly updated. MWWorld::Ptr ptr = getPlayer(); @@ -517,7 +385,7 @@ namespace MWMechanics int MechanicsManager::getHoursToRest() const { - return mActors.getHoursToRest(mWatched); + return mActors.getHoursToRest(getPlayer()); } void MechanicsManager::setPlayerName (const std::string& name) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 86bc4c720..c546497bb 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -21,20 +21,6 @@ namespace MWMechanics { class MechanicsManager : public MWBase::MechanicsManager { - MWWorld::Ptr mWatched; - - AttributeValue mWatchedAttributes[8]; - SkillValue mWatchedSkills[27]; - - DynamicStat mWatchedHealth; - DynamicStat mWatchedMagicka; - DynamicStat mWatchedFatigue; - - int mWatchedLevel; - - float mWatchedTimeToStartDrowning; - - bool mWatchedStatsEmpty; bool mUpdatePlayer; bool mClassSelected; bool mRaceSelected; @@ -68,10 +54,6 @@ namespace MWMechanics virtual void drop(const MWWorld::CellStore *cellStore) override; ///< Deregister all objects in the given cell. - virtual void watchActor(const MWWorld::Ptr& ptr) override; - ///< On each update look for changes in a previously registered actor and update the - /// GUI accordingly. - virtual void update (float duration, bool paused) override; ///< Update objects /// diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 42fe1a960..113848394 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -741,15 +741,12 @@ namespace MWWorld player.getClass().adjustPosition(player, true); } - MWBase::MechanicsManager *mechMgr = - MWBase::Environment::get().getMechanicsManager(); - - mechMgr->updateCell(old, player); - mechMgr->watchActor(player); + MWBase::Environment::get().getMechanicsManager()->updateCell(old, player); + MWBase::Environment::get().getWindowManager()->watchActor(player); mPhysics->updatePtr(old, player); - MWBase::Environment::get().getWorld()->adjustSky(); + world->adjustSky(); mLastPlayerPos = player.getRefData().getPosition().asVec3(); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6788a7fa2..d8b822242 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2453,7 +2453,7 @@ namespace MWWorld rotateObject(player, 0.f, 0.f, 0.f, MWBase::RotationFlag_inverseOrder | MWBase::RotationFlag_adjust); MWBase::Environment::get().getMechanicsManager()->add(getPlayerPtr()); - MWBase::Environment::get().getMechanicsManager()->watchActor(getPlayerPtr()); + MWBase::Environment::get().getWindowManager()->watchActor(getPlayerPtr()); std::string model = getPlayerPtr().getClass().getModel(getPlayerPtr()); model = Misc::ResourceHelpers::correctActorModelPath(model, mResourceSystem->getVFS()); From f53f049a648f1ffbc61558e2369080dc2ead06db Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 1 Jul 2020 17:42:18 +0200 Subject: [PATCH 023/107] give MacOS 10.15 a spin --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d877e8acc..5fec5a830 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,9 +37,9 @@ addons: build_command: "make VERBOSE=1 -j3" matrix: include: - - name: OpenMW (all) on macOS Xcode 10.2 + - name: OpenMW (all) on MacOS 10.15 with Xcode 12 os: osx - osx_image: xcode10.2 + osx_image: xcode12 if: branch != coverity_scan - name: OpenMW (all) on Ubuntu Focal with GCC os: linux From 439891ef5359040e8e0e5a8322d9415f2a2dad59 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 14:41:05 +0200 Subject: [PATCH 024/107] Put logic to update water sound id and volume into a separate class --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwsound/soundmanagerimp.cpp | 88 ++++++++--------------- apps/openmw/mwsound/soundmanagerimp.hpp | 9 +-- apps/openmw/mwsound/watersoundupdater.cpp | 71 ++++++++++++++++++ apps/openmw/mwsound/watersoundupdater.hpp | 54 ++++++++++++++ 5 files changed, 157 insertions(+), 67 deletions(-) create mode 100644 apps/openmw/mwsound/watersoundupdater.cpp create mode 100644 apps/openmw/mwsound/watersoundupdater.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 8631834c9..775a4358f 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -57,7 +57,7 @@ add_openmw_dir (mwscript add_openmw_dir (mwsound soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output - loudness movieaudiofactory alext efx efx-presets regionsoundselector + loudness movieaudiofactory alext efx efx-presets regionsoundselector watersoundupdater ) add_openmw_dir (mwworld diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 79cff8bf0..c3ee5ea64 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -30,6 +30,23 @@ namespace MWSound { + namespace + { + WaterSoundUpdaterSettings makeWaterSoundUpdaterSettings() + { + WaterSoundUpdaterSettings settings; + + settings.mNearWaterRadius = Fallback::Map::getInt("Water_NearWaterRadius"); + settings.mNearWaterPoints = Fallback::Map::getInt("Water_NearWaterPoints"); + settings.mNearWaterIndoorTolerance = Fallback::Map::getFloat("Water_NearWaterIndoorTolerance"); + settings.mNearWaterOutdoorTolerance = Fallback::Map::getFloat("Water_NearWaterOutdoorTolerance"); + settings.mNearWaterIndoorID = Misc::StringUtils::lowerCase(Fallback::Map::getString("Water_NearWaterIndoorID")); + settings.mNearWaterOutdoorID = Misc::StringUtils::lowerCase(Fallback::Map::getString("Water_NearWaterOutdoorID")); + + return settings; + } + } + // For combining PlayMode and Type flags inline int operator|(PlayMode a, Type b) { return static_cast(a) | static_cast(b); } @@ -41,6 +58,7 @@ namespace MWSound , mMusicVolume(1.0f) , mVoiceVolume(1.0f) , mFootstepsVolume(1.0f) + , mWaterSoundUpdater(makeWaterSoundUpdaterSettings()) , mSoundBuffers(new SoundBufferList::element_type()) , mBufferCacheSize(0) , mSounds(new std::deque()) @@ -65,13 +83,6 @@ namespace MWSound mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); mFootstepsVolume = std::min(std::max(mFootstepsVolume, 0.0f), 1.0f); - mNearWaterRadius = Fallback::Map::getInt("Water_NearWaterRadius"); - mNearWaterPoints = Fallback::Map::getInt("Water_NearWaterPoints"); - mNearWaterIndoorTolerance = Fallback::Map::getFloat("Water_NearWaterIndoorTolerance"); - mNearWaterOutdoorTolerance = Fallback::Map::getFloat("Water_NearWaterOutdoorTolerance"); - mNearWaterIndoorID = Misc::StringUtils::lowerCase(Fallback::Map::getString("Water_NearWaterIndoorID")); - mNearWaterOutdoorID = Misc::StringUtils::lowerCase(Fallback::Map::getString("Water_NearWaterOutdoorID")); - mBufferCacheMin = std::max(Settings::Manager::getInt("buffer cache min", "Sound"), 1); mBufferCacheMax = std::max(Settings::Manager::getInt("buffer cache max", "Sound"), 1); mBufferCacheMax *= 1024*1024; @@ -912,57 +923,12 @@ namespace MWSound static const ESM::Cell *LastCell; MWBase::World* world = MWBase::Environment::get().getWorld(); const MWWorld::ConstPtr player = world->getPlayerPtr(); - osg::Vec3f pos = player.getRefData().getPosition().asVec3(); const ESM::Cell *curcell = player.getCell()->getCell(); - - float volume = 0.0f; - const std::string& soundId = player.getCell()->isExterior() ? mNearWaterOutdoorID : mNearWaterIndoorID; - - if (!mListenerUnderwater) - { - if (curcell->hasWater()) - { - float dist = std::abs(player.getCell()->getWaterLevel() - pos.z()); - - if (player.getCell()->isExterior() && dist < mNearWaterOutdoorTolerance) - { - volume = (mNearWaterOutdoorTolerance - dist) / mNearWaterOutdoorTolerance; - - if (mNearWaterPoints > 1) - { - int underwaterPoints = 0; - - float step = mNearWaterRadius * 2.0f / (mNearWaterPoints - 1); - - for (int x = 0; x < mNearWaterPoints; x++) - { - for (int y = 0; y < mNearWaterPoints; y++) - { - float height = world->getTerrainHeightAt( - osg::Vec3f(pos.x() - mNearWaterRadius + x*step, pos.y() - mNearWaterRadius + y*step, 0.0f)); - - if (height < 0) - underwaterPoints++; - } - } - - volume *= underwaterPoints * 2.0f / (mNearWaterPoints*mNearWaterPoints); - } - } - else if (!player.getCell()->isExterior() && dist < mNearWaterIndoorTolerance) - { - volume = (mNearWaterIndoorTolerance - dist) / mNearWaterIndoorTolerance; - } - } - } - else - volume = 1.0f; - - volume = std::min(volume, 1.0f); + const auto update = mWaterSoundUpdater.update(player, *world); if (mNearWaterSound) { - if (volume == 0.0f) + if (update.mVolume == 0.0f) { mOutput->finishSound(mNearWaterSound); mNearWaterSound = nullptr; @@ -971,7 +937,7 @@ namespace MWSound { bool soundIdChanged = false; - Sound_Buffer *sfx = lookupSound(soundId); + Sound_Buffer *sfx = lookupSound(update.mId); if(LastCell != curcell) { LastCell = curcell; @@ -991,16 +957,16 @@ namespace MWSound if(soundIdChanged) { mOutput->finishSound(mNearWaterSound); - mNearWaterSound = playSound(soundId, volume, 1.0f, Type::Sfx, PlayMode::Loop); + mNearWaterSound = playSound(update.mId, update.mVolume, 1.0f, Type::Sfx, PlayMode::Loop); } else if (sfx) - mNearWaterSound->setVolume(volume * sfx->mVolume); + mNearWaterSound->setVolume(update.mVolume * sfx->mVolume); } } - else if (volume > 0.0f) + else if (update.mVolume > 0.0f) { LastCell = curcell; - mNearWaterSound = playSound(soundId, volume, 1.0f, Type::Sfx, PlayMode::Loop); + mNearWaterSound = playSound(update.mId, update.mVolume, 1.0f, Type::Sfx, PlayMode::Loop); } } @@ -1165,7 +1131,7 @@ namespace MWSound mMusic->updateFade(duration); mOutput->updateStream(mMusic); - + if (mMusic->getRealVolume() <= 0.f) { streamMusicFull(mNextMusic); @@ -1242,6 +1208,8 @@ namespace MWSound mListenerUp = up; mListenerUnderwater = underwater; + + mWaterSoundUpdater.setUnderwater(underwater); } void SoundManager::updatePtr(const MWWorld::ConstPtr &old, const MWWorld::ConstPtr &updated) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index be457ae38..81f7cd84a 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -15,6 +15,7 @@ #include "../mwbase/soundmanager.hpp" #include "regionsoundselector.hpp" +#include "watersoundupdater.hpp" namespace VFS { @@ -61,12 +62,8 @@ namespace MWSound float mVoiceVolume; float mFootstepsVolume; - int mNearWaterRadius; - int mNearWaterPoints; - float mNearWaterIndoorTolerance; - float mNearWaterOutdoorTolerance; - std::string mNearWaterIndoorID; - std::string mNearWaterOutdoorID; + WaterSoundUpdater mWaterSoundUpdater; + typedef std::unique_ptr > SoundBufferList; // List of sound buffers, grown as needed. New enties are added to the // back, allowing existing Sound_Buffer references/pointers to remain diff --git a/apps/openmw/mwsound/watersoundupdater.cpp b/apps/openmw/mwsound/watersoundupdater.cpp new file mode 100644 index 000000000..b1646c404 --- /dev/null +++ b/apps/openmw/mwsound/watersoundupdater.cpp @@ -0,0 +1,71 @@ +#include "watersoundupdater.hpp" + +#include "../mwbase/world.hpp" +#include "../mwworld/cellstore.hpp" +#include "../mwworld/ptr.hpp" + +#include + +#include + +namespace MWSound +{ + WaterSoundUpdater::WaterSoundUpdater(const WaterSoundUpdaterSettings& settings) + : mSettings(settings) + { + } + + WaterSoundUpdate WaterSoundUpdater::update(const MWWorld::ConstPtr& player, const MWBase::World& world) const + { + WaterSoundUpdate result; + + result.mId = player.getCell()->isExterior() ? mSettings.mNearWaterOutdoorID : mSettings.mNearWaterIndoorID; + result.mVolume = std::min(1.0f, getVolume(player, world)); + + return result; + } + + float WaterSoundUpdater::getVolume(const MWWorld::ConstPtr& player, const MWBase::World& world) const + { + if (mListenerUnderwater) + return 1.0f; + + const MWWorld::CellStore& cell = *player.getCell(); + + if (!cell.getCell()->hasWater()) + return 0.0f; + + const osg::Vec3f pos = player.getRefData().getPosition().asVec3(); + const float dist = std::abs(cell.getWaterLevel() - pos.z()); + + if (cell.isExterior() && dist < mSettings.mNearWaterOutdoorTolerance) + { + if (mSettings.mNearWaterPoints <= 1) + return (mSettings.mNearWaterOutdoorTolerance - dist) / mSettings.mNearWaterOutdoorTolerance; + + const float step = mSettings.mNearWaterRadius * 2.0f / (mSettings.mNearWaterPoints - 1); + + int underwaterPoints = 0; + + for (int x = 0; x < mSettings.mNearWaterPoints; x++) + { + for (int y = 0; y < mSettings.mNearWaterPoints; y++) + { + const float terrainX = pos.x() - mSettings.mNearWaterRadius + x * step; + const float terrainY = pos.y() - mSettings.mNearWaterRadius + y * step; + const float height = world.getTerrainHeightAt(osg::Vec3f(terrainX, terrainY, 0.0f)); + + if (height < 0) + underwaterPoints++; + } + } + + return underwaterPoints * 2.0f / (mSettings.mNearWaterPoints * mSettings.mNearWaterPoints); + } + + if (!cell.isExterior() && dist < mSettings.mNearWaterIndoorTolerance) + return (mSettings.mNearWaterIndoorTolerance - dist) / mSettings.mNearWaterIndoorTolerance; + + return 0.0f; + } +} diff --git a/apps/openmw/mwsound/watersoundupdater.hpp b/apps/openmw/mwsound/watersoundupdater.hpp new file mode 100644 index 000000000..b20b9db6c --- /dev/null +++ b/apps/openmw/mwsound/watersoundupdater.hpp @@ -0,0 +1,54 @@ +#ifndef GAME_SOUND_WATERSOUNDUPDATER_H +#define GAME_SOUND_WATERSOUNDUPDATER_H + +#include + +namespace MWBase +{ + class World; +} + +namespace MWWorld +{ + class ConstPtr; +} + +namespace MWSound +{ + struct WaterSoundUpdaterSettings + { + int mNearWaterRadius; + int mNearWaterPoints; + float mNearWaterIndoorTolerance; + float mNearWaterOutdoorTolerance; + std::string mNearWaterIndoorID; + std::string mNearWaterOutdoorID; + }; + + struct WaterSoundUpdate + { + std::string mId; + float mVolume; + }; + + class WaterSoundUpdater + { + public: + explicit WaterSoundUpdater(const WaterSoundUpdaterSettings& settings); + + WaterSoundUpdate update(const MWWorld::ConstPtr& player, const MWBase::World& world) const; + + void setUnderwater(bool value) + { + mListenerUnderwater = value; + } + + private: + const WaterSoundUpdaterSettings mSettings; + bool mListenerUnderwater = false; + + float getVolume(const MWWorld::ConstPtr& player, const MWBase::World& world) const; + }; +} + +#endif From 3eeee4bc9477451c0ec01377b3d96e73c59e17ef Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 1 Jul 2020 17:52:34 +0200 Subject: [PATCH 025/107] drop need to upgrade qt, 5.15 is by default installed; add CXX_FLAGS; retarget SYSROOT to 10.15 --- CI/before_install.osx.sh | 1 - CI/before_script.osx.sh | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_install.osx.sh b/CI/before_install.osx.sh index e279d1933..0f69ecb39 100755 --- a/CI/before_install.osx.sh +++ b/CI/before_install.osx.sh @@ -2,7 +2,6 @@ brew update brew outdated pkgconfig || brew upgrade pkgconfig -brew install qt brew install ccache curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-ef2462c.zip -o ~/openmw-deps.zip diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index 01d9d2b80..c71dc3d6f 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -13,8 +13,9 @@ cmake \ -D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \ -D CMAKE_C_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" \ -D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" \ +-D CMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" \ -D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \ --D CMAKE_OSX_SYSROOT="macosx10.14" \ +-D CMAKE_OSX_SYSROOT="macosx10.15" \ -D CMAKE_BUILD_TYPE=Release \ -D OPENMW_OSX_DEPLOYMENT=TRUE \ -D BUILD_ESMTOOL=FALSE \ From a62e3a7b35c46c4177625a20c392605a08fca536 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 1 Jul 2020 18:50:41 +0200 Subject: [PATCH 026/107] What happens when I remove the sysroot line? --- CI/before_script.osx.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index c71dc3d6f..8bcfe99ce 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -15,7 +15,6 @@ cmake \ -D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" \ -D CMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" \ -D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \ --D CMAKE_OSX_SYSROOT="macosx10.15" \ -D CMAKE_BUILD_TYPE=Release \ -D OPENMW_OSX_DEPLOYMENT=TRUE \ -D BUILD_ESMTOOL=FALSE \ From 1e23d007dd8b16905d5efb1bd4d2c15480deadbb Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 1 Jul 2020 22:23:02 +0200 Subject: [PATCH 027/107] Use Debug instead of Release to increase build time (passing -O0) --- CI/before_script.osx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index 8bcfe99ce..7ba21b23b 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -15,7 +15,7 @@ cmake \ -D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" \ -D CMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" \ -D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \ --D CMAKE_BUILD_TYPE=Release \ +-D CMAKE_BUILD_TYPE=DEBUG \ -D OPENMW_OSX_DEPLOYMENT=TRUE \ -D BUILD_ESMTOOL=FALSE \ -G"Unix Makefiles" \ From a36a55bfb5deca08d5d176b18470fe2e6355284d Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 1 Jul 2020 18:37:31 +0200 Subject: [PATCH 028/107] Clamp sound volume on settings update --- CHANGELOG.md | 1 + apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/soundmanager.hpp | 10 +---- apps/openmw/mwsound/soundmanagerimp.cpp | 43 +------------------ apps/openmw/mwsound/soundmanagerimp.hpp | 8 ++-- apps/openmw/mwsound/type.hpp | 17 ++++++++ apps/openmw/mwsound/volumesettings.cpp | 56 +++++++++++++++++++++++++ apps/openmw/mwsound/volumesettings.hpp | 26 ++++++++++++ 8 files changed, 108 insertions(+), 55 deletions(-) create mode 100644 apps/openmw/mwsound/type.hpp create mode 100644 apps/openmw/mwsound/volumesettings.cpp create mode 100644 apps/openmw/mwsound/volumesettings.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 633685887..687e421fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ Bug #5490: Hits to carried left slot aren't redistributed if there's no shield equipped Bug #5499: Faction advance is available when requirements not met Bug #5502: Dead zone for analogue stick movement is too small + Bug #5507: Sound volume is not clamped on ingame settings update Feature #390: 3rd person look "over the shoulder" Feature #2386: Distant Statics in the form of Object Paging Feature #5297: Add a search function to the "Datafiles" tab of the OpenMW launcher diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 277a79235..d174d7b15 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -57,7 +57,7 @@ add_openmw_dir (mwscript add_openmw_dir (mwsound soundmanagerimp openal_output ffmpeg_decoder sound sound_buffer sound_decoder sound_output - loudness movieaudiofactory alext efx efx-presets regionsoundselector watersoundupdater + loudness movieaudiofactory alext efx efx-presets regionsoundselector watersoundupdater volumesettings ) add_openmw_dir (mwworld diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp index 81b54c566..2bac561fd 100644 --- a/apps/openmw/mwbase/soundmanager.hpp +++ b/apps/openmw/mwbase/soundmanager.hpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwsound/type.hpp" namespace MWWorld { @@ -44,14 +45,7 @@ namespace MWSound LoopNoEnv = Loop | NoEnv, LoopRemoveAtDistance = Loop | RemoveAtDistance }; - enum class Type { - Sfx = 1<<4, /* Normal SFX sound */ - Voice = 1<<5, /* Voice sound */ - Foot = 1<<6, /* Footstep sound */ - Music = 1<<7, /* Music track */ - Movie = 1<<8, /* Movie audio track */ - Mask = Sfx | Voice | Foot | Music | Movie - }; + // Used for creating a type mask for SoundManager::pauseSounds and resumeSounds inline int operator~(Type a) { return ~static_cast(a); } inline int operator&(Type a, Type b) { return static_cast(a) & static_cast(b); } diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index c3ee5ea64..a1eb59bac 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -53,11 +53,6 @@ namespace MWSound SoundManager::SoundManager(const VFS::Manager* vfs, bool useSound) : mVFS(vfs) , mOutput(new DEFAULT_OUTPUT(*this)) - , mMasterVolume(1.0f) - , mSFXVolume(1.0f) - , mMusicVolume(1.0f) - , mVoiceVolume(1.0f) - , mFootstepsVolume(1.0f) , mWaterSoundUpdater(makeWaterSoundUpdaterSettings()) , mSoundBuffers(new SoundBufferList::element_type()) , mBufferCacheSize(0) @@ -72,17 +67,6 @@ namespace MWSound , mNearWaterSound(nullptr) , mPlaybackPaused(false) { - mMasterVolume = Settings::Manager::getFloat("master volume", "Sound"); - mMasterVolume = std::min(std::max(mMasterVolume, 0.0f), 1.0f); - mSFXVolume = Settings::Manager::getFloat("sfx volume", "Sound"); - mSFXVolume = std::min(std::max(mSFXVolume, 0.0f), 1.0f); - mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); - mMusicVolume = std::min(std::max(mMusicVolume, 0.0f), 1.0f); - mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); - mVoiceVolume = std::min(std::max(mVoiceVolume, 0.0f), 1.0f); - mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); - mFootstepsVolume = std::min(std::max(mFootstepsVolume, 0.0f), 1.0f); - mBufferCacheMin = std::max(Settings::Manager::getInt("buffer cache min", "Sound"), 1); mBufferCacheMax = std::max(Settings::Manager::getInt("buffer cache max", "Sound"), 1); mBufferCacheMax *= 1024*1024; @@ -349,26 +333,7 @@ namespace MWSound // Gets the combined volume settings for the given sound type float SoundManager::volumeFromType(Type type) const { - float volume = mMasterVolume; - switch(type) - { - case Type::Sfx: - volume *= mSFXVolume; - break; - case Type::Voice: - volume *= mVoiceVolume; - break; - case Type::Foot: - volume *= mFootstepsVolume; - break; - case Type::Music: - volume *= mMusicVolume; - break; - case Type::Movie: - case Type::Mask: - break; - } - return volume; + return mVolumeSettings.getVolumeFromType(type); } void SoundManager::stopMusic() @@ -1158,11 +1123,7 @@ namespace MWSound void SoundManager::processChangedSettings(const Settings::CategorySettingVector& settings) { - mMasterVolume = Settings::Manager::getFloat("master volume", "Sound"); - mMusicVolume = Settings::Manager::getFloat("music volume", "Sound"); - mSFXVolume = Settings::Manager::getFloat("sfx volume", "Sound"); - mFootstepsVolume = Settings::Manager::getFloat("footsteps volume", "Sound"); - mVoiceVolume = Settings::Manager::getFloat("voice volume", "Sound"); + mVolumeSettings.update(); if(!mOutput->isInitialized()) return; diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 81f7cd84a..c79f9abe5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -16,6 +16,8 @@ #include "regionsoundselector.hpp" #include "watersoundupdater.hpp" +#include "type.hpp" +#include "volumesettings.hpp" namespace VFS { @@ -56,11 +58,7 @@ namespace MWSound std::unordered_map> mMusicToPlay; // A list with music files not yet played std::string mLastPlayedMusic; // The music file that was last played - float mMasterVolume; - float mSFXVolume; - float mMusicVolume; - float mVoiceVolume; - float mFootstepsVolume; + VolumeSettings mVolumeSettings; WaterSoundUpdater mWaterSoundUpdater; diff --git a/apps/openmw/mwsound/type.hpp b/apps/openmw/mwsound/type.hpp new file mode 100644 index 000000000..9f95bfa40 --- /dev/null +++ b/apps/openmw/mwsound/type.hpp @@ -0,0 +1,17 @@ +#ifndef GAME_SOUND_TYPE_H +#define GAME_SOUND_TYPE_H + +namespace MWSound +{ + enum class Type + { + Sfx = 1 << 4, /* Normal SFX sound */ + Voice = 1 << 5, /* Voice sound */ + Foot = 1 << 6, /* Footstep sound */ + Music = 1 << 7, /* Music track */ + Movie = 1 << 8, /* Movie audio track */ + Mask = Sfx | Voice | Foot | Music | Movie + }; +} + +#endif diff --git a/apps/openmw/mwsound/volumesettings.cpp b/apps/openmw/mwsound/volumesettings.cpp new file mode 100644 index 000000000..cc4eac3d6 --- /dev/null +++ b/apps/openmw/mwsound/volumesettings.cpp @@ -0,0 +1,56 @@ +#include "volumesettings.hpp" + +#include + +#include + +namespace MWSound +{ + namespace + { + float clamp(float value) + { + return std::max(0.0f, std::min(1.0f, value)); + } + } + + VolumeSettings::VolumeSettings() + : mMasterVolume(clamp(Settings::Manager::getFloat("master volume", "Sound"))), + mSFXVolume(clamp(Settings::Manager::getFloat("sfx volume", "Sound"))), + mMusicVolume(clamp(Settings::Manager::getFloat("music volume", "Sound"))), + mVoiceVolume(clamp(Settings::Manager::getFloat("voice volume", "Sound"))), + mFootstepsVolume(clamp(Settings::Manager::getFloat("footsteps volume", "Sound"))) + { + } + + float VolumeSettings::getVolumeFromType(Type type) const + { + float volume = mMasterVolume; + + switch(type) + { + case Type::Sfx: + volume *= mSFXVolume; + break; + case Type::Voice: + volume *= mVoiceVolume; + break; + case Type::Foot: + volume *= mFootstepsVolume; + break; + case Type::Music: + volume *= mMusicVolume; + break; + case Type::Movie: + case Type::Mask: + break; + } + + return volume; + } + + void VolumeSettings::update() + { + *this = VolumeSettings(); + } +} diff --git a/apps/openmw/mwsound/volumesettings.hpp b/apps/openmw/mwsound/volumesettings.hpp new file mode 100644 index 000000000..eec5f5c1b --- /dev/null +++ b/apps/openmw/mwsound/volumesettings.hpp @@ -0,0 +1,26 @@ +#ifndef GAME_SOUND_VOLUMESETTINGS_H +#define GAME_SOUND_VOLUMESETTINGS_H + +#include "type.hpp" + +namespace MWSound +{ + class VolumeSettings + { + public: + VolumeSettings(); + + float getVolumeFromType(Type type) const; + + void update(); + + private: + float mMasterVolume; + float mSFXVolume; + float mMusicVolume; + float mVoiceVolume; + float mFootstepsVolume; + }; +} + +#endif From e9126fae54ddd3c7540cf9913b98fb5066913ed7 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 2 Jul 2020 12:36:25 +0200 Subject: [PATCH 029/107] Resolve #5509 where culling did not take invisiblity into accont --- apps/openmw/mwrender/animation.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 69136bac3..aa12d7adb 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1481,10 +1481,10 @@ namespace MWRender void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature) { osg::ref_ptr previousStateset; + osg::ref_ptr previousCullCallback; if (mObjectRoot) { - if (mLightListCallback) - mObjectRoot->removeCullCallback(mLightListCallback); + previousCullCallback = mObjectRoot->getCullCallback(); previousStateset = mObjectRoot->getStateSet(); mObjectRoot->getParent(0)->removeChild(mObjectRoot); } @@ -1573,9 +1573,9 @@ namespace MWRender removeTriBipVisitor.remove(); } - if (!mLightListCallback) - mLightListCallback = new SceneUtil::LightListCallback; - mObjectRoot->addCullCallback(mLightListCallback); + if (!previousCullCallback) + previousCullCallback = mLightListCallback; + mObjectRoot->setCullCallback(previousCullCallback); } osg::Group* Animation::getObjectRoot() From 8f9de7289d872004458d74bd34c1b0a4731a6adf Mon Sep 17 00:00:00 2001 From: Dillon Date: Thu, 2 Jul 2020 13:48:56 +0000 Subject: [PATCH 030/107] fix typos --- files/ui/advancedpage.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index fed547b8c..03b011b47 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -442,7 +442,7 @@ - <html><head/><body><p>If this setting is true, melee weapons reach and speed will be showed on item tooltip.</p><p>The default value is false.</p></body></html> + <html><head/><body><p>If this setting is true, melee weapons reach and speed will be shown on item tooltip.</p><p>The default value is false.</p></body></html> Show melee info @@ -452,7 +452,7 @@ - <html><head/><body><p>If this setting is true, damage bonus of arrows and bolts will be showed on item tooltip.</p><p>The default value is false.</p></body></html> + <html><head/><body><p>If this setting is true, damage bonus of arrows and bolts will be shown on item tooltip.</p><p>The default value is false.</p></body></html> Show projectile damage @@ -462,7 +462,7 @@ - <html><head/><body><p>If this setting is true, dialogue topics will have a different color if the topic is specific to the NPC you're talking to or the topic was previously seen. Color can be change in settings.cfg.</p><p>The default value is false.</p></body></html> + <html><head/><body><p>If this setting is true, dialogue topics will have a different color if the topic is specific to the NPC you're talking to or the topic was previously seen. Color can be changed in settings.cfg.</p><p>The default value is false.</p></body></html> Change dialogue topic color From 3fa1e7ebafc090727eb7da1410b44de863c74bd9 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 13:49:05 +0200 Subject: [PATCH 031/107] Make time passed SoundManager field --- apps/openmw/mwsound/soundmanagerimp.cpp | 12 ++++++------ apps/openmw/mwsound/soundmanagerimp.hpp | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index a1eb59bac..42c8d9065 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -32,6 +32,8 @@ namespace MWSound { namespace { + constexpr float sMinUpdateInterval = 1.0f / 30.0f; + WaterSoundUpdaterSettings makeWaterSoundUpdaterSettings() { WaterSoundUpdaterSettings settings; @@ -946,13 +948,11 @@ namespace MWSound mSaySoundsQueue.erase(queuesayiter++); } - static float timePassed = 0.0; - - timePassed += duration; - if(timePassed < (1.0f/30.0f)) + mTimePassed += duration; + if (mTimePassed < sMinUpdateInterval) return; - duration = timePassed; - timePassed = 0.0f; + duration = mTimePassed; + mTimePassed = 0.0f; // Make sure music is still playing if(!isMusicPlaying() && !mCurrentPlaylist.empty()) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index c79f9abe5..b3d43dc88 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -114,6 +114,8 @@ namespace MWSound RegionSoundSelector mRegionSoundSelector; + float mTimePassed = 0; + Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound); Sound_Buffer *lookupSound(const std::string &soundId) const; From 6ab1a1f9073ac4fed68ad4b034818dcd8f036dc7 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 14:52:50 +0200 Subject: [PATCH 032/107] Make last cell a field of SoundManager and initialize --- apps/openmw/mwsound/soundmanagerimp.cpp | 7 +++---- apps/openmw/mwsound/soundmanagerimp.hpp | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 42c8d9065..be7c68e64 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -887,7 +887,6 @@ namespace MWSound void SoundManager::updateWaterSound(float /*duration*/) { - static const ESM::Cell *LastCell; MWBase::World* world = MWBase::Environment::get().getWorld(); const MWWorld::ConstPtr player = world->getPlayerPtr(); const ESM::Cell *curcell = player.getCell()->getCell(); @@ -905,9 +904,9 @@ namespace MWSound bool soundIdChanged = false; Sound_Buffer *sfx = lookupSound(update.mId); - if(LastCell != curcell) + if (mLastCell != curcell) { - LastCell = curcell; + mLastCell = curcell; SoundMap::const_iterator snditer = mActiveSounds.find(MWWorld::Ptr()); if(snditer != mActiveSounds.end()) { @@ -932,7 +931,7 @@ namespace MWSound } else if (update.mVolume > 0.0f) { - LastCell = curcell; + mLastCell = curcell; mNearWaterSound = playSound(update.mId, update.mVolume, 1.0f, Type::Sfx, PlayMode::Loop); } } diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index b3d43dc88..85aa0a386 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -27,6 +27,7 @@ namespace VFS namespace ESM { struct Sound; + struct Cell; } namespace MWSound @@ -116,6 +117,8 @@ namespace MWSound float mTimePassed = 0; + const ESM::Cell *mLastCell = nullptr; + Sound_Buffer *insertSound(const std::string &soundId, const ESM::Sound *sound); Sound_Buffer *lookupSound(const std::string &soundId) const; From d3c24a6ea404ec9e0b2336ac6ed18558ff8737d6 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 2 Jul 2020 22:01:42 +0200 Subject: [PATCH 033/107] Should resolve the original cause of #5509 and prevent mesh from growing while switching back and for from 3rd and 1st person view --- apps/openmw/mwrender/animation.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index aa12d7adb..688937ce9 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1481,10 +1481,12 @@ namespace MWRender void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature) { osg::ref_ptr previousStateset; - osg::ref_ptr previousCullCallback; if (mObjectRoot) { - previousCullCallback = mObjectRoot->getCullCallback(); + if (mLightListCallback) + mObjectRoot->removeCullCallback(mLightListCallback); + if (mTransparencyUpdater) + mObjectRoot->removeCullCallback(mTransparencyUpdater); previousStateset = mObjectRoot->getStateSet(); mObjectRoot->getParent(0)->removeChild(mObjectRoot); } @@ -1573,9 +1575,11 @@ namespace MWRender removeTriBipVisitor.remove(); } - if (!previousCullCallback) - previousCullCallback = mLightListCallback; - mObjectRoot->setCullCallback(previousCullCallback); + if (!mLightListCallback) + mLightListCallback = new SceneUtil::LightListCallback; + mObjectRoot->addCullCallback(mLightListCallback); + if (mTransparencyUpdater) + mObjectRoot->addCullCallback(mTransparencyUpdater); } osg::Group* Animation::getObjectRoot() From 56bc462007a5963cfd716f765b007c0ec74bf486 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 3 Jul 2020 20:42:51 +0200 Subject: [PATCH 034/107] Make all stats fit into the window --- components/resource/stats.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/resource/stats.cpp b/components/resource/stats.cpp index 2dda2c2df..147970add 100644 --- a/components/resource/stats.cpp +++ b/components/resource/stats.cpp @@ -25,7 +25,7 @@ StatsHandler::StatsHandler(): _statsWidth(1280.0f), _statsHeight(1024.0f), _font(""), - _characterSize(20.0f) + _characterSize(18.0f) { _camera = new osg::Camera; _camera->getOrCreateStateSet()->setGlobalDefaults(); @@ -45,6 +45,8 @@ Profiler::Profiler() else _font = ""; + _characterSize = 18; + setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_F3); } From 080b0d63193951efee66df657c6d7720009ac48f Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 13:50:02 +0200 Subject: [PATCH 035/107] Remove unused duration from updateWaterSound --- apps/openmw/mwsound/soundmanagerimp.cpp | 4 ++-- apps/openmw/mwsound/soundmanagerimp.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index be7c68e64..e340138c6 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -885,7 +885,7 @@ namespace MWSound playSound(*next, 1.0f, 1.0f); } - void SoundManager::updateWaterSound(float /*duration*/) + void SoundManager::updateWaterSound() { MWBase::World* world = MWBase::Environment::get().getWorld(); const MWWorld::ConstPtr player = world->getPlayerPtr(); @@ -1115,7 +1115,7 @@ namespace MWSound MWBase::StateManager::State_NoGame) { updateRegionSound(duration); - updateWaterSound(duration); + updateWaterSound(); } } diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 85aa0a386..fc1687386 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -138,7 +138,7 @@ namespace MWSound void updateSounds(float duration); void updateRegionSound(float duration); - void updateWaterSound(float duration); + void updateWaterSound(); void updateMusic(float duration); float volumeFromType(Type type) const; From b424aac25ea5892c1fa7a231345d2009671fea65 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 15:38:30 +0200 Subject: [PATCH 036/107] Choose next action for water sound in a separate function --- apps/openmw/mwsound/soundmanagerimp.cpp | 83 +++++++++++++++---------- apps/openmw/mwsound/soundmanagerimp.hpp | 11 ++++ 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index e340138c6..3f21487bc 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -892,48 +892,67 @@ namespace MWSound const ESM::Cell *curcell = player.getCell()->getCell(); const auto update = mWaterSoundUpdater.update(player, *world); + WaterSoundAction action; + Sound_Buffer* sfx; + std::tie(action, sfx) = getWaterSoundAction(update, curcell); + + switch (action) + { + case WaterSoundAction::DoNothing: + break; + case WaterSoundAction::SetVolume: + mNearWaterSound->setVolume(update.mVolume * sfx->mVolume); + break; + case WaterSoundAction::FinishSound: + mOutput->finishSound(mNearWaterSound); + mNearWaterSound = nullptr; + break; + case WaterSoundAction::PlaySound: + if (mNearWaterSound) + mOutput->finishSound(mNearWaterSound); + mNearWaterSound = playSound(update.mId, update.mVolume, 1.0f, Type::Sfx, PlayMode::Loop); + break; + } + + mLastCell = curcell; + } + + std::pair SoundManager::getWaterSoundAction( + const WaterSoundUpdate& update, const ESM::Cell* cell) const + { if (mNearWaterSound) { if (update.mVolume == 0.0f) - { - mOutput->finishSound(mNearWaterSound); - mNearWaterSound = nullptr; - } - else - { - bool soundIdChanged = false; + return {WaterSoundAction::FinishSound, nullptr}; - Sound_Buffer *sfx = lookupSound(update.mId); - if (mLastCell != curcell) - { - mLastCell = curcell; - SoundMap::const_iterator snditer = mActiveSounds.find(MWWorld::Ptr()); - if(snditer != mActiveSounds.end()) - { - SoundBufferRefPairList::const_iterator pairiter = std::find_if( - snditer->second.begin(), snditer->second.end(), - [this](const SoundBufferRefPairList::value_type &item) -> bool - { return mNearWaterSound == item.first; } - ); - if (pairiter != snditer->second.end() && pairiter->second != sfx) - soundIdChanged = true; - } - } + bool soundIdChanged = false; - if(soundIdChanged) + Sound_Buffer* sfx = lookupSound(update.mId); + if (mLastCell != cell) + { + const auto snditer = mActiveSounds.find(MWWorld::ConstPtr()); + if (snditer != mActiveSounds.end()) { - mOutput->finishSound(mNearWaterSound); - mNearWaterSound = playSound(update.mId, update.mVolume, 1.0f, Type::Sfx, PlayMode::Loop); + const auto pairiter = std::find_if( + snditer->second.begin(), snditer->second.end(), + [this](const SoundBufferRefPairList::value_type &item) -> bool + { return mNearWaterSound == item.first; } + ); + if (pairiter != snditer->second.end() && pairiter->second != sfx) + soundIdChanged = true; } - else if (sfx) - mNearWaterSound->setVolume(update.mVolume * sfx->mVolume); } + + if (soundIdChanged) + return {WaterSoundAction::PlaySound, nullptr}; + + if (sfx) + return {WaterSoundAction::SetVolume, sfx}; } else if (update.mVolume > 0.0f) - { - mLastCell = curcell; - mNearWaterSound = playSound(update.mId, update.mVolume, 1.0f, Type::Sfx, PlayMode::Loop); - } + return {WaterSoundAction::PlaySound, nullptr}; + + return {WaterSoundAction::DoNothing, nullptr}; } void SoundManager::updateSounds(float duration) diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index fc1687386..90bf4b12c 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -143,6 +143,17 @@ namespace MWSound float volumeFromType(Type type) const; + enum class WaterSoundAction + { + DoNothing, + SetVolume, + FinishSound, + PlaySound, + }; + + std::pair getWaterSoundAction(const WaterSoundUpdate& update, + const ESM::Cell* cell) const; + SoundManager(const SoundManager &rhs); SoundManager& operator=(const SoundManager &rhs); From 3ea576efdc014e89258b77d3d1037f8f18297f51 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 3 Jul 2020 23:24:54 +0200 Subject: [PATCH 037/107] do not build a few things; temporary disable checking package; get things compiling and cached first --- .travis.yml | 2 +- CI/before_install.osx.sh | 2 -- CI/before_script.osx.sh | 3 +++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5fec5a830..cfc449434 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,7 @@ script: - cd ./build - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ${ANALYZE} make -j3; fi - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi +# - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi - cd "${TRAVIS_BUILD_DIR}" diff --git a/CI/before_install.osx.sh b/CI/before_install.osx.sh index 0f69ecb39..5dae1f102 100755 --- a/CI/before_install.osx.sh +++ b/CI/before_install.osx.sh @@ -1,7 +1,5 @@ #!/bin/sh -e -brew update -brew outdated pkgconfig || brew upgrade pkgconfig brew install ccache curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-ef2462c.zip -o ~/openmw-deps.zip diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index 7ba21b23b..7438c6c7a 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -18,5 +18,8 @@ cmake \ -D CMAKE_BUILD_TYPE=DEBUG \ -D OPENMW_OSX_DEPLOYMENT=TRUE \ -D BUILD_ESMTOOL=FALSE \ +-D BUILD_BSATOOL=FALSE \ +-D BUILD_ESSIMPORTER=FALSE \ +-D BUILD_NIFTEST=FALSE \ -G"Unix Makefiles" \ .. From 6ca29c610740b9ab4c1fd96720de95c1919447c2 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 17:17:43 +0200 Subject: [PATCH 038/107] Use common type for pool of sounds and streams --- apps/openmw/mwsound/soundmanagerimp.cpp | 58 ++++++++----------------- apps/openmw/mwsound/soundmanagerimp.hpp | 8 ++-- components/misc/objectpool.hpp | 46 ++++++++++++++++++++ 3 files changed, 66 insertions(+), 46 deletions(-) create mode 100644 components/misc/objectpool.hpp diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 3f21487bc..71ed96ac9 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -58,8 +58,6 @@ namespace MWSound , mWaterSoundUpdater(makeWaterSoundUpdaterSettings()) , mSoundBuffers(new SoundBufferList::element_type()) , mBufferCacheSize(0) - , mSounds(new std::deque()) - , mStreams(new std::deque()) , mMusic(nullptr) , mListenerUnderwater(false) , mListenerPos(0,0,0) @@ -270,34 +268,12 @@ namespace MWSound Sound *SoundManager::getSoundRef() { - Sound *ret; - if(!mUnusedSounds.empty()) - { - ret = mUnusedSounds.back(); - mUnusedSounds.pop_back(); - } - else - { - mSounds->emplace_back(); - ret = &mSounds->back(); - } - return ret; + return mSounds.get(); } Stream *SoundManager::getStreamRef() { - Stream *ret; - if(!mUnusedStreams.empty()) - { - ret = mUnusedStreams.back(); - mUnusedStreams.pop_back(); - } - else - { - mStreams->emplace_back(); - ret = &mStreams->back(); - } - return ret; + return mStreams.get(); } Stream *SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal) @@ -326,7 +302,7 @@ namespace MWSound } if(!played) { - mUnusedStreams.push_back(sound); + mStreams.recycle(sound); return nullptr; } return sound; @@ -343,7 +319,7 @@ namespace MWSound if(mMusic) { mOutput->finishStream(mMusic); - mUnusedStreams.push_back(mMusic); + mStreams.recycle(mMusic); mMusic = nullptr; } } @@ -572,7 +548,7 @@ namespace MWSound if(snditer != mSaySoundsQueue.end()) { mOutput->finishStream(snditer->second); - mUnusedStreams.push_back(snditer->second); + mStreams.recycle(snditer->second); mSaySoundsQueue.erase(snditer); } @@ -580,7 +556,7 @@ namespace MWSound if(snditer != mActiveSaySounds.end()) { mOutput->finishStream(snditer->second); - mUnusedStreams.push_back(snditer->second); + mStreams.recycle(snditer->second); mActiveSaySounds.erase(snditer); } } @@ -595,7 +571,7 @@ namespace MWSound track->init(1.0f, volumeFromType(type), 1.0f, PlayMode::NoEnv|type|Play_2D); if(!mOutput->streamSound(decoder, track)) { - mUnusedStreams.push_back(track); + mStreams.recycle(track); return nullptr; } @@ -611,7 +587,7 @@ namespace MWSound TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream); if(iter != mActiveTracks.end() && *iter == stream) mActiveTracks.erase(iter); - mUnusedStreams.push_back(stream); + mStreams.recycle(stream); } double SoundManager::getTrackTimeDelay(Stream *stream) @@ -635,7 +611,7 @@ namespace MWSound sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); if(!mOutput->playSound(sound, sfx->mHandle, offset)) { - mUnusedSounds.push_back(sound); + mSounds.recycle(sound); return nullptr; } @@ -682,7 +658,7 @@ namespace MWSound } if(!played) { - mUnusedSounds.push_back(sound); + mSounds.recycle(sound); return nullptr; } @@ -712,7 +688,7 @@ namespace MWSound sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); if(!mOutput->playSound3D(sound, sfx->mHandle, offset)) { - mUnusedSounds.push_back(sound); + mSounds.recycle(sound); return nullptr; } @@ -1023,7 +999,7 @@ namespace MWSound if(!mOutput->isSoundPlaying(sound)) { mOutput->finishSound(sound); - mUnusedSounds.push_back(sound); + mSounds.recycle(sound); if(sound == mUnderwaterSound) mUnderwaterSound = nullptr; if(sound == mNearWaterSound) @@ -1067,7 +1043,7 @@ namespace MWSound if(!mOutput->isStreamPlaying(sound)) { mOutput->finishStream(sound); - mUnusedStreams.push_back(sound); + mStreams.recycle(sound); mActiveSaySounds.erase(sayiter++); } else @@ -1292,7 +1268,7 @@ namespace MWSound for(SoundBufferRefPair &sndbuf : snd.second) { mOutput->finishSound(sndbuf.first); - mUnusedSounds.push_back(sndbuf.first); + mSounds.recycle(sndbuf.first); Sound_Buffer *sfx = sndbuf.second; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); @@ -1305,21 +1281,21 @@ namespace MWSound for(SaySoundMap::value_type &snd : mSaySoundsQueue) { mOutput->finishStream(snd.second); - mUnusedStreams.push_back(snd.second); + mStreams.recycle(snd.second); } mSaySoundsQueue.clear(); for(SaySoundMap::value_type &snd : mActiveSaySounds) { mOutput->finishStream(snd.second); - mUnusedStreams.push_back(snd.second); + mStreams.recycle(snd.second); } mActiveSaySounds.clear(); for(Stream *sound : mActiveTracks) { mOutput->finishStream(sound); - mUnusedStreams.push_back(sound); + mStreams.recycle(sound); } mActiveTracks.clear(); mPlaybackPaused = false; diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index 90bf4b12c..e03bd7b1f 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -9,7 +9,7 @@ #include #include - +#include #include #include "../mwbase/soundmanager.hpp" @@ -79,11 +79,9 @@ namespace MWSound typedef std::deque SoundList; SoundList mUnusedBuffers; - std::unique_ptr> mSounds; - std::vector mUnusedSounds; + Misc::ObjectPool mSounds; - std::unique_ptr> mStreams; - std::vector mUnusedStreams; + Misc::ObjectPool mStreams; typedef std::pair SoundBufferRefPair; typedef std::vector SoundBufferRefPairList; diff --git a/components/misc/objectpool.hpp b/components/misc/objectpool.hpp new file mode 100644 index 000000000..97a055331 --- /dev/null +++ b/components/misc/objectpool.hpp @@ -0,0 +1,46 @@ +#ifndef OPENMW_COMPONENTS_MISC_OBJECTPOOL_H +#define OPENMW_COMPONENTS_MISC_OBJECTPOOL_H + +#include +#include +#include + +namespace Misc +{ + template + class ObjectPool + { + public: + ObjectPool() + : mObjects(std::make_unique>()) {} + + T* get() + { + T* object; + + if (!mUnused.empty()) + { + object = mUnused.back(); + mUnused.pop_back(); + } + else + { + mObjects->emplace_back(); + object = &mObjects->back(); + } + + return object; + } + + void recycle(T* object) + { + mUnused.push_back(object); + } + + private: + std::unique_ptr> mObjects; + std::vector mUnused; + }; +} + +#endif From 02f9b44f01b8ab052b9381b1757ce818d7052277 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 18:25:23 +0200 Subject: [PATCH 039/107] Use RAII for object ptr from pool --- apps/openmw/mwsound/soundmanagerimp.cpp | 187 ++++++++++-------------- apps/openmw/mwsound/soundmanagerimp.hpp | 17 ++- components/misc/objectpool.hpp | 49 ++++++- 3 files changed, 134 insertions(+), 119 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 71ed96ac9..eed935e61 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -58,7 +58,6 @@ namespace MWSound , mWaterSoundUpdater(makeWaterSoundUpdaterSettings()) , mSoundBuffers(new SoundBufferList::element_type()) , mBufferCacheSize(0) - , mMusic(nullptr) , mListenerUnderwater(false) , mListenerPos(0,0,0) , mListenerDir(1,0,0) @@ -266,17 +265,17 @@ namespace MWSound return nullptr; } - Sound *SoundManager::getSoundRef() + SoundPtr SoundManager::getSoundRef() { return mSounds.get(); } - Stream *SoundManager::getStreamRef() + StreamPtr SoundManager::getStreamRef() { return mStreams.get(); } - Stream *SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal) + StreamPtr SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal) { MWBase::World* world = MWBase::Environment::get().getWorld(); static const float fAudioMinDistanceMult = world->getStore().get().find("fAudioMinDistanceMult")->mValue.getFloat(); @@ -288,23 +287,20 @@ namespace MWSound bool played; float basevol = volumeFromType(Type::Voice); - Stream *sound = getStreamRef(); + StreamPtr sound = getStreamRef(); if(playlocal) { sound->init(1.0f, basevol, 1.0f, PlayMode::NoEnv|Type::Voice|Play_2D); - played = mOutput->streamSound(decoder, sound, true); + played = mOutput->streamSound(decoder, sound.get(), true); } else { sound->init(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, PlayMode::Normal|Type::Voice|Play_3D); - played = mOutput->streamSound3D(decoder, sound, true); + played = mOutput->streamSound3D(decoder, sound.get(), true); } if(!played) - { - mStreams.recycle(sound); return nullptr; - } return sound; } @@ -318,8 +314,7 @@ namespace MWSound { if(mMusic) { - mOutput->finishStream(mMusic); - mStreams.recycle(mMusic); + mOutput->finishStream(mMusic.get()); mMusic = nullptr; } } @@ -339,7 +334,7 @@ namespace MWSound mMusic = getStreamRef(); mMusic->init(1.0f, volumeFromType(Type::Music), 1.0f, PlayMode::NoEnv|Type::Music|Play_2D); - mOutput->streamSound(decoder, mMusic); + mOutput->streamSound(decoder, mMusic.get()); } void SoundManager::advanceMusic(const std::string& filename) @@ -389,7 +384,7 @@ namespace MWSound bool SoundManager::isMusicPlaying() { - return mMusic && mOutput->isStreamPlaying(mMusic); + return mMusic && mOutput->isStreamPlaying(mMusic.get()); } void SoundManager::playPlaylist(const std::string &playlist) @@ -472,10 +467,10 @@ namespace MWSound const osg::Vec3f pos = world->getActorHeadTransform(ptr).getTrans(); stopSay(ptr); - Stream *sound = playVoice(decoder, pos, (ptr == MWMechanics::getPlayer())); + StreamPtr sound = playVoice(decoder, pos, (ptr == MWMechanics::getPlayer())); if(!sound) return; - mSaySoundsQueue.emplace(ptr, sound); + mSaySoundsQueue.emplace(ptr, std::move(sound)); } float SoundManager::getSaySoundLoudness(const MWWorld::ConstPtr &ptr) const @@ -483,7 +478,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - Stream *sound = snditer->second; + Stream *sound = snditer->second.get(); return mOutput->getStreamLoudness(sound); } @@ -503,10 +498,10 @@ namespace MWSound return; stopSay(MWWorld::ConstPtr()); - Stream *sound = playVoice(decoder, osg::Vec3f(), true); + StreamPtr sound = playVoice(decoder, osg::Vec3f(), true); if(!sound) return; - mActiveSaySounds.insert(std::make_pair(MWWorld::ConstPtr(), sound)); + mActiveSaySounds.emplace(MWWorld::ConstPtr(), std::move(sound)); } bool SoundManager::sayDone(const MWWorld::ConstPtr &ptr) const @@ -514,7 +509,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - if(mOutput->isStreamPlaying(snditer->second)) + if(mOutput->isStreamPlaying(snditer->second.get())) return false; return true; } @@ -526,7 +521,7 @@ namespace MWSound SaySoundMap::const_iterator snditer = mSaySoundsQueue.find(ptr); if(snditer != mSaySoundsQueue.end()) { - if(mOutput->isStreamPlaying(snditer->second)) + if(mOutput->isStreamPlaying(snditer->second.get())) return true; return false; } @@ -534,7 +529,7 @@ namespace MWSound snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - if(mOutput->isStreamPlaying(snditer->second)) + if(mOutput->isStreamPlaying(snditer->second.get())) return true; return false; } @@ -547,16 +542,14 @@ namespace MWSound SaySoundMap::iterator snditer = mSaySoundsQueue.find(ptr); if(snditer != mSaySoundsQueue.end()) { - mOutput->finishStream(snditer->second); - mStreams.recycle(snditer->second); + mOutput->finishStream(snditer->second.get()); mSaySoundsQueue.erase(snditer); } snditer = mActiveSaySounds.find(ptr); if(snditer != mActiveSaySounds.end()) { - mOutput->finishStream(snditer->second); - mStreams.recycle(snditer->second); + mOutput->finishStream(snditer->second.get()); mActiveSaySounds.erase(snditer); } } @@ -567,27 +560,24 @@ namespace MWSound if(!mOutput->isInitialized()) return nullptr; - Stream *track = getStreamRef(); + StreamPtr track = getStreamRef(); track->init(1.0f, volumeFromType(type), 1.0f, PlayMode::NoEnv|type|Play_2D); - if(!mOutput->streamSound(decoder, track)) - { - mStreams.recycle(track); + if(!mOutput->streamSound(decoder, track.get())) return nullptr; - } - mActiveTracks.insert( - std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track), track - ); - return track; + Stream* result = track.get(); + const auto it = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), track); + mActiveTracks.insert(it, std::move(track)); + return result; } void SoundManager::stopTrack(Stream *stream) { mOutput->finishStream(stream); - TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream); - if(iter != mActiveTracks.end() && *iter == stream) + TrackList::iterator iter = std::lower_bound(mActiveTracks.begin(), mActiveTracks.end(), stream, + [] (const StreamPtr& lhs, Stream* rhs) { return lhs.get() < rhs; }); + if(iter != mActiveTracks.end() && iter->get() == stream) mActiveTracks.erase(iter); - mStreams.recycle(stream); } double SoundManager::getTrackTimeDelay(Stream *stream) @@ -596,7 +586,7 @@ namespace MWSound } - Sound *SoundManager::playSound(const std::string& soundId, float volume, float pitch, Type type, PlayMode mode, float offset) + Sound* SoundManager::playSound(const std::string& soundId, float volume, float pitch, Type type, PlayMode mode, float offset) { if(!mOutput->isInitialized()) return nullptr; @@ -607,13 +597,10 @@ namespace MWSound // Only one copy of given sound can be played at time, so stop previous copy stopSound(sfx, MWWorld::ConstPtr()); - Sound *sound = getSoundRef(); + SoundPtr sound = getSoundRef(); sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); - if(!mOutput->playSound(sound, sfx->mHandle, offset)) - { - mSounds.recycle(sound); + if(!mOutput->playSound(sound.get(), sfx->mHandle, offset)) return nullptr; - } if(sfx->mUses++ == 0) { @@ -621,8 +608,9 @@ namespace MWSound if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[MWWorld::ConstPtr()].push_back(std::make_pair(sound, sfx)); - return sound; + Sound* result = sound.get(); + mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx); + return result; } Sound *SoundManager::playSound3D(const MWWorld::ConstPtr &ptr, const std::string& soundId, @@ -644,23 +632,20 @@ namespace MWSound stopSound(sfx, ptr); bool played; - Sound *sound = getSoundRef(); + SoundPtr sound = getSoundRef(); if(!(mode&PlayMode::NoPlayerLocal) && ptr == MWMechanics::getPlayer()) { sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); - played = mOutput->playSound(sound, sfx->mHandle, offset); + played = mOutput->playSound(sound.get(), sfx->mHandle, offset); } else { sound->init(objpos, volume * sfx->mVolume, volumeFromType(type), pitch, sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); - played = mOutput->playSound3D(sound, sfx->mHandle, offset); + played = mOutput->playSound3D(sound.get(), sfx->mHandle, offset); } if(!played) - { - mSounds.recycle(sound); return nullptr; - } if(sfx->mUses++ == 0) { @@ -668,8 +653,9 @@ namespace MWSound if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[ptr].push_back(std::make_pair(sound, sfx)); - return sound; + Sound* result = sound.get(); + mActiveSounds[ptr].emplace_back(std::move(sound), sfx); + return result; } Sound *SoundManager::playSound3D(const osg::Vec3f& initialPos, const std::string& soundId, @@ -683,14 +669,11 @@ namespace MWSound Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); if(!sfx) return nullptr; - Sound *sound = getSoundRef(); + SoundPtr sound = getSoundRef(); sound->init(initialPos, volume * sfx->mVolume, volumeFromType(type), pitch, sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); - if(!mOutput->playSound3D(sound, sfx->mHandle, offset)) - { - mSounds.recycle(sound); + if(!mOutput->playSound3D(sound.get(), sfx->mHandle, offset)) return nullptr; - } if(sfx->mUses++ == 0) { @@ -698,8 +681,9 @@ namespace MWSound if(iter != mUnusedBuffers.end()) mUnusedBuffers.erase(iter); } - mActiveSounds[MWWorld::ConstPtr()].push_back(std::make_pair(sound, sfx)); - return sound; + Sound* result = sound.get(); + mActiveSounds[MWWorld::ConstPtr()].emplace_back(std::move(sound), sfx); + return result; } void SoundManager::stopSound(Sound *sound) @@ -716,7 +700,7 @@ namespace MWSound for(SoundBufferRefPair &snd : snditer->second) { if(snd.second == sfx) - mOutput->finishSound(snd.first); + mOutput->finishSound(snd.first.get()); } } } @@ -738,14 +722,14 @@ namespace MWSound if(snditer != mActiveSounds.end()) { for(SoundBufferRefPair &snd : snditer->second) - mOutput->finishSound(snd.first); + mOutput->finishSound(snd.first.get()); } SaySoundMap::iterator sayiter = mSaySoundsQueue.find(ptr); if(sayiter != mSaySoundsQueue.end()) - mOutput->finishStream(sayiter->second); + mOutput->finishStream(sayiter->second.get()); sayiter = mActiveSaySounds.find(ptr); if(sayiter != mActiveSaySounds.end()) - mOutput->finishStream(sayiter->second); + mOutput->finishStream(sayiter->second.get()); } void SoundManager::stopSound(const MWWorld::CellStore *cell) @@ -755,20 +739,20 @@ namespace MWSound if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) { for(SoundBufferRefPair &sndbuf : snd.second) - mOutput->finishSound(sndbuf.first); + mOutput->finishSound(sndbuf.first.get()); } } for(SaySoundMap::value_type &snd : mSaySoundsQueue) { if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) - mOutput->finishStream(snd.second); + mOutput->finishStream(snd.second.get()); } for(SaySoundMap::value_type &snd : mActiveSaySounds) { if(!snd.first.isEmpty() && snd.first != MWMechanics::getPlayer() && snd.first.getCell() == cell) - mOutput->finishStream(snd.second); + mOutput->finishStream(snd.second.get()); } } @@ -795,7 +779,7 @@ namespace MWSound Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); return std::find_if(snditer->second.cbegin(), snditer->second.cend(), [this,sfx](const SoundBufferRefPair &snd) -> bool - { return snd.second == sfx && mOutput->isSoundPlaying(snd.first); } + { return snd.second == sfx && mOutput->isSoundPlaying(snd.first.get()); } ) != snditer->second.cend(); } return false; @@ -912,7 +896,7 @@ namespace MWSound const auto pairiter = std::find_if( snditer->second.begin(), snditer->second.end(), [this](const SoundBufferRefPairList::value_type &item) -> bool - { return mNearWaterSound == item.first; } + { return mNearWaterSound == item.first.get(); } ); if (pairiter != snditer->second.end() && pairiter->second != sfx) soundIdChanged = true; @@ -938,7 +922,11 @@ namespace MWSound SaySoundMap::iterator queuesayiter = mSaySoundsQueue.begin(); while (queuesayiter != mSaySoundsQueue.end()) { - mActiveSaySounds[queuesayiter->first] = queuesayiter->second; + const auto dst = mActiveSaySounds.find(queuesayiter->first); + if (dst == mActiveSaySounds.end()) + mActiveSaySounds.emplace(queuesayiter->first, std::move(queuesayiter->second)); + else + dst->second = std::move(queuesayiter->second); mSaySoundsQueue.erase(queuesayiter++); } @@ -979,10 +967,9 @@ namespace MWSound SoundBufferRefPairList::iterator sndidx = snditer->second.begin(); while(sndidx != snditer->second.end()) { - Sound *sound; - Sound_Buffer *sfx; + Sound *sound = sndidx->first.get(); + Sound_Buffer *sfx = sndidx->second; - std::tie(sound, sfx) = *sndidx; if(!ptr.isEmpty() && sound->getIs3D()) { const ESM::Position &pos = ptr.getRefData().getPosition(); @@ -999,10 +986,9 @@ namespace MWSound if(!mOutput->isSoundPlaying(sound)) { mOutput->finishSound(sound); - mSounds.recycle(sound); - if(sound == mUnderwaterSound) + if (sound == mUnderwaterSound) mUnderwaterSound = nullptr; - if(sound == mNearWaterSound) + if (sound == mNearWaterSound) mNearWaterSound = nullptr; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); @@ -1026,7 +1012,7 @@ namespace MWSound while(sayiter != mActiveSaySounds.end()) { MWWorld::ConstPtr ptr = sayiter->first; - Stream *sound = sayiter->second; + Stream *sound = sayiter->second.get(); if(!ptr.isEmpty() && sound->getIs3D()) { MWBase::World *world = MWBase::Environment::get().getWorld(); @@ -1043,7 +1029,6 @@ namespace MWSound if(!mOutput->isStreamPlaying(sound)) { mOutput->finishStream(sound); - mStreams.recycle(sound); mActiveSaySounds.erase(sayiter++); } else @@ -1058,7 +1043,7 @@ namespace MWSound TrackList::iterator trkiter = mActiveTracks.begin(); for(;trkiter != mActiveTracks.end();++trkiter) { - Stream *sound = *trkiter; + Stream *sound = trkiter->get(); if(!mOutput->isStreamPlaying(sound)) { mOutput->finishStream(sound); @@ -1089,7 +1074,7 @@ namespace MWSound { mMusic->updateFade(duration); - mOutput->updateStream(mMusic); + mOutput->updateStream(mMusic.get()); if (mMusic->getRealVolume() <= 0.f) { @@ -1126,32 +1111,32 @@ namespace MWSound { for(SoundBufferRefPair &sndbuf : snd.second) { - Sound *sound = sndbuf.first; + Sound *sound = sndbuf.first.get(); sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateSound(sound); } } for(SaySoundMap::value_type &snd : mActiveSaySounds) { - Stream *sound = snd.second; + Stream *sound = snd.second.get(); sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } for(SaySoundMap::value_type &snd : mSaySoundsQueue) { - Stream *sound = snd.second; + Stream *sound = snd.second.get(); sound->setBaseVolume(volumeFromType(sound->getPlayType())); mOutput->updateStream(sound); } - for(Stream *sound : mActiveTracks) + for (const StreamPtr& sound : mActiveTracks) { sound->setBaseVolume(volumeFromType(sound->getPlayType())); - mOutput->updateStream(sound); + mOutput->updateStream(sound.get()); } if(mMusic) { mMusic->setBaseVolume(volumeFromType(mMusic->getPlayType())); - mOutput->updateStream(mMusic); + mOutput->updateStream(mMusic.get()); } mOutput->finishUpdate(); } @@ -1180,17 +1165,17 @@ namespace MWSound SaySoundMap::iterator sayiter = mSaySoundsQueue.find(old); if(sayiter != mSaySoundsQueue.end()) { - Stream *stream = sayiter->second; + StreamPtr stream = std::move(sayiter->second); mSaySoundsQueue.erase(sayiter); - mSaySoundsQueue.emplace(updated, stream); + mSaySoundsQueue.emplace(updated, std::move(stream)); } sayiter = mActiveSaySounds.find(old); if(sayiter != mActiveSaySounds.end()) { - Stream *stream = sayiter->second; + StreamPtr stream = std::move(sayiter->second); mActiveSaySounds.erase(sayiter); - mActiveSaySounds.emplace(updated, stream); + mActiveSaySounds.emplace(updated, std::move(stream)); } } @@ -1267,8 +1252,7 @@ namespace MWSound { for(SoundBufferRefPair &sndbuf : snd.second) { - mOutput->finishSound(sndbuf.first); - mSounds.recycle(sndbuf.first); + mOutput->finishSound(sndbuf.first.get()); Sound_Buffer *sfx = sndbuf.second; if(sfx->mUses-- == 1) mUnusedBuffers.push_front(sfx); @@ -1279,24 +1263,15 @@ namespace MWSound mNearWaterSound = nullptr; for(SaySoundMap::value_type &snd : mSaySoundsQueue) - { - mOutput->finishStream(snd.second); - mStreams.recycle(snd.second); - } + mOutput->finishStream(snd.second.get()); mSaySoundsQueue.clear(); for(SaySoundMap::value_type &snd : mActiveSaySounds) - { - mOutput->finishStream(snd.second); - mStreams.recycle(snd.second); - } + mOutput->finishStream(snd.second.get()); mActiveSaySounds.clear(); - for(Stream *sound : mActiveTracks) - { - mOutput->finishStream(sound); - mStreams.recycle(sound); - } + for(StreamPtr& sound : mActiveTracks) + mOutput->finishStream(sound.get()); mActiveTracks.clear(); mPlaybackPaused = false; std::fill(std::begin(mPausedSoundTypes), std::end(mPausedSoundTypes), 0); diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp index e03bd7b1f..b3f612d7d 100644 --- a/apps/openmw/mwsound/soundmanagerimp.hpp +++ b/apps/openmw/mwsound/soundmanagerimp.hpp @@ -48,6 +48,9 @@ namespace MWSound Play_3D = 1<<31 }; + using SoundPtr = Misc::ObjectPtr; + using StreamPtr = Misc::ObjectPtr; + class SoundManager : public MWBase::SoundManager { const VFS::Manager* mVFS; @@ -83,19 +86,19 @@ namespace MWSound Misc::ObjectPool mStreams; - typedef std::pair SoundBufferRefPair; + typedef std::pair SoundBufferRefPair; typedef std::vector SoundBufferRefPairList; typedef std::map SoundMap; SoundMap mActiveSounds; - typedef std::map SaySoundMap; + typedef std::map SaySoundMap; SaySoundMap mSaySoundsQueue; SaySoundMap mActiveSaySounds; - typedef std::vector TrackList; + typedef std::vector TrackList; TrackList mActiveTracks; - Stream *mMusic; + StreamPtr mMusic; std::string mCurrentPlaylist; bool mListenerUnderwater; @@ -125,10 +128,10 @@ namespace MWSound // returns a decoder to start streaming, or nullptr if the sound was not found DecoderPtr loadVoice(const std::string &voicefile); - Sound *getSoundRef(); - Stream *getStreamRef(); + SoundPtr getSoundRef(); + StreamPtr getStreamRef(); - Stream *playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); + StreamPtr playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal); void streamMusicFull(const std::string& filename); void advanceMusic(const std::string& filename); diff --git a/components/misc/objectpool.hpp b/components/misc/objectpool.hpp index 97a055331..b3dae6a4f 100644 --- a/components/misc/objectpool.hpp +++ b/components/misc/objectpool.hpp @@ -7,14 +7,51 @@ namespace Misc { + template + class ObjectPool; + + template + class ObjectPtrDeleter + { + public: + ObjectPtrDeleter(std::nullptr_t) + : mPool(nullptr) {} + + ObjectPtrDeleter(ObjectPool& pool) + : mPool(&pool) {} + + void operator()(T* object) const + { + mPool->recycle(object); + } + + private: + ObjectPool* mPool; + }; + + template + struct ObjectPtr final : std::unique_ptr> + { + using std::unique_ptr>::unique_ptr; + using std::unique_ptr>::operator=; + + ObjectPtr() + : ObjectPtr(nullptr) {} + + ObjectPtr(std::nullptr_t) + : std::unique_ptr>(nullptr, nullptr) {} + }; + template class ObjectPool { + friend class ObjectPtrDeleter; + public: ObjectPool() : mObjects(std::make_unique>()) {} - T* get() + ObjectPtr get() { T* object; @@ -29,17 +66,17 @@ namespace Misc object = &mObjects->back(); } - return object; + return ObjectPtr(object, ObjectPtrDeleter(*this)); } + private: + std::unique_ptr> mObjects; + std::vector mUnused; + void recycle(T* object) { mUnused.push_back(object); } - - private: - std::unique_ptr> mObjects; - std::vector mUnused; }; } From d1b5f17390e8000058efb57615b4a6f6735d0b29 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 4 Jul 2020 10:17:39 +0400 Subject: [PATCH 040/107] Remove redundant virtual qualifier --- apps/openmw/mwgui/statswatcher.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/statswatcher.hpp b/apps/openmw/mwgui/statswatcher.hpp index 9f17e5c54..41ab4fd25 100644 --- a/apps/openmw/mwgui/statswatcher.hpp +++ b/apps/openmw/mwgui/statswatcher.hpp @@ -62,7 +62,7 @@ namespace MWGui void removeListener(StatsListener* listener); void watchActor(const MWWorld::Ptr& ptr); - virtual MWWorld::Ptr getWatchedActor() const { return mWatched; } + MWWorld::Ptr getWatchedActor() const { return mWatched; } }; } From 9ec61c14d20ed438019d2ed39e5630f147a3c81e Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 4 Jul 2020 10:36:02 +0400 Subject: [PATCH 041/107] Mark some methods as overrides to avoid warnings --- apps/openmw/mwgui/hud.hpp | 8 ++++---- apps/openmw/mwgui/statswindow.hpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index c28dbc6d7..15235fe91 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -47,7 +47,7 @@ namespace MWGui void setCrosshairVisible(bool visible); void setCrosshairOwned(bool owned); - void onFrame(float dt); + void onFrame(float dt) override; void setCellName(const std::string& cellName); @@ -58,7 +58,7 @@ namespace MWGui void setEnemy(const MWWorld::Ptr& enemy); void resetEnemy(); - void clear(); + void clear() override; private: MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning; @@ -112,8 +112,8 @@ namespace MWGui void onMapClicked(MyGUI::Widget* _sender); // LocalMapBase - virtual void customMarkerCreated(MyGUI::Widget* marker); - virtual void doorMarkerCreated(MyGUI::Widget* marker); + virtual void customMarkerCreated(MyGUI::Widget* marker) override; + virtual void doorMarkerCreated(MyGUI::Widget* marker) override; void updateEnemyHealthBar(); diff --git a/apps/openmw/mwgui/statswindow.hpp b/apps/openmw/mwgui/statswindow.hpp index 60e17a821..1b6c60793 100644 --- a/apps/openmw/mwgui/statswindow.hpp +++ b/apps/openmw/mwgui/statswindow.hpp @@ -18,7 +18,7 @@ namespace MWGui StatsWindow(DragAndDrop* drag); /// automatically updates all the data in the stats window, but only if it has changed. - void onFrame(float dt); + void onFrame(float dt) override; void setBar(const std::string& name, const std::string& tname, int val, int max); void setPlayerName(const std::string& playerName); @@ -35,7 +35,7 @@ namespace MWGui void setBounty (int bounty) { if (bounty != mBounty) mChanged = true; this->mBounty = bounty; } void updateSkillArea(); - virtual void onOpen() { onWindowResize(mMainWidget->castType()); } + virtual void onOpen() override { onWindowResize(mMainWidget->castType()); } private: void addSkills(const SkillList &skills, const std::string &titleId, const std::string &titleDefault, MyGUI::IntCoord &coord1, MyGUI::IntCoord &coord2); @@ -70,8 +70,8 @@ namespace MWGui const int mMinFullWidth; protected: - virtual void onPinToggled(); - virtual void onTitleDoubleClicked(); + virtual void onPinToggled() override; + virtual void onTitleDoubleClicked() override; }; } #endif From db75398fba426a9a535a0a37f3dddb415c9826ca Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 4 Jul 2020 11:54:19 +0200 Subject: [PATCH 042/107] only build openmw for now --- CI/before_script.osx.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index 7438c6c7a..9697c757c 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -17,6 +17,8 @@ cmake \ -D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \ -D CMAKE_BUILD_TYPE=DEBUG \ -D OPENMW_OSX_DEPLOYMENT=TRUE \ +-D BUILD_OPENMW=TRUE \ +-D BUILD_OPENCS=FALSE \ -D BUILD_ESMTOOL=FALSE \ -D BUILD_BSATOOL=FALSE \ -D BUILD_ESSIMPORTER=FALSE \ From 2ac4a2c6e364cbc746ba950a9653ac871058ff95 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 4 Jul 2020 13:22:58 +0200 Subject: [PATCH 043/107] do not make package for now --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cfc449434..cd0e6e713 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,7 +71,7 @@ before_script: script: - cd ./build - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ${ANALYZE} make -j3; fi - - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi +# - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi # - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then ../CI/check_package.osx.sh; fi - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi - if [ "${COVERITY_SCAN_BRANCH}" != 1 ] && [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi From dc6fbd39d880e93d56a8f671be2859ee4dea6abe Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Tue, 7 Jan 2020 19:49:53 +1300 Subject: [PATCH 044/107] Cache compilation using ccache --- .gitlab-ci.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1f8bc6417..e58d3a498 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,19 +7,24 @@ Debian: - linux image: debian:bullseye cache: - key: apt-cache + key: cache.002 paths: - apt-cache/ + - ccache/ before_script: - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR - apt-get update -yq - - apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake build-essential libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-iostreams-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt5opengl5-dev libopenal-dev libopenscenegraph-dev libunshield-dev libtinyxml-dev libmygui-dev libbullet-dev + - apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake build-essential libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-iostreams-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt5opengl5-dev libopenal-dev libopenscenegraph-dev libunshield-dev libtinyxml-dev libmygui-dev libbullet-dev ccache stage: build - script: + script: + - export CCACHE_BASEDIR="`pwd`" + - export CCACHE_DIR="`pwd`/ccache" && mkdir -pv "$CCACHE_DIR" + - ccache -z -M 250M - cores_to_use=$((`nproc`-2)); if (( $cores_to_use < 1 )); then cores_to_use=1; fi - - mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../ + - mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - make -j$cores_to_use - DESTDIR=artifacts make install + - ccache -s artifacts: paths: - build/artifacts/ From 14d5b3eeaf65f1ac259c538a703be0e9e175c07e Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Mon, 6 Jul 2020 07:47:31 +0200 Subject: [PATCH 045/107] try release again and turning on bit by bit for ccache to be used --- CI/before_script.osx.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index 9697c757c..15d6862db 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -14,14 +14,16 @@ cmake \ -D CMAKE_C_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" \ -D CMAKE_CXX_COMPILER_LAUNCHER="$CCACHE_EXECUTABLE" \ -D CMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" \ +-D CMAKE_C_FLAGS_RELEASE="-g -O0" \ +-D CMAKE_CXX_FLAGS_RELEASE="-g -O0" \ -D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \ --D CMAKE_BUILD_TYPE=DEBUG \ +-D CMAKE_BUILD_TYPE=RELEASE \ -D OPENMW_OSX_DEPLOYMENT=TRUE \ -D BUILD_OPENMW=TRUE \ -D BUILD_OPENCS=FALSE \ --D BUILD_ESMTOOL=FALSE \ --D BUILD_BSATOOL=FALSE \ --D BUILD_ESSIMPORTER=FALSE \ --D BUILD_NIFTEST=FALSE \ +-D BUILD_ESMTOOL=TRUE \ +-D BUILD_BSATOOL=TRUE \ +-D BUILD_ESSIMPORTER=TRUE \ +-D BUILD_NIFTEST=TRUE \ -G"Unix Makefiles" \ .. From 3c460fb3e93a282a768f0ad1efce7ab9d309ed04 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 22:50:06 +0200 Subject: [PATCH 046/107] Use pointer to Sound to stop sounds started by NpcAnimation --- apps/openmw/mwrender/npcanimation.cpp | 14 ++++++++------ apps/openmw/mwrender/npcanimation.hpp | 9 ++++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 6e7669976..c6a0b15bd 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -349,6 +349,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, osg::ref_ptr par mPartPriorities[i] = 0; } + std::fill(mSounds.begin(), mSounds.end(), nullptr); + updateNpcBase(); } @@ -756,10 +758,10 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type) mPartslots[type] = -1; mObjectParts[type].reset(); - if (!mSoundIds[type].empty() && !mSoundsDisabled) + if (mSounds[type] != nullptr && !mSoundsDisabled) { - MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mSoundIds[type]); - mSoundIds[type].clear(); + MWBase::Environment::get().getSoundManager()->stopSound(mSounds[type]); + mSounds[type] = nullptr; } } @@ -838,10 +840,10 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g MWWorld::ConstContainerStoreIterator csi = inv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); if (csi != inv.end()) { - mSoundIds[type] = csi->getClass().getSound(*csi); - if (!mSoundIds[type].empty()) + const auto soundId = csi->getClass().getSound(*csi); + if (!soundId.empty()) { - MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, mSoundIds[type], + mSounds[type] = MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWSound::Type::Sfx, MWSound::PlayMode::Loop ); } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 7f8d5434b..7edf35a5c 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -8,12 +8,19 @@ #include "actoranimation.hpp" #include "weaponanimation.hpp" +#include + namespace ESM { struct NPC; struct BodyPart; } +namespace MWSound +{ + class Sound; +} + namespace MWRender { @@ -40,7 +47,7 @@ private: // Bounded Parts PartHolderPtr mObjectParts[ESM::PRT_Count]; - std::string mSoundIds[ESM::PRT_Count]; + std::array mSounds; const ESM::NPC *mNpc; std::string mHeadModel; From 281cef9769b1ea68b1451b08b76c7c9b41accb5a Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Mon, 6 Jul 2020 20:28:08 +0200 Subject: [PATCH 047/107] The 3 skill selected by a trainer are based on its 3 best skills. The skills are sorted either on their base value or on their modified one depending on the new setting 'trainers training skills based on base skill' --- apps/openmw/mwgui/trainingwindow.cpp | 16 +++++++++++++++- files/settings-default.cfg | 3 +++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index e4e4bae5a..91e9ce3cb 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -14,6 +14,8 @@ #include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/actorutil.hpp" +#include + #include "tooltips.hpp" namespace @@ -32,6 +34,17 @@ bool sortSkills (const std::pair& left, const std::pair& rig return left.first < right.first; } + +// Retrieve the base skill value if the setting 'training skills based on base skill' is set; +// otherwise returns the modified skill +float getSkillForTraining(const MWMechanics::NpcStats& stats, int i) +{ + static const bool trainersTrainingSkillsBasedOnBaseSkill = Settings::Manager::getBool("trainers training skills based on base skill", "Game"); + if (trainersTrainingSkillsBasedOnBaseSkill) + return stats.getSkill(i).getBase(); + return stats.getSkill(i).getModified(); +} + } namespace MWGui @@ -76,9 +89,10 @@ namespace MWGui // NPC can train you in his best 3 skills std::vector< std::pair > skills; + MWMechanics::NpcStats const& actorStats(actor.getClass().getNpcStats(actor)); for (int i=0; i Date: Mon, 6 Jul 2020 20:30:14 +0200 Subject: [PATCH 048/107] The number of skills points a trainer can teach is based either on its base values or on its modified ones depending on the new setting 'trainers training skills based on base skill' value --- apps/openmw/mwgui/trainingwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index 91e9ce3cb..60eb797ee 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -154,7 +154,7 @@ namespace MWGui if (price > player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId)) return; - if (mPtr.getClass().getSkill(mPtr, skillId) <= pcStats.getSkill (skillId).getBase ()) + if (getSkillForTraining(mPtr.getClass().getNpcStats(mPtr), skillId) <= pcStats.getSkill(skillId).getBase()) { MWBase::Environment::get().getWindowManager()->messageBox ("#{sServiceTrainingWords}"); return; From 998bf5da34f745202d823ef7bc3ad971bf64bd81 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Mon, 6 Jul 2020 20:32:30 +0200 Subject: [PATCH 049/107] Add new checkbox for the new setting 'trainers training skills based on base skill' --- apps/launcher/advancedpage.cpp | 2 ++ files/ui/advancedpage.ui | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 866cec728..e9db74cae 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -90,6 +90,7 @@ bool Launcher::AdvancedPage::loadSettings() loadSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game"); } loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game"); + loadSettingBool(trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game"); // Input Settings loadSettingBool(grabCursorCheckBox, "grab cursor", "Input"); @@ -155,6 +156,7 @@ void Launcher::AdvancedPage::saveSettings() saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game"); saveSettingBool(shieldSheathingCheckBox, "shield sheathing", "Game"); saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game"); + saveSettingBool(trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game"); // Input Settings saveSettingBool(grabCursorCheckBox, "grab cursor", "Input"); diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index 03b011b47..142cd7259 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -236,6 +236,16 @@ + + + + <html><head/><body><p>Trainers now only choose which skills to train using their base skill points, allowing mercantile improving effects to be used without making mercantile an offered skill.</p></body></html> + + + Trainers choose their training skills based on their base skill points + + + From 096e25b29a590a4667ab04046f1d2fd69517c7d3 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Tue, 7 Jul 2020 09:50:02 +0200 Subject: [PATCH 050/107] Make the getSkillForTraining a member method of TrainingWindow class. The implementation is based now on the member of the class mTrainingSkillBasedOnBaseSkill instead of local static --- apps/openmw/mwgui/trainingwindow.cpp | 19 ++++++++----------- apps/openmw/mwgui/trainingwindow.hpp | 10 ++++++++++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/trainingwindow.cpp b/apps/openmw/mwgui/trainingwindow.cpp index 60eb797ee..d0176ece4 100644 --- a/apps/openmw/mwgui/trainingwindow.cpp +++ b/apps/openmw/mwgui/trainingwindow.cpp @@ -34,17 +34,6 @@ bool sortSkills (const std::pair& left, const std::pair& rig return left.first < right.first; } - -// Retrieve the base skill value if the setting 'training skills based on base skill' is set; -// otherwise returns the modified skill -float getSkillForTraining(const MWMechanics::NpcStats& stats, int i) -{ - static const bool trainersTrainingSkillsBasedOnBaseSkill = Settings::Manager::getBool("trainers training skills based on base skill", "Game"); - if (trainersTrainingSkillsBasedOnBaseSkill) - return stats.getSkill(i).getBase(); - return stats.getSkill(i).getModified(); -} - } namespace MWGui @@ -53,6 +42,7 @@ namespace MWGui TrainingWindow::TrainingWindow() : WindowBase("openmw_trainingwindow.layout") , mTimeAdvancer(0.05f) + , mTrainingSkillBasedOnBaseSkill(Settings::Manager::getBool("trainers training skills based on base skill", "Game")) { getWidget(mTrainingOptions, "TrainingOptions"); getWidget(mCancelButton, "CancelButton"); @@ -209,6 +199,13 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode(); } + float TrainingWindow::getSkillForTraining(const MWMechanics::NpcStats& stats, int skillId) const + { + if (mTrainingSkillBasedOnBaseSkill) + return stats.getSkill(skillId).getBase(); + return stats.getSkill(skillId).getModified(); + } + void TrainingWindow::onFrame(float dt) { checkReferenceAvailable(); diff --git a/apps/openmw/mwgui/trainingwindow.hpp b/apps/openmw/mwgui/trainingwindow.hpp index 2edad1f27..955615516 100644 --- a/apps/openmw/mwgui/trainingwindow.hpp +++ b/apps/openmw/mwgui/trainingwindow.hpp @@ -6,6 +6,11 @@ #include "timeadvancer.hpp" #include "waitdialog.hpp" +namespace MWMechanics +{ + class NpcStats; +} + namespace MWGui { @@ -35,12 +40,17 @@ namespace MWGui void onTrainingProgressChanged(int cur, int total); void onTrainingFinished(); + // Retrieve the base skill value if the setting 'training skills based on base skill' is set; + // otherwise returns the modified skill + float getSkillForTraining(const MWMechanics::NpcStats& stats, int skillId) const; + MyGUI::Widget* mTrainingOptions; MyGUI::Button* mCancelButton; MyGUI::TextBox* mPlayerGold; WaitDialogProgressBar mProgressBar; TimeAdvancer mTimeAdvancer; + bool mTrainingSkillBasedOnBaseSkill; //corresponds to the setting 'training skills based on base skill' }; } From e51191b5ca6858c187ccbafea1dfeb8c4ca789ad Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Tue, 7 Jul 2020 17:54:31 +0200 Subject: [PATCH 051/107] Update documentation --- docs/source/reference/modding/settings/game.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/source/reference/modding/settings/game.rst b/docs/source/reference/modding/settings/game.rst index c27796aec..9cac845a5 100644 --- a/docs/source/reference/modding/settings/game.rst +++ b/docs/source/reference/modding/settings/game.rst @@ -330,3 +330,18 @@ If disabled then the whole character's body is pointed to the direction of view. If enabled then the character turns lower body to the direction of movement. Upper body is turned partially. Head is always pointed to the direction of view. In combat mode it works only for diagonal movement. In non-combat mode it also changes straight right and straight left movement. This setting can only be configured by editing the settings configuration file. + +trainers training skills based on base skill +----------------------- + +:Type: boolean +:Range: True/False +:Default: False + +The trainers in Morrowind choose their proposed training skills based on their 3 best attributes. + +If disabled then the 3 best skills of trainers and the training limits take into account fortified/drained trainer skill. + +If enabled then the 3 best skills of trainers and the training limits are based on the trainer base skills. + +This setting can be controlled in Advanced tab of the launcher. From d76b81a4a43cf3bce0c98fa355d9c4746889e5bd Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Tue, 7 Jul 2020 17:54:42 +0200 Subject: [PATCH 052/107] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 687e421fa..c2f05c3c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Feature #5362: Show the soul gems' trapped soul in count dialog Feature #5445: Handle NiLines Feature #5457: Realistic diagonal movement + Feature #5486: Fixes trainers to choose their training skills based on their base skill points Task #5480: Drop Qt4 support 0.46.0 From 624baa6d89679406fccd1314c2b00626d2fc0c7a Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 28 Jun 2020 19:59:53 +0200 Subject: [PATCH 053/107] Check distance to object before load sound --- apps/openmw/mwsound/soundmanagerimp.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index eed935e61..eabda4cc3 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -620,14 +620,14 @@ namespace MWSound if(!mOutput->isInitialized()) return nullptr; + const osg::Vec3f objpos(ptr.getRefData().getPosition().asVec3()); + if ((mode & PlayMode::RemoveAtDistance) && (mListenerPos - objpos).length2() > 2000 * 2000) + return nullptr; + // Look up the sound in the ESM data Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); if(!sfx) return nullptr; - const osg::Vec3f objpos(ptr.getRefData().getPosition().asVec3()); - if((mode&PlayMode::RemoveAtDistance) && (mListenerPos-objpos).length2() > 2000*2000) - return nullptr; - // Only one copy of given sound can be played at time on ptr, so stop previous copy stopSound(sfx, ptr); From 1c9ce03575d0834cb8aa556d594ee03693ff1644 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 29 Jun 2020 00:05:25 +0200 Subject: [PATCH 054/107] Lookup sound when need to fade out --- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index eabda4cc3..a4241fef2 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -762,7 +762,9 @@ namespace MWSound SoundMap::iterator snditer = mActiveSounds.find(ptr); if(snditer != mActiveSounds.end()) { - Sound_Buffer *sfx = loadSound(Misc::StringUtils::lowerCase(soundId)); + Sound_Buffer *sfx = lookupSound(Misc::StringUtils::lowerCase(soundId)); + if (sfx == nullptr) + return; for(SoundBufferRefPair &sndbuf : snditer->second) { if(sndbuf.second == sfx) From 46db69a3490bc0d3110fdeac6d93b399e1969565 Mon Sep 17 00:00:00 2001 From: psi29a Date: Thu, 9 Jul 2020 06:47:37 +0000 Subject: [PATCH 055/107] Merge branch 'swimming' into 'master' Swimming-related fixes See merge request OpenMW/openmw!247 (cherry picked from commit 8be328ef80f29e9692e29d24beefa8ced16537a7) 738c71fd Extend the "turn to movement direction" mode for swimming up and down. 10d3e82b New setting "swim upward coef" --- apps/openmw/mwmechanics/character.cpp | 26 ++++++++++++++++--- apps/openmw/mwrender/animation.cpp | 5 ++-- apps/openmw/mwrender/animation.hpp | 3 +++ apps/openmw/mwrender/creatureanimation.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 2 +- .../reference/modding/settings/game.rst | 13 +++++++++- files/settings-default.cfg | 3 +++ 7 files changed, 46 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index cf09fa6f7..aed638895 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1914,6 +1914,7 @@ void CharacterController::update(float duration, bool animationOnly) mTimeUntilWake -= duration; bool isPlayer = mPtr == MWMechanics::getPlayer(); + bool isFirstPersonPlayer = isPlayer && MWBase::Environment::get().getWorld()->isFirstPerson(); bool godmode = isPlayer && MWBase::Environment::get().getWorld()->getGodModeState(); float scale = mPtr.getCellRef().getScale(); @@ -1977,7 +1978,7 @@ void CharacterController::update(float duration, bool animationOnly) float effectiveRotation = rot.z(); static const bool turnToMovementDirection = Settings::Manager::getBool("turn to movement direction", "Game"); - if (turnToMovementDirection && !(isPlayer && MWBase::Environment::get().getWorld()->isFirstPerson())) + if (turnToMovementDirection && !isFirstPersonPlayer) { float targetMovementAngle = vec.y() >= 0 ? std::atan2(-vec.x(), vec.y()) : std::atan2(vec.x(), -vec.y()); movementSettings.mIsStrafing = (stats.getDrawState() != MWMechanics::DrawState_Nothing || inwater) @@ -2206,8 +2207,7 @@ void CharacterController::update(float duration, bool animationOnly) // It seems only bipedal actors use turning animations. // Also do not use turning animations in the first-person view and when sneaking. - bool isFirstPlayer = isPlayer && MWBase::Environment::get().getWorld()->isFirstPerson(); - if (!sneak && jumpstate == JumpState_None && !isFirstPlayer && mPtr.getClass().isBipedal(mPtr)) + if (!sneak && jumpstate == JumpState_None && !isFirstPersonPlayer && mPtr.getClass().isBipedal(mPtr)) { if(effectiveRotation > rotationThreshold) movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight; @@ -2231,6 +2231,26 @@ void CharacterController::update(float duration, bool animationOnly) sndMgr->playSound3D(mPtr, sound, 1.f, 1.f, MWSound::Type::Foot, MWSound::PlayMode::NoPlayerLocal); } + if (turnToMovementDirection) + { + float targetSwimmingPitch; + if (inwater && vec.y() != 0 && !isFirstPersonPlayer && !movementSettings.mIsStrafing) + targetSwimmingPitch = -mPtr.getRefData().getPosition().rot[0]; + else + targetSwimmingPitch = 0; + float maxSwimPitchDelta = 3.0f * duration; + float swimmingPitch = mAnimation->getBodyPitchRadians(); + swimmingPitch += osg::clampBetween(targetSwimmingPitch - swimmingPitch, -maxSwimPitchDelta, maxSwimPitchDelta); + mAnimation->setBodyPitchRadians(swimmingPitch); + } + if (inwater && isPlayer && !isFirstPersonPlayer) + { + static const float swimUpwardCoef = Settings::Manager::getFloat("swim upward coef", "Game"); + static const float swimForwardCoef = sqrtf(1.0f - swimUpwardCoef * swimUpwardCoef); + vec.z() = std::abs(vec.y()) * swimUpwardCoef; + vec.y() *= swimForwardCoef; + } + // Player can not use smooth turning as NPCs, so we play turning animation a bit to avoid jittering if (isPlayer) { diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 688937ce9..3835e26de 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -623,6 +623,7 @@ namespace MWRender , mHeadPitchRadians(0.f) , mUpperBodyYawRadians(0.f) , mLegsYawRadians(0.f) + , mBodyPitchRadians(0.f) , mHasMagicEffects(false) , mAlpha(1.f) { @@ -1340,11 +1341,11 @@ namespace MWRender float yawOffset = 0; if (mRootController) { - bool enable = std::abs(mLegsYawRadians) > epsilon; + bool enable = std::abs(mLegsYawRadians) > epsilon || std::abs(mBodyPitchRadians) > epsilon; mRootController->setEnabled(enable); if (enable) { - mRootController->setRotate(osg::Quat(mLegsYawRadians, osg::Vec3f(0,0,1))); + mRootController->setRotate(osg::Quat(mLegsYawRadians, osg::Vec3f(0,0,1)) * osg::Quat(mBodyPitchRadians, osg::Vec3f(1,0,0))); yawOffset = mLegsYawRadians; } } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 564952a90..a04a3f999 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -273,6 +273,7 @@ protected: float mHeadPitchRadians; float mUpperBodyYawRadians; float mLegsYawRadians; + float mBodyPitchRadians; RotateController* addRotateController(std::string bone); @@ -489,6 +490,8 @@ public: virtual void setLegsYawRadians(float v) { mLegsYawRadians = v; } virtual float getUpperBodyYawRadians() const { return mUpperBodyYawRadians; } virtual float getLegsYawRadians() const { return mLegsYawRadians; } + virtual void setBodyPitchRadians(float v) { mBodyPitchRadians = v; } + virtual float getBodyPitchRadians() const { return mBodyPitchRadians; } virtual void setAccurateAiming(bool enabled) {} virtual bool canBeHarvested() const { return false; } diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 8e7f30687..489a7a987 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -273,7 +273,7 @@ osg::Vec3f CreatureWeaponAnimation::runAnimation(float duration) { osg::Vec3f ret = Animation::runAnimation(duration); - WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0]); + WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0] + getBodyPitchRadians()); return ret; } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index c6a0b15bd..468938d22 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -747,7 +747,7 @@ osg::Vec3f NpcAnimation::runAnimation(float timepassed) mFirstPersonNeckController->setOffset(mFirstPersonOffset); } - WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0]); + WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0] + getBodyPitchRadians()); return ret; } diff --git a/docs/source/reference/modding/settings/game.rst b/docs/source/reference/modding/settings/game.rst index 9cac845a5..8d0b0dfc1 100644 --- a/docs/source/reference/modding/settings/game.rst +++ b/docs/source/reference/modding/settings/game.rst @@ -331,8 +331,19 @@ If enabled then the character turns lower body to the direction of movement. Upp This setting can only be configured by editing the settings configuration file. +swim upward coef +---------------- + +:Type: floating point +:Range: -1.0 to 1.0 +:Default: 0.0 + +Makes player swim a bit upward (or downward in case of negative value) from the line of sight. Intended to make simpler swimming without diving. Recommened range of values is from 0.0 to 0.2. + +This setting can only be configured by editing the settings configuration file. + trainers training skills based on base skill ------------------------ +-------------------------------------------- :Type: boolean :Range: True/False diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 494b06092..b044bdd5c 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -310,6 +310,9 @@ uncapped damage fatigue = false # Turn lower body to movement direction. 'true' makes diagonal movement more realistic. turn to movement direction = false +# Makes player swim a bit upward (or downward in case of negative value) from the line of sight. +swim upward coef = 0.0 + # Make the training skills proposed by a trainer based on its base attribute instead of its modified ones trainers training skills based on base skill = false From bbba524a6c336d6910ab2a1bc34a6902316e5032 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 9 Jul 2020 22:36:57 +0200 Subject: [PATCH 056/107] Resolves #5517 by removing the object being rotated from the paging system. --- apps/openmw/mwworld/worldimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d8b822242..fd934b8a8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1390,6 +1390,9 @@ namespace MWWorld { if(ptr.getRefData().getBaseNode() != 0) { + mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); + mWorldScene->removeFromPagedRefs(ptr); + mRendering->rotateObject(ptr, rotate); mPhysics->updateRotation(ptr); From 4ea018c594929e4beacad0009942a094b45fddd8 Mon Sep 17 00:00:00 2001 From: bzzt lost a hitlab login Date: Thu, 9 Jul 2020 23:17:01 +0200 Subject: [PATCH 057/107] Should resolve #5493 by better supporting objects that are placed across cells. --- apps/openmw/mwrender/objectpaging.cpp | 17 +++++++++++++++-- apps/openmw/mwrender/objectpaging.hpp | 4 ++-- apps/openmw/mwrender/renderingmanager.cpp | 4 ++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index fd12ad367..0f7e1c422 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -670,16 +670,27 @@ namespace MWRender { if (mActiveGridOnly && !std::get<2>(id)) return false; pos /= ESM::Land::REAL_SIZE; + clampToCell(pos); osg::Vec2f center = std::get<0>(id); float halfSize = std::get<1>(id)/2; return pos.x() >= center.x()-halfSize && pos.y() >= center.y()-halfSize && pos.x() <= center.x()+halfSize && pos.y() <= center.y()+halfSize; } + void clampToCell(osg::Vec3f& cellPos) + { + osg::Vec2i min (mCell.x(), mCell.y()); + osg::Vec2i max (mCell.x()+1, mCell.y()+1); + if (cellPos.x() < min.x()) cellPos.x() = min.x(); + if (cellPos.x() > max.x()) cellPos.x() = max.x(); + if (cellPos.y() < min.y()) cellPos.y() = min.y(); + if (cellPos.y() > max.y()) cellPos.y() = max.y(); + } osg::Vec3f mPosition; + osg::Vec2i mCell; std::set mToClear; bool mActiveGridOnly = false; }; - bool ObjectPaging::enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, bool enabled) + bool ObjectPaging::enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, const osg::Vec2i& cell, bool enabled) { if (!typeFilter(type, false)) return false; @@ -693,6 +704,7 @@ namespace MWRender ClearCacheFunctor ccf; ccf.mPosition = pos; + ccf.mCell = cell; mCache->call(ccf); if (ccf.mToClear.empty()) return false; for (auto chunk : ccf.mToClear) @@ -700,7 +712,7 @@ namespace MWRender return true; } - bool ObjectPaging::blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos) + bool ObjectPaging::blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, const osg::Vec2i& cell) { if (!typeFilter(type, false)) return false; @@ -713,6 +725,7 @@ namespace MWRender ClearCacheFunctor ccf; ccf.mPosition = pos; + ccf.mCell = cell; ccf.mActiveGridOnly = true; mCache->call(ccf); if (ccf.mToClear.empty()) return false; diff --git a/apps/openmw/mwrender/objectpaging.hpp b/apps/openmw/mwrender/objectpaging.hpp index 2ca302038..18fa30289 100644 --- a/apps/openmw/mwrender/objectpaging.hpp +++ b/apps/openmw/mwrender/objectpaging.hpp @@ -34,10 +34,10 @@ namespace MWRender virtual unsigned int getNodeMask() override; /// @return true if view needs rebuild - bool enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, bool enabled); + bool enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, const osg::Vec2i& cell, bool enabled); /// @return true if view needs rebuild - bool blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos); + bool blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, const osg::Vec2i& cell); void clear(); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 0c6e48645..a7d9003dc 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -1517,7 +1517,7 @@ namespace MWRender { if (!ptr.isInCell() || !ptr.getCell()->isExterior() || !mObjectPaging) return false; - if (mObjectPaging->enableObject(type, ptr.getCellRef().getRefNum(), ptr.getCellRef().getPosition().asVec3(), enabled)) + if (mObjectPaging->enableObject(type, ptr.getCellRef().getRefNum(), ptr.getCellRef().getPosition().asVec3(), osg::Vec2i(ptr.getCell()->getCell()->getGridX(), ptr.getCell()->getCell()->getGridY()), enabled)) { mTerrain->rebuildViews(); return true; @@ -1530,7 +1530,7 @@ namespace MWRender return; const ESM::RefNum & refnum = ptr.getCellRef().getRefNum(); if (!refnum.hasContentFile()) return; - if (mObjectPaging->blacklistObject(type, refnum, ptr.getCellRef().getPosition().asVec3())) + if (mObjectPaging->blacklistObject(type, refnum, ptr.getCellRef().getPosition().asVec3(), osg::Vec2i(ptr.getCell()->getCell()->getGridX(), ptr.getCell()->getCell()->getGridY()))) mTerrain->rebuildViews(); } bool RenderingManager::pagingUnlockCache() From 280862f58b5af9bf0b099ccf16ffb42b6bc898dc Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Tue, 23 Jun 2020 20:05:22 +0200 Subject: [PATCH 058/107] New setting "third person camera distance" --- apps/openmw/mwrender/camera.cpp | 8 ++++++-- apps/openmw/mwrender/camera.hpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 6 +++--- docs/source/reference/modding/settings/camera.rst | 11 +++++++++++ files/settings-default.cfg | 3 +++ 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 148aa33ed..09ad40428 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" @@ -56,7 +57,7 @@ namespace MWRender mFurthest(800.f), mIsNearest(false), mHeight(124.f), - mBaseCameraDistance(192.f), + mBaseCameraDistance(Settings::Manager::getFloat("third person camera distance", "Camera")), mVanityToggleQueued(false), mVanityToggleQueuedValue(false), mViewModeToggleQueued(false), @@ -380,7 +381,7 @@ namespace MWRender return mCameraDistance; } - void Camera::setBaseCameraDistance(float dist, bool adjust) + void Camera::updateBaseCameraDistance(float dist, bool adjust) { if(mFirstPersonView && !mPreviewMode && !mVanity.enabled) return; @@ -407,7 +408,10 @@ namespace MWRender if (mVanity.enabled || mPreviewMode) mPreviewCam.offset = dist; else if (!mFirstPersonView) + { mBaseCameraDistance = dist; + Settings::Manager::setFloat("third person camera distance", "Camera", dist); + } setCameraDistance(); } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index c04bf31c2..6398f4825 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -119,7 +119,7 @@ namespace MWRender /// Set base camera distance for current mode. Don't work on 1st person view. /// \param adjust Indicates should distance be adjusted or set. - void setBaseCameraDistance(float dist, bool adjust = false); + void updateBaseCameraDistance(float dist, bool adjust = false); /// Set camera distance for current mode. Don't work on 1st person view. /// \param adjust Indicates should distance be adjusted or set. diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 0c6e48645..d7549fc54 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -1340,7 +1340,7 @@ namespace MWRender if(mCamera->isNearest() && dist > 0.f) mCamera->toggleViewMode(); else if (override) - mCamera->setBaseCameraDistance(-dist / 120.f * 10, adjust); + mCamera->updateBaseCameraDistance(-dist / 120.f * 10, adjust); else mCamera->setCameraDistance(-dist / 120.f * 10, adjust); } @@ -1348,7 +1348,7 @@ namespace MWRender { mCamera->toggleViewMode(); if (override) - mCamera->setBaseCameraDistance(0.f, false); + mCamera->updateBaseCameraDistance(0.f, false); else mCamera->setCameraDistance(0.f, false); } @@ -1397,7 +1397,7 @@ namespace MWRender void RenderingManager::changeVanityModeScale(float factor) { if(mCamera->isVanityOrPreviewModeEnabled()) - mCamera->setBaseCameraDistance(-factor/120.f*10, true); + mCamera->updateBaseCameraDistance(-factor/120.f*10, true); } void RenderingManager::overrideFieldOfView(float val) diff --git a/docs/source/reference/modding/settings/camera.rst b/docs/source/reference/modding/settings/camera.rst index ecc1bda50..20349e97f 100644 --- a/docs/source/reference/modding/settings/camera.rst +++ b/docs/source/reference/modding/settings/camera.rst @@ -114,6 +114,17 @@ while small values can result in the hands not being visible. This setting can only be configured by editing the settings configuration file. +third person camera distance +---------------------------- + +:Type: floating point +:Range: 30-800 +:Default: 192.0 + +Distance from the camera to the character in third person mode. + +This setting can be changed in game using "Zoom In" / "Zoom Out" controls. + view over shoulder ------------------ diff --git a/files/settings-default.cfg b/files/settings-default.cfg index b044bdd5c..1e62ff5bf 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -33,6 +33,9 @@ field of view = 60.0 # Best to leave this at the default since vanilla assets are not complete enough to adapt to high FoV's. Too low FoV would clip the hands off screen. first person field of view = 60.0 +# Distance from the camera to the character in third person mode. +third person camera distance = 192 + # If enabled then third person camera is positioned above character's shoulder and crosshair is visible. view over shoulder = false From fd61ebf6abf6e2077e0e0d23f7ab451e37823b3c Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 10 Jul 2020 00:44:54 +0200 Subject: [PATCH 059/107] remove big white blob of space --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index a7d9003dc..9876fae54 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -1517,7 +1517,7 @@ namespace MWRender { if (!ptr.isInCell() || !ptr.getCell()->isExterior() || !mObjectPaging) return false; - if (mObjectPaging->enableObject(type, ptr.getCellRef().getRefNum(), ptr.getCellRef().getPosition().asVec3(), osg::Vec2i(ptr.getCell()->getCell()->getGridX(), ptr.getCell()->getCell()->getGridY()), enabled)) + if (mObjectPaging->enableObject(type, ptr.getCellRef().getRefNum(), ptr.getCellRef().getPosition().asVec3(), osg::Vec2i(ptr.getCell()->getCell()->getGridX(), ptr.getCell()->getCell()->getGridY()), enabled)) { mTerrain->rebuildViews(); return true; From 721e659d3757ad2458ad6a401d5daecf22e8a78d Mon Sep 17 00:00:00 2001 From: psi29a Date: Fri, 10 Jul 2020 12:12:07 +0000 Subject: [PATCH 060/107] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2f05c3c3..7be9cc2c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Bug #5367: Selecting a spell on an enchanted item per hotkey always plays the equip sound Bug #5369: Spawnpoint in the Grazelands doesn't produce oversized creatures Bug #5370: Opening an unlocked but trapped door uses the key + Bug #5384: openmw-cs: deleting an instance requires reload of scene window to show in editor Bug #5397: NPC greeting does not reset if you leave + reenter area Bug #5400: Editor: Verifier checks race of non-skin bodyparts Bug #5403: Enchantment effect doesn't show on an enemy during death animation From 5c3496fb15db92dffc30d4457f5347e5a91a4ac0 Mon Sep 17 00:00:00 2001 From: psi29a Date: Fri, 10 Jul 2020 12:22:58 +0000 Subject: [PATCH 061/107] Delete FindBullet.cmake; we use cmake's version which has been available since 3.0.2 and we have a requirement of 3.1.0 https://cmake.org/cmake/help/v3.0/module/FindBullet.html --- cmake/FindBullet.cmake | 73 ------------------------------------------ 1 file changed, 73 deletions(-) delete mode 100644 cmake/FindBullet.cmake diff --git a/cmake/FindBullet.cmake b/cmake/FindBullet.cmake deleted file mode 100644 index 6d68bed70..000000000 --- a/cmake/FindBullet.cmake +++ /dev/null @@ -1,73 +0,0 @@ -# - Try to find the Bullet physics engine -# -# This module accepts the following env variables -# BULLET_ROOT - Can be set to bullet install path or Windows build path -# -# Once done this will define -# Bullet_FOUND - System has the all required components. -# Bullet_INCLUDE_DIRS - Include directory necessary for using the required components headers. -# Bullet_LIBRARIES - Link these to use the required bullet components. -# Bullet_VERSION - Version of libbullet -# -# For each of the components -# - LinearMath -# - BulletCollision -# - BulletSoftBody -# - BulletDynamics -# -# Copyright (c) 2009, Philip Lowman -# Modified for OpenMW to parse BT_BULLET_VERSION. -# -# Redistribution AND use is allowed according to the terms of the New -# BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - -include(LibFindMacros) - -# Macro: _internal_find_bullet_library -# Checks for the given component by invoking pkgconfig etc. -macro(_internal_find_bullet_library _lib) - libfind_pkg_detect(Bullet_${_lib} bullet - FIND_LIBRARY ${_lib} - HINTS $ENV{BULLET_ROOT} - PATH_SUFFIXES lib - ) - libfind_process(Bullet_${_lib}) -endmacro() - -set(_known_components LinearMath BulletCollision BulletSoftBody BulletDynamics) - -# Check if the required components were found and add their stuff to the Bullet_* vars. -foreach (_component ${Bullet_FIND_COMPONENTS}) - list(FIND _known_components ${_component} _known_component) - if (_known_component EQUAL -1) - message(FATAL_ERROR "Unknown component '${_component}'") - endif() - - set(Bullet_${_component}_Debug_FIND_QUIETLY TRUE) # don't spam messages with optional Debug component - _internal_find_bullet_library(${_component}) - _internal_find_bullet_library(${_component}_Debug) - - if (Bullet_${_component}_Debug_FOUND) - set(Bullet_LIBRARIES ${Bullet_LIBRARIES} optimized ${Bullet_${_component}_LIBRARIES} debug ${Bullet_${_component}_Debug_LIBRARIES}) - else() - set(Bullet_LIBRARIES ${Bullet_LIBRARIES} ${Bullet_${_component}_LIBRARIES}) - endif() -endforeach() - -libfind_pkg_detect(Bullet bullet - FIND_PATH btBulletCollisionCommon.h - HINTS $ENV{BULLET_ROOT} - PATH_SUFFIXES include/bullet -) -set(Bullet_INCLUDE_DIRS ${Bullet_INCLUDE_DIR}) -libfind_version_header(Bullet LinearMath/btScalar.h BT_BULLET_VERSION) - -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Bullet - FOUND_VAR Bullet_FOUND - VERSION_VAR Bullet_VERSION - HANDLE_COMPONENTS - REQUIRED_VARS - Bullet_LIBRARIES - Bullet_INCLUDE_DIR -) From 7300496a5fc32804fefd4c72072f51afce5f13f4 Mon Sep 17 00:00:00 2001 From: psi29a Date: Fri, 10 Jul 2020 12:27:22 +0000 Subject: [PATCH 062/107] Delete FindFreetype.cmake; as it is provided by cmake as of 3.0.2 and we require 3.1.0. --- cmake/FindFreetype.cmake | 91 ---------------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 cmake/FindFreetype.cmake diff --git a/cmake/FindFreetype.cmake b/cmake/FindFreetype.cmake deleted file mode 100644 index 3b7586835..000000000 --- a/cmake/FindFreetype.cmake +++ /dev/null @@ -1,91 +0,0 @@ -#------------------------------------------------------------------- -# This file is part of the CMake build system for OGRE -# (Object-oriented Graphics Rendering Engine) -# For the latest info, see https://www.ogre3d.org/ -# -# The contents of this file are placed in the public domain. Feel -# free to make use of it in any way you like. -#------------------------------------------------------------------- - -# - Try to find FreeType -# -# This module accepts the following env variable -# FREETYPE_DIR - Can be set to custom install path -# -# Once done, this will define -# -# Freetype_FOUND - system has FreeType -# Freetype_INCLUDE_DIRS - the FreeType include directories -# Freetype_LIBRARIES - link these to use FreeType -# Freetype_VERSION - version of FreeType -# -# libfreetype internals: -# -# ====================================== -# new versions (2.5.2) -# -# file structure: -# /include/freetype2/ft2build.h -# /include/freetype2/freetype.h -# used as: -# #include -# #include -# requires: -# -I /include/freetype2/ -# -# ====================================== -# old versions (2.4.8, 2.3.5) -# -# file structure: -# /include/ft2build.h -# /include/freetype2/freetype/freetype.h -# used as: -# #include -# #include -# requires: -# -I /include/ -I /include/freetype2/ -# -# ====================================== - -include(LibFindMacros) - -set(_REGULAR_INSTALL_PATHS - /usr/X11R6 - /usr/local/X11R6 - /usr/local/X11 - /usr/freeware - ENV GTKMM_BASEPATH - [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path] -) - -libfind_pkg_detect(Freetype freetype2 - FIND_PATH ft2build.h - HINTS $ENV{FREETYPE_DIR} - PATHS ${_REGULAR_INSTALL_PATHS} - PATH_SUFFIXES include freetype2 - FIND_LIBRARY freetype freetype2311 freetype239 freetype238 freetype235 freetype219 - HINTS $ENV{FREETYPE_DIR} - PATHS ${_REGULAR_INSTALL_PATHS} - PATH_SUFFIXES lib -) -find_path(Freetype_OLD_INCLUDE_DIR - # in new versions of freetype old_include_dir equals to include_dir - # see explanation above - NAMES freetype/freetype.h freetype.h - PATHS ${Freetype_INCLUDE_DIR} - PATH_SUFFIXES freetype2 - NO_DEFAULT_PATH -) -libfind_version_n_header(Freetype - NAMES freetype/freetype.h freetype.h - PATHS Freetype_OLD_INCLUDE_DIR - DEFINES FREETYPE_MAJOR FREETYPE_MINOR FREETYPE_PATCH -) - -set(Freetype_PROCESS_INCLUDES Freetype_OLD_INCLUDE_DIR) -libfind_process(Freetype) - -if (Freetype_INCLUDE_DIRS) - list(REMOVE_DUPLICATES Freetype_INCLUDE_DIRS) -endif() From f47d2bb8afbcdd5eb838812c4a4c7ccc49a5c4fb Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Fri, 10 Jul 2020 15:01:44 +0200 Subject: [PATCH 063/107] make sure we use case-sensative BULLET_ prefix --- CMakeLists.txt | 2 +- components/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c5bf22fd..dbe28fd84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -311,7 +311,7 @@ include_directories("." ${Boost_INCLUDE_DIR} ${MyGUI_INCLUDE_DIRS} ${OPENAL_INCLUDE_DIR} - ${Bullet_INCLUDE_DIRS} + ${BULLET_INCLUDE_DIRS} ) link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS}) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 1d4a84ce1..86d657792 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -210,7 +210,7 @@ if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") endif() endif () -include_directories(${Bullet_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${BULLET_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS} ${ESM_UI_HDR}) @@ -229,7 +229,7 @@ target_link_libraries(components ${OSGGA_LIBRARIES} ${OSGSHADOW_LIBRARIES} ${OSGANIMATION_LIBRARIES} - ${Bullet_LIBRARIES} + ${BULLET_LIBRARIES} ${SDL2_LIBRARIES} ${OPENGL_gl_LIBRARY} ${MyGUI_LIBRARIES} From 4a17bf27a368720bd141ca38f791190f307105f1 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 11 Jul 2020 00:18:14 +0200 Subject: [PATCH 064/107] Set BULLET_ROOT via add_cmake_opts like we do the rest --- CI/before_script.msvc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 9a213963e..dc6eb7e44 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -606,7 +606,7 @@ printf "Bullet 2.89 (${BULLET_DBL_DISPLAY})... " eval 7z x -y "${DEPS}/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" $STRIP mv "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}" Bullet fi - export BULLET_ROOT="$(real_pwd)/Bullet" + add_cmake_opts -DBULLET_ROOT="$(real_pwd)/Bullet" echo Done. } cd $DEPS From 1bb54a28bc5903b27bd8bd8f368d10482b7181ee Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 03:23:15 +0100 Subject: [PATCH 065/107] Build fewer targets Most importantly, skip the CS. This should bring the build time under an hour. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d77db4059..0f62bfa37 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,7 +67,7 @@ Windows_Ninja_RelWithDebInfo: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config + - cmake --build . --config $config --target openwm openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -113,7 +113,7 @@ Windows_MSBuild_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config + - cmake --build . --config $config --target openwm openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From c29a1c256751650acc17c8f2018d03b4e40de953 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 03:52:54 +0100 Subject: [PATCH 066/107] ninja: error: unknown target 'openwm', did you mean 'openmw'? --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0f62bfa37..fda13c4be 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -67,7 +67,7 @@ Windows_Ninja_RelWithDebInfo: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config --target openwm openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -113,7 +113,7 @@ Windows_MSBuild_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config --target openwm openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From a4e3f32ec89ab7364acf0e2d692fe83f0fe4a8a6 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 11 Jul 2020 13:29:20 +0200 Subject: [PATCH 067/107] Fix TSAN warnings for ripples emitter While main thread creates particles rendering thread draws them so sychronization is required. --- apps/openmw/mwrender/ripplesimulation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index f7feb267a..6788f53f4 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -200,6 +200,7 @@ void RippleSimulation::emitRipple(const osg::Vec3f &pos) { if (std::abs(pos.z() - mParticleNode->getPosition().z()) < 20) { + osgParticle::ParticleSystem::ScopedWriteLock lock(*mParticleSystem->getReadWriteMutex()); osgParticle::Particle* p = mParticleSystem->createParticle(nullptr); p->setPosition(osg::Vec3f(pos.x(), pos.y(), 0.f)); p->setAngle(osg::Vec3f(0,0, Misc::Rng::rollProbability() * osg::PI * 2 - osg::PI)); From db8f0ad6fd05c3842a9a0c0b498420ac597302c2 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 11 Jul 2020 17:24:20 +0400 Subject: [PATCH 068/107] Do not use outdated references when moving objects to new cells (bug #5387) --- CHANGELOG.md | 1 + apps/openmw/mwbase/windowmanager.hpp | 2 ++ apps/openmw/mwgui/console.cpp | 6 ++++++ apps/openmw/mwgui/console.hpp | 2 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 5 +++++ apps/openmw/mwgui/windowmanagerimp.hpp | 2 ++ apps/openmw/mwscript/transformationextensions.cpp | 6 ++++-- apps/openmw/mwworld/worldimp.cpp | 2 ++ 8 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7be9cc2c7..991744bf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Bug #5369: Spawnpoint in the Grazelands doesn't produce oversized creatures Bug #5370: Opening an unlocked but trapped door uses the key Bug #5384: openmw-cs: deleting an instance requires reload of scene window to show in editor + Bug #5387: Move/MoveWorld don't update the object's cell properly Bug #5397: NPC greeting does not reset if you leave + reenter area Bug #5400: Editor: Verifier checks race of non-skin bodyparts Bug #5403: Enchantment effect doesn't show on an enemy during death animation diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index f35df7881..1d59015d3 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -237,6 +237,8 @@ namespace MWBase virtual void update (float duration) = 0; + virtual void updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) = 0; + /** * Fetches a GMST string from the store, if there is no setting with the given * ID or it is not a string the default string is returned. diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index df4bdec5b..120573d59 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -472,6 +472,12 @@ namespace MWGui setCoord(10,10, width-10, height/2); } + void Console::updateSelectedObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) + { + if (mPtr == currentPtr) + mPtr = newPtr; + } + void Console::setSelectedObject(const MWWorld::Ptr& object) { if (!object.isEmpty()) diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 883bc8967..e431d18d1 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -58,6 +58,8 @@ namespace MWGui void executeFile (const std::string& path); + void updateSelectedObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr); + void clear(); virtual void resetReference (); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 02b42c9cd..840f0f9cf 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -574,6 +574,11 @@ namespace MWGui } } + void WindowManager::updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) + { + mConsole->updateSelectedObjectPtr(currentPtr, newPtr); + } + void WindowManager::updateVisible() { bool loading = (getMode() == GM_Loading || getMode() == GM_LoadingWallpaper); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index a8cb0b10a..67a16f516 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -242,6 +242,8 @@ namespace MWGui virtual void unsetSelectedSpell(); virtual void unsetSelectedWeapon(); + virtual void updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr); + virtual void showCrosshair(bool show); virtual bool getSubtitlesEnabled(); diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 791d054f3..7bb9093c1 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -725,7 +725,8 @@ namespace MWScript // We should move actors, standing on moving object, too. // This approach can be used to create elevators. moveStandingActors(ptr, diff); - MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x(), worldPos.y(), worldPos.z()); + dynamic_cast(runtime.getContext()).updatePtr(ptr, + MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x(), worldPos.y(), worldPos.z())); } }; @@ -761,7 +762,8 @@ namespace MWScript // We should move actors, standing on moving object, too. // This approach can be used to create elevators. moveStandingActors(ptr, diff); - MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+diff.x(), objPos[1]+diff.y(), objPos[2]+diff.z()); + dynamic_cast(runtime.getContext()).updatePtr(ptr, + MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+diff.x(), objPos[1]+diff.y(), objPos[2]+diff.z())); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index fd934b8a8..1efb03b32 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1201,6 +1201,8 @@ namespace MWWorld } } } + + MWBase::Environment::get().getWindowManager()->updateConsoleObjectPtr(ptr, newPtr); } if (haveToMove && newPtr.getRefData().getBaseNode()) { From a9e6bf11c2df6c0380286b98b0283b11152ff4a1 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 16:36:21 +0100 Subject: [PATCH 069/107] Configurations (via inheritance) --- .gitlab-ci.yml | 51 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fda13c4be..638e89317 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,7 @@ MacOS: paths: - build/OpenMW-*.dmg -Windows_Ninja_RelWithDebInfo: +.Windows_Ninja_Base: tags: - windows before_script: @@ -61,7 +61,6 @@ Windows_Ninja_RelWithDebInfo: stage: build script: - $time = (Get-Date -Format "HH:mm:ss") - - $config = "RelWithDebInfo" - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N @@ -71,10 +70,10 @@ Windows_Ninja_RelWithDebInfo: - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' Get-ChildItem -Recurse *.pdb | Remove-Item } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}.zip '*' + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}.zip '*' cache: paths: - deps @@ -93,8 +92,25 @@ Windows_Ninja_RelWithDebInfo: - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log +Windows_Ninja_Release: + extends: + - .Windows_Ninja_Base + variables: + - config: "Release" -Windows_MSBuild_RelWithDebInfo: +Windows_Ninja_Debug: + extends: + - .Windows_Ninja_Base + variables: + - config: "Debug" + +Windows_Ninja_RelWithDebInfo: + extends: + - .Windows_Ninja_Base + variables: + - config: "RelWithDebInfo" + +.Windows_MSBuild_Base: tags: - windows before_script: @@ -108,7 +124,6 @@ Windows_MSBuild_RelWithDebInfo: stage: build script: - $time = (Get-Date -Format "HH:mm:ss") - - $config = "RelWithDebInfo" - echo ${time} - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V @@ -117,10 +132,10 @@ Windows_MSBuild_RelWithDebInfo: - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' Get-ChildItem -Recurse *.pdb | Remove-Item } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${CIBuildRefName}_${CIBuildID}.zip '*' + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}.zip '*' cache: paths: - deps @@ -137,4 +152,22 @@ Windows_MSBuild_RelWithDebInfo: - MSVC2019_64/*/*/*/*/*.log - MSVC2019_64/*/*/*/*/*/*.log - MSVC2019_64/*/*/*/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*/*/*/*.log \ No newline at end of file + - MSVC2019_64/*/*/*/*/*/*/*/*.log + +Windows_MSBuild_Release: + extends: + - .Windows_MSBuild_Base + variables: + - config: "Release" + +Windows_MSBuild_Debug: + extends: + - .Windows_MSBuild_Base + variables: + - config: "Debug" + +Windows_MSBuild_RelWithDebInfo: + extends: + - .Windows_MSBuild_Base + variables: + - config: "RelWithDebInfo" \ No newline at end of file From 3862f0d10a09b3035656327b162981e119c40456 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 16:42:15 +0100 Subject: [PATCH 070/107] Migrate variable names Some of the built-ins were deprecated/removed --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 638e89317..56b893338 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -70,10 +70,10 @@ MacOS: - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' Get-ChildItem -Recurse *.pdb | Remove-Item } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}.zip '*' + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: paths: - deps @@ -132,10 +132,10 @@ Windows_Ninja_RelWithDebInfo: - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}_symbols.zip '*.pdb' + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' Get-ChildItem -Recurse *.pdb | Remove-Item } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CIBuildRefName}_${CIBuildID}.zip '*' + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: paths: - deps From 81aed34588a464f0763823be2ac3d17911394896 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 16:54:13 +0100 Subject: [PATCH 071/107] variables should be a hash of key value pairs --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 56b893338..e49690153 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -96,19 +96,19 @@ Windows_Ninja_Release: extends: - .Windows_Ninja_Base variables: - - config: "Release" + config: "Release" Windows_Ninja_Debug: extends: - .Windows_Ninja_Base variables: - - config: "Debug" + config: "Debug" Windows_Ninja_RelWithDebInfo: extends: - .Windows_Ninja_Base variables: - - config: "RelWithDebInfo" + config: "RelWithDebInfo" .Windows_MSBuild_Base: tags: @@ -158,16 +158,16 @@ Windows_MSBuild_Release: extends: - .Windows_MSBuild_Base variables: - - config: "Release" + config: "Release" Windows_MSBuild_Debug: extends: - .Windows_MSBuild_Base variables: - - config: "Debug" + config: "Debug" Windows_MSBuild_RelWithDebInfo: extends: - .Windows_MSBuild_Base variables: - - config: "RelWithDebInfo" \ No newline at end of file + config: "RelWithDebInfo" \ No newline at end of file From 58e3900ea0edc9e09ad9d561a9d02e7ade4c3b1e Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 8 Jul 2020 14:12:55 +0400 Subject: [PATCH 072/107] Avoid redundant call --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index fd934b8a8..0ab15dfc4 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1907,7 +1907,7 @@ namespace MWWorld std::string enchantId = selectedEnchantItem.getClass().getEnchantment(selectedEnchantItem); if (!enchantId.empty()) { - const ESM::Enchantment* ench = mStore.get().search(selectedEnchantItem.getClass().getEnchantment(selectedEnchantItem)); + const ESM::Enchantment* ench = mStore.get().search(enchantId); if (ench) preloadEffects(&ench->mEffects); } From bdf215d1a9b6c966621028a575afd3f3996455d9 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 11 Jul 2020 18:32:33 +0200 Subject: [PATCH 073/107] Add bug #4764 to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7be9cc2c7..c2869408e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Bug #3714: Savegame fails to load due to conflict between SpellState and MagicEffects Bug #4021: Attributes and skills are not stored as floats Bug #4623: Corprus implementation is incorrect + Bug #4764: Data race in osg ParticleSystem Bug #4774: Guards are ignorant of an invisible player that tries to attack them Bug #5108: Savegame bloating due to inefficient fog textures format Bug #5165: Active spells should use real time intead of timestamps From db0ad8421f57d2ac0993d96b7e35bcdb3d6aadf0 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 11 Jul 2020 16:16:44 +0200 Subject: [PATCH 074/107] Report OSG rendering stats --- apps/openmw/engine.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index ec12d6a1f..7cbc1c99f 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -908,7 +908,14 @@ void OMW::Engine::go() if (stats) { const auto frameNumber = mViewer->getFrameStamp()->getFrameNumber(); - mViewer->getViewerStats()->report(stats, frameNumber); + if (frameNumber >= 2) + { + mViewer->getViewerStats()->report(stats, frameNumber - 2); + osgViewer::Viewer::Cameras cameras; + mViewer->getCameras(cameras); + for (auto camera : cameras) + camera->getStats()->report(stats, frameNumber - 2); + } } mEnvironment.limitFrameRate(frameTimer.time_s()); From da791590ac05010ba768480754b97b47cb939a5e Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 11 Jul 2020 20:40:00 +0400 Subject: [PATCH 075/107] Update HUD icons during mechanics update again to avoid crashes --- apps/openmw/mwgui/statswatcher.cpp | 21 --------------- .../mwmechanics/mechanicsmanagerimp.cpp | 26 ++++++++++++++++++- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwgui/statswatcher.cpp b/apps/openmw/mwgui/statswatcher.cpp index 7baec2f2c..ccb77de8f 100644 --- a/apps/openmw/mwgui/statswatcher.cpp +++ b/apps/openmw/mwgui/statswatcher.cpp @@ -136,27 +136,6 @@ namespace MWGui } mWatchedStatsEmpty = false; - - // Update the equipped weapon icon - MWWorld::InventoryStore& inv = mWatched.getClass().getInventoryStore(mWatched); - MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if (weapon == inv.end()) - winMgr->unsetSelectedWeapon(); - else - winMgr->setSelectedWeapon(*weapon); - - // Update the selected spell icon - MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); - if (enchantItem != inv.end()) - winMgr->setSelectedEnchantItem(*enchantItem); - else - { - const std::string& spell = winMgr->getSelectedSpell(); - if (!spell.empty()) - winMgr->setSelectedSpell(spell, int(MWMechanics::getSpellSuccessChance(spell, mWatched))); - else - winMgr->unsetSelectedSpell(); - } } void StatsWatcher::addListener(StatsListener* listener) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index fcae60c58..fd8902b37 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -302,13 +302,37 @@ namespace MWMechanics void MechanicsManager::update(float duration, bool paused) { + // Note: we should do it here since game mechanics and world updates use these values + MWWorld::Ptr ptr = getPlayer(); + MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager(); + + // Update the equipped weapon icon + MWWorld::InventoryStore& inv = ptr.getClass().getInventoryStore(ptr); + MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if (weapon == inv.end()) + winMgr->unsetSelectedWeapon(); + else + winMgr->setSelectedWeapon(*weapon); + + // Update the selected spell icon + MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem(); + if (enchantItem != inv.end()) + winMgr->setSelectedEnchantItem(*enchantItem); + else + { + const std::string& spell = winMgr->getSelectedSpell(); + if (!spell.empty()) + winMgr->setSelectedSpell(spell, int(MWMechanics::getSpellSuccessChance(spell, ptr))); + else + winMgr->unsetSelectedSpell(); + } + if (mUpdatePlayer) { mUpdatePlayer = false; // HACK? The player has been changed, so a new Animation object may // have been made for them. Make sure they're properly updated. - MWWorld::Ptr ptr = getPlayer(); mActors.removeActor(ptr); mActors.addActor(ptr, true); } From 699ec9e06e8926ad9a6115dbb6f1ead6507096c3 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 17:52:42 +0100 Subject: [PATCH 076/107] separate caches for MSBuild and Ninja --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e49690153..258963a2f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,6 +75,7 @@ MacOS: } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: + key: ninja paths: - deps - MSVC2019_64_Ninja/deps @@ -137,6 +138,7 @@ Windows_Ninja_RelWithDebInfo: } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: + key: msbuild paths: - deps - MSVC2019_64/deps From 24129e8a54029dc92cbc5c94bdbb7f7397e62ae4 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 20:40:36 +0100 Subject: [PATCH 077/107] Runner now supports sensible globbing patterns --- .gitlab-ci.yml | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 258963a2f..e332c6a94 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -84,14 +84,7 @@ MacOS: paths: - "*.zip" - "*.log" - - MSVC2019_64_Ninja/*.log - - MSVC2019_64_Ninja/*/*.log - - MSVC2019_64_Ninja/*/*/*.log - - MSVC2019_64_Ninja/*/*/*/*.log - - MSVC2019_64_Ninja/*/*/*/*/*.log - - MSVC2019_64_Ninja/*/*/*/*/*/*.log - - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log - - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log + - MSVC2019_64_Ninja/**.log Windows_Ninja_Release: extends: @@ -147,14 +140,7 @@ Windows_Ninja_RelWithDebInfo: paths: - "*.zip" - "*.log" - - MSVC2019_64/*.log - - MSVC2019_64/*/*.log - - MSVC2019_64/*/*/*.log - - MSVC2019_64/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*/*/*.log - - MSVC2019_64/*/*/*/*/*/*/*/*.log + - MSVC2019_64/**.log Windows_MSBuild_Release: extends: From 094f0d1772d86795dd07a8f8fddaf5dfb7977f7c Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 11 Jul 2020 22:46:12 +0100 Subject: [PATCH 078/107] Maybe this will make globbing work --- .gitlab-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e332c6a94..4e2bb3451 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -84,7 +84,8 @@ MacOS: paths: - "*.zip" - "*.log" - - MSVC2019_64_Ninja/**.log + - MSVC2019_64_Ninja/*.log + - MSVC2019_64_Ninja/**/*.log Windows_Ninja_Release: extends: @@ -140,7 +141,8 @@ Windows_Ninja_RelWithDebInfo: paths: - "*.zip" - "*.log" - - MSVC2019_64/**.log + - MSVC2019_64/*.log + - MSVC2019_64/**/*.log Windows_MSBuild_Release: extends: From ef451fa26680a0536b053de73f0e27fe6c23d667 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 03:17:46 +0100 Subject: [PATCH 079/107] Revert "Runner now supports sensible globbing patterns" & "Maybe this will make globbing work" Runner *actually* only supports sensible globbing patterns for cache, not artifacts. This reverts commits 24129e8a54029dc92cbc5c94bdbb7f7397e62ae4 and 094f0d1772d86795dd07a8f8fddaf5dfb7977f7c. --- .gitlab-ci.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4e2bb3451..258963a2f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -85,7 +85,13 @@ MacOS: - "*.zip" - "*.log" - MSVC2019_64_Ninja/*.log - - MSVC2019_64_Ninja/**/*.log + - MSVC2019_64_Ninja/*/*.log + - MSVC2019_64_Ninja/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log + - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log Windows_Ninja_Release: extends: @@ -142,7 +148,13 @@ Windows_Ninja_RelWithDebInfo: - "*.zip" - "*.log" - MSVC2019_64/*.log - - MSVC2019_64/**/*.log + - MSVC2019_64/*/*.log + - MSVC2019_64/*/*/*.log + - MSVC2019_64/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*/*.log + - MSVC2019_64/*/*/*/*/*/*/*/*.log Windows_MSBuild_Release: extends: From 22c5c7a96e7f158c0d9feb45bd671f5bdc1ffe05 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 03:18:56 +0100 Subject: [PATCH 080/107] Build the CS again. Maybe this will work now the cache isn't trash --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 258963a2f..f88029ce7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ MacOS: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -129,7 +129,7 @@ Windows_Ninja_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From 271f7040a653cf48275b872d71e062d0947938e0 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 12 Jul 2020 13:25:40 +0200 Subject: [PATCH 081/107] Fix a regression caused by #2648 (fixes #5513) --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 1fbe8f7fd..209ab538e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1185,7 +1185,6 @@ namespace MWWorld mRendering->updatePtr(ptr, newPtr); MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr); mPhysics->updatePtr(ptr, newPtr); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().updatePtrs(ptr, newPtr); MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager(); mechMgr->updateCell(ptr, newPtr); @@ -1203,6 +1202,7 @@ namespace MWWorld } MWBase::Environment::get().getWindowManager()->updateConsoleObjectPtr(ptr, newPtr); + MWBase::Environment::get().getScriptManager()->getGlobalScripts().updatePtrs(ptr, newPtr); } if (haveToMove && newPtr.getRefData().getBaseNode()) { From 20859bbc50341745b3be00ef8995d1f9d698bd8b Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 13:55:45 +0100 Subject: [PATCH 082/107] Revert "Build the CS again." There wasn't enough time. This reverts commit 22c5c7a96e7f158c0d9feb45bd671f5bdc1ffe05. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f88029ce7..258963a2f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ MacOS: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config + - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -129,7 +129,7 @@ Windows_Ninja_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config + - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From 6f3e87ce696a904b1e3b40a0ec0042030ec597af Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 13:58:12 +0100 Subject: [PATCH 083/107] Cache less stuff to avoid duplicate entries. This might make everything faster if we're network-bound. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 258963a2f..2d34e6fd3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -78,7 +78,7 @@ MacOS: key: ninja paths: - deps - - MSVC2019_64_Ninja/deps + - MSVC2019_64_Ninja/deps/Qt artifacts: when: always paths: @@ -141,7 +141,7 @@ Windows_Ninja_RelWithDebInfo: key: msbuild paths: - deps - - MSVC2019_64/deps + - MSVC2019_64/deps/Qt artifacts: when: always paths: From 5934a9d145babfa36c7703c3fe4a0923543753c3 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 15:08:47 +0100 Subject: [PATCH 084/107] Actualy build the reduced cache. It looks like cache is only invalidated if new files are added, not old ones removed. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2d34e6fd3..2bdfa990e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,7 +75,7 @@ MacOS: } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: - key: ninja + key: ninja-v2 paths: - deps - MSVC2019_64_Ninja/deps/Qt @@ -138,7 +138,7 @@ Windows_Ninja_RelWithDebInfo: } - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: - key: msbuild + key: msbuild-v2 paths: - deps - MSVC2019_64/deps/Qt From 65ac0c86b8a3fdb77d9347597ae3cc441b8190d5 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 12 Jul 2020 19:05:47 +0300 Subject: [PATCH 085/107] Fix search filter unicode character case sensitivity --- apps/openmw/mwgui/sortfilteritemmodel.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/sortfilteritemmodel.cpp b/apps/openmw/mwgui/sortfilteritemmodel.cpp index 615e2dfc9..f18cac681 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.cpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.cpp @@ -69,8 +69,8 @@ namespace return compareType(leftName, rightName); // compare items by name - leftName = Misc::StringUtils::lowerCase(left.mBase.getClass().getName(left.mBase)); - rightName = Misc::StringUtils::lowerCase(right.mBase.getClass().getName(right.mBase)); + leftName = Misc::StringUtils::lowerCaseUtf8(left.mBase.getClass().getName(left.mBase)); + rightName = Misc::StringUtils::lowerCaseUtf8(right.mBase.getClass().getName(right.mBase)); result = leftName.compare(rightName); if (result != 0) @@ -213,7 +213,7 @@ namespace MWGui if (!mNameFilter.empty()) { - const auto itemName = Misc::StringUtils::lowerCase(base.getClass().getName(base)); + const auto itemName = Misc::StringUtils::lowerCaseUtf8(base.getClass().getName(base)); return itemName.find(mNameFilter) != std::string::npos; } @@ -226,7 +226,7 @@ namespace MWGui for (const auto& effect : effects) { - const auto ciEffect = Misc::StringUtils::lowerCase(effect); + const auto ciEffect = Misc::StringUtils::lowerCaseUtf8(effect); if (ciEffect.find(mEffectFilter) != std::string::npos) return true; @@ -285,7 +285,7 @@ namespace MWGui return false; } - std::string compare = Misc::StringUtils::lowerCase(item.mBase.getClass().getName(item.mBase)); + std::string compare = Misc::StringUtils::lowerCaseUtf8(item.mBase.getClass().getName(item.mBase)); if(compare.find(mNameFilter) == std::string::npos) return false; @@ -318,12 +318,12 @@ namespace MWGui void SortFilterItemModel::setNameFilter (const std::string& filter) { - mNameFilter = Misc::StringUtils::lowerCase(filter); + mNameFilter = Misc::StringUtils::lowerCaseUtf8(filter); } void SortFilterItemModel::setEffectFilter (const std::string& filter) { - mEffectFilter = Misc::StringUtils::lowerCase(filter); + mEffectFilter = Misc::StringUtils::lowerCaseUtf8(filter); } void SortFilterItemModel::update() From 5675d6ce81116261df3d320a163ba8d9500e41f2 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Fri, 19 Jun 2020 22:03:11 +0200 Subject: [PATCH 086/107] Generalize calculation of focal point offset for 3rd person camera. When player swim, the view slowly switches from "over shoulder" to "above head". New functions to switch shoulder. --- apps/openmw/mwrender/camera.cpp | 95 +++++++++++++++++++++++++-------- apps/openmw/mwrender/camera.hpp | 17 ++++-- 2 files changed, 86 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 09ad40428..e0f031b8c 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -7,6 +7,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" #include "../mwworld/class.hpp" #include "../mwworld/ptr.hpp" @@ -64,7 +65,10 @@ namespace MWRender mCameraDistance(0.f), mThirdPersonMode(ThirdPersonViewMode::Standard), mOverShoulderOffset(osg::Vec2f(30.0f, -10.0f)), - mSmoothTransitionToCombatMode(0.f) + mDefaultShoulderIsRight(true), + mThirdPersionOffsetType(ThirdPersonOffsetType::RightShoulder), + mFocalPointCurrentOffset(osg::Vec2d()), + mFocalPointTransitionSpeed(1.f) { mVanity.enabled = false; mVanity.allowed = true; @@ -121,12 +125,9 @@ namespace MWRender osg::Vec3d offset(0, 0, 10.f); if (mThirdPersonMode == ThirdPersonViewMode::OverShoulder && !mPreviewMode && !mVanity.enabled) { - float horizontalOffset = mOverShoulderOffset.x() * (1.f - mSmoothTransitionToCombatMode); - float verticalOffset = mSmoothTransitionToCombatMode * 15.f + (1.f - mSmoothTransitionToCombatMode) * mOverShoulderOffset.y(); - - offset.x() += horizontalOffset * cos(getYaw()); - offset.y() += horizontalOffset * sin(getYaw()); - offset.z() += verticalOffset; + offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw()); + offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw()); + offset.z() += mFocalPointCurrentOffset.y(); } return offset; } @@ -214,28 +215,78 @@ namespace MWRender rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true); } - updateSmoothTransitionToCombatMode(duration); + updateFocalPointOffset(duration); } void Camera::setOverShoulderOffset(float horizontal, float vertical) { - mOverShoulderOffset = osg::Vec2f(horizontal, vertical); + mOverShoulderOffset = osg::Vec2f(std::abs(horizontal), vertical); + mDefaultShoulderIsRight = horizontal >= 0; } - void Camera::updateSmoothTransitionToCombatMode(float duration) + void Camera::switchToLeftShoulder() { - bool combatMode = true; - if (mTrackingPtr.getClass().isActor()) - combatMode = mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing; - float speed = ((combatMode ? 1.f : 0.f) - mSmoothTransitionToCombatMode) * 5; - if (speed != 0) - speed += speed > 0 ? 1 : -1; - - mSmoothTransitionToCombatMode += speed * duration; - if (mSmoothTransitionToCombatMode > 1) - mSmoothTransitionToCombatMode = 1; - if (mSmoothTransitionToCombatMode < 0) - mSmoothTransitionToCombatMode = 0; + if (mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder) + mThirdPersionOffsetType = ThirdPersonOffsetType::LeftShoulder; + } + + void Camera::switchToRightShoulder() + { + if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder) + mThirdPersionOffsetType = ThirdPersonOffsetType::RightShoulder; + } + + void Camera::switchToDefaultShoulder() + { + if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder || mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder) + mThirdPersionOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder; + } + + void Camera::updateFocalPointOffset(float duration) + { + if (mThirdPersonMode == ThirdPersonViewMode::Standard) + return; // In Standard mode there is no focal point offset. + + ThirdPersonOffsetType newOffsetType = mThirdPersionOffsetType; + if (mTrackingPtr.getClass().isActor() && mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing) + newOffsetType = ThirdPersonOffsetType::Combat; + else if (MWBase::Environment::get().getWorld()->isSwimming(mTrackingPtr)) + newOffsetType = ThirdPersonOffsetType::Swimming; + else if (mThirdPersionOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Swimming) + newOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder; + if (newOffsetType != mThirdPersionOffsetType) + { + if (newOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Combat) + mFocalPointTransitionSpeed = 5; + else + mFocalPointTransitionSpeed = 1; + mThirdPersionOffsetType = newOffsetType; + } + + osg::Vec2d focalPointTargetOffset; + switch (mThirdPersionOffsetType) + { + case ThirdPersonOffsetType::RightShoulder: + focalPointTargetOffset = mOverShoulderOffset; + break; + case ThirdPersonOffsetType::LeftShoulder: + focalPointTargetOffset = mOverShoulderOffset + focalPointTargetOffset.x() *= -1; + break; + case ThirdPersonOffsetType::Combat: + case ThirdPersonOffsetType::Swimming: + default: + focalPointTargetOffset = osg::Vec2d(0, 15); + } + + osg::Vec2d delta = focalPointTargetOffset - mFocalPointCurrentOffset; + if (delta.length2() > 0) + { + float coef = duration * (1.0 + 5.0 / delta.length()) * mFocalPointTransitionSpeed; + mFocalPointCurrentOffset += delta * std::min(coef, 1.0f); + } + else + mFocalPointTransitionSpeed = 1.f; } void Camera::toggleViewMode(bool force) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 6398f4825..1e1d12f10 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -27,6 +27,8 @@ namespace MWRender enum class ThirdPersonViewMode {Standard, OverShoulder}; private: + enum class ThirdPersonOffsetType { RightShoulder, LeftShoulder, Combat, Swimming }; + struct CamData { float pitch, yaw, offset; }; @@ -60,12 +62,15 @@ namespace MWRender ThirdPersonViewMode mThirdPersonMode; osg::Vec2f mOverShoulderOffset; + bool mDefaultShoulderIsRight; osg::Vec3d mFocalPointAdjustment; - // Makes sense only if mThirdPersonMode is OverShoulder. Can be in range [0, 1]. - // Used for smooth transition from non-combat camera position (0) to combat camera position (1). - float mSmoothTransitionToCombatMode; - void updateSmoothTransitionToCombatMode(float duration); + // Makes sense only if mThirdPersonMode is OverShoulder. + ThirdPersonOffsetType mThirdPersionOffsetType; + osg::Vec2d mFocalPointCurrentOffset; + float mFocalPointTransitionSpeed; + + void updateFocalPointOffset(float duration); float getCameraDistanceCorrection() const; osg::ref_ptr mUpdateCallback; @@ -79,6 +84,10 @@ namespace MWRender void setThirdPersonViewMode(ThirdPersonViewMode mode) { mThirdPersonMode = mode; } void setOverShoulderOffset(float horizontal, float vertical); + void switchToLeftShoulder(); + void switchToRightShoulder(); + void switchToDefaultShoulder(); + /// Update the view matrix of \a cam void updateCamera(osg::Camera* cam); From ef03f2c033ebd8a6c2de41d7ed692b0715050123 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 20 Jun 2020 00:46:26 +0200 Subject: [PATCH 087/107] Auto switch shoulder --- apps/openmw/mwrender/camera.cpp | 2 +- apps/openmw/mwrender/camera.hpp | 3 +- apps/openmw/mwworld/worldimp.cpp | 35 +++++++++++++++++-- .../reference/modding/settings/camera.rst | 12 +++++++ files/settings-default.cfg | 3 ++ 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index e0f031b8c..3da94f97d 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -270,7 +270,7 @@ namespace MWRender focalPointTargetOffset = mOverShoulderOffset; break; case ThirdPersonOffsetType::LeftShoulder: - focalPointTargetOffset = mOverShoulderOffset + focalPointTargetOffset = mOverShoulderOffset; focalPointTargetOffset.x() *= -1; break; case ThirdPersonOffsetType::Combat: diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 1e1d12f10..b3e7e1f67 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -82,8 +82,9 @@ namespace MWRender MWWorld::Ptr getTrackingPtr() const; void setThirdPersonViewMode(ThirdPersonViewMode mode) { mThirdPersonMode = mode; } - void setOverShoulderOffset(float horizontal, float vertical); + ThirdPersonViewMode getThirdPersonViewMode() const { return mThirdPersonMode; } + void setOverShoulderOffset(float horizontal, float vertical); void switchToLeftShoulder(); void switchToRightShoulder(); void switchToDefaultShoulder(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 209ab538e..80a9a01ae 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1869,13 +1869,44 @@ namespace MWWorld float cameraObstacleLimit = mRendering->getNearClipDistance() * 2.5f; float focalObstacleLimit = std::max(cameraObstacleLimit, 10.0f); - // Adjust focal point. osg::Vec3d focal = camera->getFocalPoint(); osg::Vec3d focalOffset = camera->getFocalPointOffset(); + osg::Vec3d playerPos = focal - focalOffset; + + static const bool autoSwitchShoulder = Settings::Manager::getBool("auto switch shoulder", "Camera"); + if (camera->getThirdPersonViewMode() == MWRender::Camera::ThirdPersonViewMode::OverShoulder + && autoSwitchShoulder && !camera->isVanityOrPreviewModeEnabled()) + { + const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit + const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance + auto orient = osg::Quat(camera->getYaw(), osg::Vec3d(0,0,1)); + int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_Door | MWPhysics::CollisionType_HeightMap; + MWPhysics::PhysicsSystem::RayResult rayRight = mPhysics->castRay( + playerPos + orient * osg::Vec3d(28, 0, 0), + playerPos + orient * osg::Vec3d(limitToSwitchBack, limitToSwitchBack, 0), + {}, {}, mask); + MWPhysics::PhysicsSystem::RayResult rayLeft = mPhysics->castRay( + playerPos + orient * osg::Vec3d(-28, 0, 0), + playerPos + orient * osg::Vec3d(-limitToSwitchBack, limitToSwitchBack, 0), + {}, {}, mask); + MWPhysics::PhysicsSystem::RayResult rayForward = mPhysics->castRay( + playerPos, playerPos + orient * osg::Vec3d(0, limitToSwitchBack, 0), + {}, {}, mask); + bool rightTooClose = rayRight.mHit && (rayRight.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch; + bool leftTooClose = rayLeft.mHit && (rayLeft.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch; + if (!rayRight.mHit && leftTooClose) + camera->switchToRightShoulder(); + else if (!rayLeft.mHit && rightTooClose) + camera->switchToLeftShoulder(); + else if (!rayRight.mHit && !rayLeft.mHit && !rayForward.mHit) + camera->switchToDefaultShoulder(); + } + + // Adjust focal point. float offsetLen = focalOffset.length(); if (offsetLen > 0) { - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal - focalOffset, focal, focalObstacleLimit); + MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(playerPos, focal, focalObstacleLimit); if (result.mHit) { double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen; diff --git a/docs/source/reference/modding/settings/camera.rst b/docs/source/reference/modding/settings/camera.rst index 20349e97f..21fec8fd6 100644 --- a/docs/source/reference/modding/settings/camera.rst +++ b/docs/source/reference/modding/settings/camera.rst @@ -150,3 +150,15 @@ Recommened values: 30 -10 for the right shoulder, -30 -10 for the left shoulder. This setting can only be configured by editing the settings configuration file. +auto switch shoulder +-------------------- + +:Type: boolean +:Range: True/False +:Default: True + +This setting makes difference only in third person mode if 'view over shoulder' is enabled. +When player is close to an obstacle, automatically switches camera to the shoulder that is farther away from the obstacle. + +This setting can only be configured by editing the settings configuration file. + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 1e62ff5bf..b960946d8 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -42,6 +42,9 @@ view over shoulder = false # Makes sense only if 'view over shoulder' is true. First number is horizontal offset (negative value means offset to the left), second number is vertical offset. view over shoulder offset = 30 -10 +# Switch shoulder automatically when player is close to an obstacle. +auto switch shoulder = true + [Cells] # Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled. From 5bdf61a886d6da3913593ffe607d51c50e9783fb Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Mon, 22 Jun 2020 19:26:37 +0200 Subject: [PATCH 088/107] Slightly pulls camera away when the character moves --- apps/openmw/mwrender/camera.cpp | 19 +++++++++++++++++-- apps/openmw/mwrender/camera.hpp | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 3da94f97d..e856b8ab3 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -68,7 +68,8 @@ namespace MWRender mDefaultShoulderIsRight(true), mThirdPersionOffsetType(ThirdPersonOffsetType::RightShoulder), mFocalPointCurrentOffset(osg::Vec2d()), - mFocalPointTransitionSpeed(1.f) + mFocalPointTransitionSpeed(1.f), + mSmoothedSpeed(0.f) { mVanity.enabled = false; mVanity.allowed = true; @@ -216,6 +217,10 @@ namespace MWRender } updateFocalPointOffset(duration); + + float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); + float maxDelta = 300.f * duration; + mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); } void Camera::setOverShoulderOffset(float horizontal, float vertical) @@ -482,7 +487,17 @@ namespace MWRender float Camera::getCameraDistanceCorrection() const { - return mThirdPersonMode != ThirdPersonViewMode::Standard ? std::max(-getPitch(), 0.f) * 50.f : 0; + if (mThirdPersonMode == ThirdPersonViewMode::Standard) + return 0; + else + { + float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f; + + float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed; + float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f; + + return pitchCorrection + speedCorrection; + } } void Camera::setCameraDistance() diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index b3e7e1f67..eb7462945 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -70,6 +70,8 @@ namespace MWRender osg::Vec2d mFocalPointCurrentOffset; float mFocalPointTransitionSpeed; + float mSmoothedSpeed; + void updateFocalPointOffset(float duration); float getCameraDistanceCorrection() const; From 51173ebcf5c7f9dfce9f57ceea6cfb30bf9ea6c9 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 11 Jul 2020 14:21:18 +0200 Subject: [PATCH 089/107] Refactoring. Move all code related to 'view over shoulder' to a separate file. --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwrender/camera.cpp | 89 +++----------------- apps/openmw/mwrender/camera.hpp | 25 ++---- apps/openmw/mwrender/renderingmanager.cpp | 19 ++--- apps/openmw/mwrender/renderingmanager.hpp | 2 + apps/openmw/mwrender/viewovershoulder.cpp | 99 +++++++++++++++++++++++ apps/openmw/mwrender/viewovershoulder.hpp | 30 +++++++ apps/openmw/mwworld/worldimp.cpp | 35 +------- 8 files changed, 159 insertions(+), 142 deletions(-) create mode 100644 apps/openmw/mwrender/viewovershoulder.cpp create mode 100644 apps/openmw/mwrender/viewovershoulder.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index fddfa276f..01d270f82 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -20,7 +20,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender actors objects renderingmanager animation rotatecontroller sky npcanimation vismask creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation - bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation + bulletdebugdraw globalmap characterpreview camera viewovershoulder localmap water terrainstorage ripplesimulation renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging ) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index e856b8ab3..3b3f1aec9 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -7,7 +7,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" -#include "../mwbase/world.hpp" #include "../mwworld/class.hpp" #include "../mwworld/ptr.hpp" @@ -63,13 +62,12 @@ namespace MWRender mVanityToggleQueuedValue(false), mViewModeToggleQueued(false), mCameraDistance(0.f), - mThirdPersonMode(ThirdPersonViewMode::Standard), - mOverShoulderOffset(osg::Vec2f(30.0f, -10.0f)), - mDefaultShoulderIsRight(true), - mThirdPersionOffsetType(ThirdPersonOffsetType::RightShoulder), mFocalPointCurrentOffset(osg::Vec2d()), + mFocalPointTargetOffset(osg::Vec2d()), mFocalPointTransitionSpeed(1.f), - mSmoothedSpeed(0.f) + mSmoothedSpeed(0.f), + mDynamicCameraDistanceEnabled(false), + mShowCrosshairInThirdPersonMode(false) { mVanity.enabled = false; mVanity.allowed = true; @@ -124,7 +122,7 @@ namespace MWRender osg::Vec3d Camera::getFocalPointOffset() const { osg::Vec3d offset(0, 0, 10.f); - if (mThirdPersonMode == ThirdPersonViewMode::OverShoulder && !mPreviewMode && !mVanity.enabled) + if (!mPreviewMode && !mVanity.enabled) { offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw()); offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw()); @@ -209,7 +207,7 @@ namespace MWRender // only show the crosshair in game mode MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager(); wm->showCrosshair(!wm->isGuiMode() && !mVanity.enabled && !mPreviewMode - && (mFirstPersonView || mThirdPersonMode != ThirdPersonViewMode::Standard)); + && (mFirstPersonView || mShowCrosshairInThirdPersonMode)); if(mVanity.enabled) { @@ -223,68 +221,9 @@ namespace MWRender mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); } - void Camera::setOverShoulderOffset(float horizontal, float vertical) - { - mOverShoulderOffset = osg::Vec2f(std::abs(horizontal), vertical); - mDefaultShoulderIsRight = horizontal >= 0; - } - - void Camera::switchToLeftShoulder() - { - if (mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder) - mThirdPersionOffsetType = ThirdPersonOffsetType::LeftShoulder; - } - - void Camera::switchToRightShoulder() - { - if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder) - mThirdPersionOffsetType = ThirdPersonOffsetType::RightShoulder; - } - - void Camera::switchToDefaultShoulder() - { - if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder || mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder) - mThirdPersionOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder; - } - void Camera::updateFocalPointOffset(float duration) { - if (mThirdPersonMode == ThirdPersonViewMode::Standard) - return; // In Standard mode there is no focal point offset. - - ThirdPersonOffsetType newOffsetType = mThirdPersionOffsetType; - if (mTrackingPtr.getClass().isActor() && mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing) - newOffsetType = ThirdPersonOffsetType::Combat; - else if (MWBase::Environment::get().getWorld()->isSwimming(mTrackingPtr)) - newOffsetType = ThirdPersonOffsetType::Swimming; - else if (mThirdPersionOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Swimming) - newOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder; - if (newOffsetType != mThirdPersionOffsetType) - { - if (newOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Combat) - mFocalPointTransitionSpeed = 5; - else - mFocalPointTransitionSpeed = 1; - mThirdPersionOffsetType = newOffsetType; - } - - osg::Vec2d focalPointTargetOffset; - switch (mThirdPersionOffsetType) - { - case ThirdPersonOffsetType::RightShoulder: - focalPointTargetOffset = mOverShoulderOffset; - break; - case ThirdPersonOffsetType::LeftShoulder: - focalPointTargetOffset = mOverShoulderOffset; - focalPointTargetOffset.x() *= -1; - break; - case ThirdPersonOffsetType::Combat: - case ThirdPersonOffsetType::Swimming: - default: - focalPointTargetOffset = osg::Vec2d(0, 15); - } - - osg::Vec2d delta = focalPointTargetOffset - mFocalPointCurrentOffset; + osg::Vec2d delta = mFocalPointTargetOffset - mFocalPointCurrentOffset; if (delta.length2() > 0) { float coef = duration * (1.0 + 5.0 / delta.length()) * mFocalPointTransitionSpeed; @@ -487,17 +426,15 @@ namespace MWRender float Camera::getCameraDistanceCorrection() const { - if (mThirdPersonMode == ThirdPersonViewMode::Standard) + if (!mDynamicCameraDistanceEnabled) return 0; - else - { - float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f; - float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed; - float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f; + float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f; - return pitchCorrection + speedCorrection; - } + float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed; + float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f; + + return pitchCorrection + speedCorrection; } void Camera::setCameraDistance() diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index eb7462945..5f3c5d6e4 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -23,12 +23,7 @@ namespace MWRender /// \brief Camera control class Camera { - public: - enum class ThirdPersonViewMode {Standard, OverShoulder}; - private: - enum class ThirdPersonOffsetType { RightShoulder, LeftShoulder, Combat, Swimming }; - struct CamData { float pitch, yaw, offset; }; @@ -60,17 +55,14 @@ namespace MWRender float mCameraDistance; - ThirdPersonViewMode mThirdPersonMode; - osg::Vec2f mOverShoulderOffset; - bool mDefaultShoulderIsRight; osg::Vec3d mFocalPointAdjustment; - - // Makes sense only if mThirdPersonMode is OverShoulder. - ThirdPersonOffsetType mThirdPersionOffsetType; osg::Vec2d mFocalPointCurrentOffset; + osg::Vec2d mFocalPointTargetOffset; float mFocalPointTransitionSpeed; float mSmoothedSpeed; + bool mDynamicCameraDistanceEnabled; + bool mShowCrosshairInThirdPersonMode; void updateFocalPointOffset(float duration); float getCameraDistanceCorrection() const; @@ -83,13 +75,10 @@ namespace MWRender MWWorld::Ptr getTrackingPtr() const; - void setThirdPersonViewMode(ThirdPersonViewMode mode) { mThirdPersonMode = mode; } - ThirdPersonViewMode getThirdPersonViewMode() const { return mThirdPersonMode; } - - void setOverShoulderOffset(float horizontal, float vertical); - void switchToLeftShoulder(); - void switchToRightShoulder(); - void switchToDefaultShoulder(); + void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeed = v; } + void setFocalPointTargetOffset(osg::Vec2d v) { mFocalPointTargetOffset = v; } + void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; } + void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; } /// Update the view matrix of \a cam void updateCamera(osg::Camera* cam); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c7dd5ca63..d91da5a08 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -65,6 +65,7 @@ #include "vismask.hpp" #include "pathgrid.hpp" #include "camera.hpp" +#include "viewovershoulder.hpp" #include "water.hpp" #include "terrainstorage.hpp" #include "util.hpp" @@ -306,6 +307,8 @@ namespace MWRender mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), resourcePath)); mCamera.reset(new Camera(mViewer->getCamera())); + if (Settings::Manager::getBool("view over shoulder", "Camera")) + mViewOverShoulderController.reset(new ViewOverShoulderController(mCamera.get())); mViewer->setLightingMode(osgViewer::View::NO_LIGHT); @@ -366,7 +369,6 @@ namespace MWRender float firstPersonFov = Settings::Manager::getFloat("first person field of view", "Camera"); mFirstPersonFieldOfView = std::min(std::max(1.f, firstPersonFov), 179.f); mStateUpdater->setFogEnd(mViewDistance); - updateThirdPersonViewMode(); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip)); mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance)); @@ -382,19 +384,6 @@ namespace MWRender mWorkQueue = nullptr; } - void RenderingManager::updateThirdPersonViewMode() - { - if (Settings::Manager::getBool("view over shoulder", "Camera")) - mCamera->setThirdPersonViewMode(Camera::ThirdPersonViewMode::OverShoulder); - else - mCamera->setThirdPersonViewMode(Camera::ThirdPersonViewMode::Standard); - - std::stringstream offset(Settings::Manager::getString("view over shoulder offset", "Camera")); - float horizontal = 30.f, vertical = -10.f; - offset >> horizontal >> vertical; - mCamera->setOverShoulderOffset(horizontal, vertical); - } - osgUtil::IncrementalCompileOperation* RenderingManager::getIncrementalCompileOperation() { return mViewer->getIncrementalCompileOperation(); @@ -630,6 +619,8 @@ namespace MWRender updateNavMesh(); updateRecastMesh(); + if (mViewOverShoulderController) + mViewOverShoulderController->update(); mCamera->update(dt, paused); osg::Vec3d focal, cameraPos; diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 6700f5ce6..d6a0f89c3 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -79,6 +79,7 @@ namespace MWRender class NpcAnimation; class Pathgrid; class Camera; + class ViewOverShoulderController; class Water; class TerrainStorage; class LandManager; @@ -294,6 +295,7 @@ namespace MWRender osg::ref_ptr mPlayerAnimation; osg::ref_ptr mPlayerNode; std::unique_ptr mCamera; + std::unique_ptr mViewOverShoulderController; osg::Vec3f mCurrentCameraPos; osg::ref_ptr mStateUpdater; diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp new file mode 100644 index 000000000..f908b1430 --- /dev/null +++ b/apps/openmw/mwrender/viewovershoulder.cpp @@ -0,0 +1,99 @@ +#include "viewovershoulder.hpp" + +#include + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/world.hpp" + +#include "../mwworld/class.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/refdata.hpp" + +#include "../mwmechanics/drawstate.hpp" + +namespace MWRender +{ + + ViewOverShoulderController::ViewOverShoulderController(Camera* camera) : + mCamera(camera), mMode(Mode::RightShoulder), + mAutoSwitchShoulder(Settings::Manager::getBool("auto switch shoulder", "Camera")), + mOverShoulderHorizontalOffset(30.f), mOverShoulderVerticalOffset(-10.f) + { + std::stringstream offset(Settings::Manager::getString("view over shoulder offset", "Camera")); + offset >> mOverShoulderHorizontalOffset >> mOverShoulderVerticalOffset; + mDefaultShoulderIsRight = mOverShoulderHorizontalOffset >= 0; + mOverShoulderHorizontalOffset = std::abs(mOverShoulderHorizontalOffset); + + mCamera->enableDynamicCameraDistance(true); + mCamera->enableCrosshairInThirdPersonMode(true); + } + + void ViewOverShoulderController::update() + { + if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson()) + return; + + Mode newMode = mMode; + auto ptr = mCamera->getTrackingPtr(); + if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing) + newMode = Mode::Combat; + else if (MWBase::Environment::get().getWorld()->isSwimming(ptr)) + newMode = Mode::Swimming; + else if (mMode == Mode::Combat || mMode == Mode::Swimming) + newMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; + if (newMode != mMode) + { + if (newMode == Mode::Combat || mMode == Mode::Combat) + mCamera->setFocalPointTransitionSpeed(5.f); + else + mCamera->setFocalPointTransitionSpeed(1.f); + mMode = newMode; + } + + if (mAutoSwitchShoulder && (mMode == Mode::LeftShoulder || mMode == Mode::RightShoulder)) + trySwitchShoulder(); + + osg::Vec2d focalPointTargetOffset; + switch (mMode) + { + case Mode::RightShoulder: + mCamera->setFocalPointTargetOffset({mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset}); + break; + case Mode::LeftShoulder: + mCamera->setFocalPointTargetOffset({-mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset}); + break; + case Mode::Combat: + case Mode::Swimming: + default: + mCamera->setFocalPointTargetOffset({0, 15}); + } + } + + void ViewOverShoulderController::trySwitchShoulder() + { + const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit + const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance + + auto orient = osg::Quat(mCamera->getYaw(), osg::Vec3d(0,0,1)); + osg::Vec3d playerPos = mCamera->getFocalPoint() - mCamera->getFocalPointOffset(); + + MWBase::World* world = MWBase::Environment::get().getWorld(); + osg::Vec3d sideOffset = orient * osg::Vec3d(world->getHalfExtents(mCamera->getTrackingPtr()).x() - 1, 0, 0); + float rayRight = world->getDistToNearestRayHit( + playerPos + sideOffset, orient * osg::Vec3d(1, 1, 0), limitToSwitchBack + 1); + float rayLeft = world->getDistToNearestRayHit( + playerPos - sideOffset, orient * osg::Vec3d(-1, 1, 0), limitToSwitchBack + 1); + float rayForward = world->getDistToNearestRayHit( + playerPos, orient * osg::Vec3d(0, 1, 0), limitToSwitchBack + 1); + + if (rayLeft < limitToSwitch && rayRight > limitToSwitchBack) + mMode = Mode::RightShoulder; + else if (rayRight < limitToSwitch && rayLeft > limitToSwitchBack) + mMode = Mode::LeftShoulder; + else if (rayLeft > limitToSwitchBack && rayRight > limitToSwitchBack && rayForward > limitToSwitchBack) + mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; + } + +} \ No newline at end of file diff --git a/apps/openmw/mwrender/viewovershoulder.hpp b/apps/openmw/mwrender/viewovershoulder.hpp new file mode 100644 index 000000000..80ac30865 --- /dev/null +++ b/apps/openmw/mwrender/viewovershoulder.hpp @@ -0,0 +1,30 @@ +#ifndef VIEWOVERSHOULDER_H +#define VIEWOVERSHOULDER_H + +#include "camera.hpp" + +namespace MWRender +{ + + class ViewOverShoulderController + { + public: + ViewOverShoulderController(Camera* camera); + + void update(); + + private: + void trySwitchShoulder(); + enum class Mode { RightShoulder, LeftShoulder, Combat, Swimming }; + + Camera* mCamera; + Mode mMode; + bool mAutoSwitchShoulder; + float mOverShoulderHorizontalOffset; + float mOverShoulderVerticalOffset; + bool mDefaultShoulderIsRight; + }; + +} + +#endif // VIEWOVERSHOULDER_H diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 80a9a01ae..209ab538e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1869,44 +1869,13 @@ namespace MWWorld float cameraObstacleLimit = mRendering->getNearClipDistance() * 2.5f; float focalObstacleLimit = std::max(cameraObstacleLimit, 10.0f); + // Adjust focal point. osg::Vec3d focal = camera->getFocalPoint(); osg::Vec3d focalOffset = camera->getFocalPointOffset(); - osg::Vec3d playerPos = focal - focalOffset; - - static const bool autoSwitchShoulder = Settings::Manager::getBool("auto switch shoulder", "Camera"); - if (camera->getThirdPersonViewMode() == MWRender::Camera::ThirdPersonViewMode::OverShoulder - && autoSwitchShoulder && !camera->isVanityOrPreviewModeEnabled()) - { - const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit - const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance - auto orient = osg::Quat(camera->getYaw(), osg::Vec3d(0,0,1)); - int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_Door | MWPhysics::CollisionType_HeightMap; - MWPhysics::PhysicsSystem::RayResult rayRight = mPhysics->castRay( - playerPos + orient * osg::Vec3d(28, 0, 0), - playerPos + orient * osg::Vec3d(limitToSwitchBack, limitToSwitchBack, 0), - {}, {}, mask); - MWPhysics::PhysicsSystem::RayResult rayLeft = mPhysics->castRay( - playerPos + orient * osg::Vec3d(-28, 0, 0), - playerPos + orient * osg::Vec3d(-limitToSwitchBack, limitToSwitchBack, 0), - {}, {}, mask); - MWPhysics::PhysicsSystem::RayResult rayForward = mPhysics->castRay( - playerPos, playerPos + orient * osg::Vec3d(0, limitToSwitchBack, 0), - {}, {}, mask); - bool rightTooClose = rayRight.mHit && (rayRight.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch; - bool leftTooClose = rayLeft.mHit && (rayLeft.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch; - if (!rayRight.mHit && leftTooClose) - camera->switchToRightShoulder(); - else if (!rayLeft.mHit && rightTooClose) - camera->switchToLeftShoulder(); - else if (!rayRight.mHit && !rayLeft.mHit && !rayForward.mHit) - camera->switchToDefaultShoulder(); - } - - // Adjust focal point. float offsetLen = focalOffset.length(); if (offsetLen > 0) { - MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(playerPos, focal, focalObstacleLimit); + MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal - focalOffset, focal, focalObstacleLimit); if (result.mHit) { double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen; From 173c1fdabb507f0dd204a0219b06d96af33a47fe Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 12 Jul 2020 01:55:20 +0200 Subject: [PATCH 090/107] Make transition in 'auto switch shoulder' smoother. --- apps/openmw/mwrender/camera.cpp | 35 +++++++++++++++++++++-- apps/openmw/mwrender/camera.hpp | 12 ++++++-- apps/openmw/mwrender/viewovershoulder.cpp | 27 ++++++++--------- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 3b3f1aec9..1e6ea2843 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -64,7 +64,8 @@ namespace MWRender mCameraDistance(0.f), mFocalPointCurrentOffset(osg::Vec2d()), mFocalPointTargetOffset(osg::Vec2d()), - mFocalPointTransitionSpeed(1.f), + mFocalPointTransitionSpeedCoef(1.f), + mPreviousTransitionInfluence(0.f), mSmoothedSpeed(0.f), mDynamicCameraDistanceEnabled(false), mShowCrosshairInThirdPersonMode(false) @@ -221,16 +222,44 @@ namespace MWRender mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); } + void Camera::setFocalPointTargetOffset(osg::Vec2d v) + { + mFocalPointTargetOffset = v; + mPreviousTransitionSpeed = mFocalPointTransitionSpeed; + mPreviousTransitionInfluence = 1.0f; + } + void Camera::updateFocalPointOffset(float duration) { + if (duration <= 0) + return; + + osg::Vec2d oldOffset = mFocalPointCurrentOffset; + + if (mPreviousTransitionInfluence > 0) + { + mFocalPointCurrentOffset -= mPreviousExtraOffset; + mPreviousExtraOffset = mPreviousExtraOffset / mPreviousTransitionInfluence + mPreviousTransitionSpeed * duration; + mPreviousTransitionInfluence = + std::max(0.f, mPreviousTransitionInfluence - duration * mFocalPointTransitionSpeedCoef); + mPreviousExtraOffset *= mPreviousTransitionInfluence; + mFocalPointCurrentOffset += mPreviousExtraOffset; + } + osg::Vec2d delta = mFocalPointTargetOffset - mFocalPointCurrentOffset; if (delta.length2() > 0) { - float coef = duration * (1.0 + 5.0 / delta.length()) * mFocalPointTransitionSpeed; + float coef = duration * (1.0 + 5.0 / delta.length()) * + mFocalPointTransitionSpeedCoef * (1.0f - mPreviousTransitionInfluence); mFocalPointCurrentOffset += delta * std::min(coef, 1.0f); } else - mFocalPointTransitionSpeed = 1.f; + { + mPreviousExtraOffset = osg::Vec2d(); + mPreviousTransitionInfluence = 0.f; + } + + mFocalPointTransitionSpeed = (mFocalPointCurrentOffset - oldOffset) / duration; } void Camera::toggleViewMode(bool force) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 5f3c5d6e4..bd70d6d9a 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -58,7 +58,13 @@ namespace MWRender osg::Vec3d mFocalPointAdjustment; osg::Vec2d mFocalPointCurrentOffset; osg::Vec2d mFocalPointTargetOffset; - float mFocalPointTransitionSpeed; + float mFocalPointTransitionSpeedCoef; + + // This fields are used to make focal point transition smooth if previous transition was not finished. + float mPreviousTransitionInfluence; + osg::Vec2d mFocalPointTransitionSpeed; + osg::Vec2d mPreviousTransitionSpeed; + osg::Vec2d mPreviousExtraOffset; float mSmoothedSpeed; bool mDynamicCameraDistanceEnabled; @@ -75,8 +81,8 @@ namespace MWRender MWWorld::Ptr getTrackingPtr() const; - void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeed = v; } - void setFocalPointTargetOffset(osg::Vec2d v) { mFocalPointTargetOffset = v; } + void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; } + void setFocalPointTargetOffset(osg::Vec2d v); void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; } void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; } diff --git a/apps/openmw/mwrender/viewovershoulder.cpp b/apps/openmw/mwrender/viewovershoulder.cpp index f908b1430..5d7ec7117 100644 --- a/apps/openmw/mwrender/viewovershoulder.cpp +++ b/apps/openmw/mwrender/viewovershoulder.cpp @@ -28,6 +28,7 @@ namespace MWRender mCamera->enableDynamicCameraDistance(true); mCamera->enableCrosshairInThirdPersonMode(true); + mCamera->setFocalPointTargetOffset({mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset}); } void ViewOverShoulderController::update() @@ -35,27 +36,23 @@ namespace MWRender if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson()) return; - Mode newMode = mMode; + Mode oldMode = mMode; auto ptr = mCamera->getTrackingPtr(); if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing) - newMode = Mode::Combat; + mMode = Mode::Combat; else if (MWBase::Environment::get().getWorld()->isSwimming(ptr)) - newMode = Mode::Swimming; - else if (mMode == Mode::Combat || mMode == Mode::Swimming) - newMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; - if (newMode != mMode) - { - if (newMode == Mode::Combat || mMode == Mode::Combat) - mCamera->setFocalPointTransitionSpeed(5.f); - else - mCamera->setFocalPointTransitionSpeed(1.f); - mMode = newMode; - } - + mMode = Mode::Swimming; + else if (oldMode == Mode::Combat || oldMode == Mode::Swimming) + mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; if (mAutoSwitchShoulder && (mMode == Mode::LeftShoulder || mMode == Mode::RightShoulder)) trySwitchShoulder(); + if (oldMode == mMode) return; + + if (oldMode == Mode::Combat || mMode == Mode::Combat) + mCamera->setFocalPointTransitionSpeed(5.f); + else + mCamera->setFocalPointTransitionSpeed(1.f); - osg::Vec2d focalPointTargetOffset; switch (mMode) { case Mode::RightShoulder: From 383fa3d3ab040e41880bc55d6ac74be82f4d4be0 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 12 Jul 2020 21:03:18 +0200 Subject: [PATCH 091/107] Make 'zoom out when move' configurable. --- apps/openmw/mwrender/camera.cpp | 3 ++- apps/openmw/mwrender/camera.hpp | 1 + docs/source/reference/modding/settings/camera.rst | 12 ++++++++++++ files/settings-default.cfg | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 1e6ea2843..7531e712b 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -67,6 +67,7 @@ namespace MWRender mFocalPointTransitionSpeedCoef(1.f), mPreviousTransitionInfluence(0.f), mSmoothedSpeed(0.f), + mZoomOutWhenMoveCoef(Settings::Manager::getFloat("zoom out when move coef", "Camera")), mDynamicCameraDistanceEnabled(false), mShowCrosshairInThirdPersonMode(false) { @@ -461,7 +462,7 @@ namespace MWRender float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f; float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed; - float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f; + float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * mZoomOutWhenMoveCoef; return pitchCorrection + speedCorrection; } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index bd70d6d9a..59fa53047 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -67,6 +67,7 @@ namespace MWRender osg::Vec2d mPreviousExtraOffset; float mSmoothedSpeed; + float mZoomOutWhenMoveCoef; bool mDynamicCameraDistanceEnabled; bool mShowCrosshairInThirdPersonMode; diff --git a/docs/source/reference/modding/settings/camera.rst b/docs/source/reference/modding/settings/camera.rst index 21fec8fd6..be636cef4 100644 --- a/docs/source/reference/modding/settings/camera.rst +++ b/docs/source/reference/modding/settings/camera.rst @@ -162,3 +162,15 @@ When player is close to an obstacle, automatically switches camera to the should This setting can only be configured by editing the settings configuration file. +zoom out when move coef +----------------------- + +:Type: floating point +:Range: Any +:Default: 20 + +This setting makes difference only in third person mode if 'view over shoulder' is enabled. +Slightly pulls camera away (or closer in case of negative value) when the character moves. To disable set it to zero. + +This setting can only be configured by editing the settings configuration file. + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index b960946d8..35be128a8 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -45,6 +45,9 @@ view over shoulder offset = 30 -10 # Switch shoulder automatically when player is close to an obstacle. auto switch shoulder = true +# Slightly pulls camera away when the character moves. Works only in 'view over shoulder' mode. Set to 0 to disable. +zoom out when move coef = 20 + [Cells] # Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled. From 7676a36b32bf86c79672878f7f4e696ce69283bc Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 22:38:48 +0100 Subject: [PATCH 092/107] Time a build with the reduced cache --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2bdfa990e..313f21d4f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -172,4 +172,4 @@ Windows_MSBuild_RelWithDebInfo: extends: - .Windows_MSBuild_Base variables: - config: "RelWithDebInfo" \ No newline at end of file + config: "RelWithDebInfo" From 0d1fb31358b02b76835d4df70965bd4c4fd73ca2 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 12 Jul 2020 22:39:24 +0100 Subject: [PATCH 093/107] Revert "Revert "Build the CS again."" Maybe the reduced cache makes it fit. This reverts commit 20859bbc50341745b3be00ef8995d1f9d698bd8b. --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 313f21d4f..cfb304af7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ MacOS: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -129,7 +129,7 @@ Windows_Ninja_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config --target openmw openmw-launcher openmw-wizard openmw-iniimporter + - cmake --build . --config $config - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From c132646b974de5641b7c3da2343fa5e44ddd8f91 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 01:44:08 +0100 Subject: [PATCH 094/107] Time commands --- .gitlab-ci.yml | 80 +++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cfb304af7..3ae240162 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,30 +50,34 @@ MacOS: tags: - windows before_script: - - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" - - choco install git --force --params "/GitAndUnixToolsOnPath" -y - - choco install 7zip -y - - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y - - choco install vswhere -y - - choco install ninja -y - - choco install python -y - - refreshenv + - Get-Date -Format "HH:mm:ss" + - Measure-Command -Expression { Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" | Out-Default } + - Measure-Command -Expression { choco install git --force --params "/GitAndUnixToolsOnPath" -y | Out-Default } + - Measure-Command -Expression { choco install 7zip -y | Out-Default } + - Measure-Command -Expression { choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y | Out-Default } + - Measure-Command -Expression { choco install vswhere -y | Out-Default } + - Measure-Command -Expression { choco install ninja -y | Out-Default } + - Measure-Command -Expression { choco install python -y | Out-Default } + - Measure-Command -Expression { refreshenv | Out-Default } + - Get-Date -Format "HH:mm:ss" stage: build script: - - $time = (Get-Date -Format "HH:mm:ss") - - echo ${time} - - echo "started by ${GITLAB_USER_NAME}" - - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - - cd MSVC2019_64_Ninja - - .\ActivateMSVC.ps1 - - cmake --build . --config $config - - cd $config + - Get-Date -Format "HH:mm:ss" + - Measure-Command -Expression { $time = (Get-Date -Format "HH:mm:ss") | Out-Default } + - Measure-Command -Expression { echo ${time} | Out-Default } + - Measure-Command -Expression { echo "started by ${GITLAB_USER_NAME}" | Out-Default } + - Measure-Command -Expression { sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N | Out-Default } + - Measure-Command -Expression { cd MSVC2019_64_Ninja | Out-Default } + - Measure-Command -Expression { .\ActivateMSVC.ps1 | Out-Default } + - Measure-Command -Expression { cmake --build . --config $config | Out-Default } + - Measure-Command -Expression { cd $config | Out-Default } - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' - Get-ChildItem -Recurse *.pdb | Remove-Item + Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' | Out-Default } + Measure-Command -Expression { Get-ChildItem -Recurse *.pdb | Remove-Item | Out-Default } } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' + - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' | Out-Default } + - Get-Date -Format "HH:mm:ss" cache: key: ninja-v2 paths: @@ -115,28 +119,32 @@ Windows_Ninja_RelWithDebInfo: tags: - windows before_script: - - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" - - choco install git --force --params "/GitAndUnixToolsOnPath" -y - - choco install 7zip -y - - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y - - choco install vswhere -y - - choco install python -y - - refreshenv + - Get-Date -Format "HH:mm:ss" + - Measure-Command -Expression { Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" | Out-Default } + - Measure-Command -Expression { choco install git --force --params "/GitAndUnixToolsOnPath" -y | Out-Default } + - Measure-Command -Expression { choco install 7zip -y | Out-Default } + - Measure-Command -Expression { choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y | Out-Default } + - Measure-Command -Expression { choco install vswhere -y | Out-Default } + - Measure-Command -Expression { choco install python -y | Out-Default } + - Measure-Command -Expression { refreshenv | Out-Default } + - Get-Date -Format "HH:mm:ss" stage: build script: - - $time = (Get-Date -Format "HH:mm:ss") - - echo ${time} - - echo "started by ${GITLAB_USER_NAME}" - - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - - cd MSVC2019_64 - - cmake --build . --config $config - - cd $config + - Get-Date -Format "HH:mm:ss" + - Measure-Command -Expression { $time = (Get-Date -Format "HH:mm:ss") | Out-Default } + - Measure-Command -Expression { echo ${time} | Out-Default } + - Measure-Command -Expression { echo "started by ${GITLAB_USER_NAME}" | Out-Default } + - Measure-Command -Expression { sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V | Out-Default } + - Measure-Command -Expression { cd MSVC2019_64 | Out-Default } + - Measure-Command -Expression { cmake --build . --config $config | Out-Default } + - Measure-Command -Expression { cd $config | Out-Default } - | if (Get-ChildItem -Recurse *.pdb) { - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' - Get-ChildItem -Recurse *.pdb | Remove-Item + Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' | Out-Default } + Measure-Command -Expression { Get-ChildItem -Recurse *.pdb | Remove-Item | Out-Default } } - - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' + - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' | Out-Default } + - Get-Date -Format "HH:mm:ss" cache: key: msbuild-v2 paths: From 6a8e736bd247b2667d5d9f0abaf0e008e81fab60 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 16:53:23 +0100 Subject: [PATCH 095/107] Revert "Time commands" This reverts commit c132646b974de5641b7c3da2343fa5e44ddd8f91. --- .gitlab-ci.yml | 80 +++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3ae240162..cfb304af7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,34 +50,30 @@ MacOS: tags: - windows before_script: - - Get-Date -Format "HH:mm:ss" - - Measure-Command -Expression { Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" | Out-Default } - - Measure-Command -Expression { choco install git --force --params "/GitAndUnixToolsOnPath" -y | Out-Default } - - Measure-Command -Expression { choco install 7zip -y | Out-Default } - - Measure-Command -Expression { choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y | Out-Default } - - Measure-Command -Expression { choco install vswhere -y | Out-Default } - - Measure-Command -Expression { choco install ninja -y | Out-Default } - - Measure-Command -Expression { choco install python -y | Out-Default } - - Measure-Command -Expression { refreshenv | Out-Default } - - Get-Date -Format "HH:mm:ss" + - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco install git --force --params "/GitAndUnixToolsOnPath" -y + - choco install 7zip -y + - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y + - choco install vswhere -y + - choco install ninja -y + - choco install python -y + - refreshenv stage: build script: - - Get-Date -Format "HH:mm:ss" - - Measure-Command -Expression { $time = (Get-Date -Format "HH:mm:ss") | Out-Default } - - Measure-Command -Expression { echo ${time} | Out-Default } - - Measure-Command -Expression { echo "started by ${GITLAB_USER_NAME}" | Out-Default } - - Measure-Command -Expression { sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N | Out-Default } - - Measure-Command -Expression { cd MSVC2019_64_Ninja | Out-Default } - - Measure-Command -Expression { .\ActivateMSVC.ps1 | Out-Default } - - Measure-Command -Expression { cmake --build . --config $config | Out-Default } - - Measure-Command -Expression { cd $config | Out-Default } + - $time = (Get-Date -Format "HH:mm:ss") + - echo ${time} + - echo "started by ${GITLAB_USER_NAME}" + - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N + - cd MSVC2019_64_Ninja + - .\ActivateMSVC.ps1 + - cmake --build . --config $config + - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' | Out-Default } - Measure-Command -Expression { Get-ChildItem -Recurse *.pdb | Remove-Item | Out-Default } + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' + Get-ChildItem -Recurse *.pdb | Remove-Item } - - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' | Out-Default } - - Get-Date -Format "HH:mm:ss" + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: key: ninja-v2 paths: @@ -119,32 +115,28 @@ Windows_Ninja_RelWithDebInfo: tags: - windows before_script: - - Get-Date -Format "HH:mm:ss" - - Measure-Command -Expression { Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" | Out-Default } - - Measure-Command -Expression { choco install git --force --params "/GitAndUnixToolsOnPath" -y | Out-Default } - - Measure-Command -Expression { choco install 7zip -y | Out-Default } - - Measure-Command -Expression { choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y | Out-Default } - - Measure-Command -Expression { choco install vswhere -y | Out-Default } - - Measure-Command -Expression { choco install python -y | Out-Default } - - Measure-Command -Expression { refreshenv | Out-Default } - - Get-Date -Format "HH:mm:ss" + - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" + - choco install git --force --params "/GitAndUnixToolsOnPath" -y + - choco install 7zip -y + - choco install cmake.install --installargs 'ADD_CMAKE_TO_PATH=System' -y + - choco install vswhere -y + - choco install python -y + - refreshenv stage: build script: - - Get-Date -Format "HH:mm:ss" - - Measure-Command -Expression { $time = (Get-Date -Format "HH:mm:ss") | Out-Default } - - Measure-Command -Expression { echo ${time} | Out-Default } - - Measure-Command -Expression { echo "started by ${GITLAB_USER_NAME}" | Out-Default } - - Measure-Command -Expression { sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V | Out-Default } - - Measure-Command -Expression { cd MSVC2019_64 | Out-Default } - - Measure-Command -Expression { cmake --build . --config $config | Out-Default } - - Measure-Command -Expression { cd $config | Out-Default } + - $time = (Get-Date -Format "HH:mm:ss") + - echo ${time} + - echo "started by ${GITLAB_USER_NAME}" + - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V + - cd MSVC2019_64 + - cmake --build . --config $config + - cd $config - | if (Get-ChildItem -Recurse *.pdb) { - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' | Out-Default } - Measure-Command -Expression { Get-ChildItem -Recurse *.pdb | Remove-Item | Out-Default } + 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}_symbols.zip '*.pdb' + Get-ChildItem -Recurse *.pdb | Remove-Item } - - Measure-Command -Expression { 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' | Out-Default } - - Get-Date -Format "HH:mm:ss" + - 7z a -tzip ..\..\OpenMW_MSVC2019_64_${config}_${CI_COMMIT_REF_NAME}_${CI_JOB_ID}.zip '*' cache: key: msbuild-v2 paths: From 5549ddab97f8d9b5cf0581219497deb92ccf6fd9 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 17:08:46 +0100 Subject: [PATCH 096/107] Split CS into separate jobs so build time is less tight. Now we have twelve Windows jobs. Yay! --- .gitlab-ci.yml | 70 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cfb304af7..9d0645eda 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,6 +46,12 @@ MacOS: paths: - build/OpenMW-*.dmg +variables: &engine-targets + targets: openmw openmw-essimporter openmw-iniimporter openmw-launcher openmw-wizard + +variables: &cs-targets + targets: openmw-cs bsatool esmtool niftest + .Windows_Ninja_Base: tags: - windows @@ -66,7 +72,7 @@ MacOS: - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config + - cmake --build . --config $config --target $targets - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -93,22 +99,46 @@ MacOS: - MSVC2019_64_Ninja/*/*/*/*/*/*/*.log - MSVC2019_64_Ninja/*/*/*/*/*/*/*/*.log -Windows_Ninja_Release: +Windows_Ninja_Engine_Release: + extends: + - .Windows_Ninja_Base + variables: + <<: *engine-targets + config: "Release" + +Windows_Ninja_Engine_Debug: + extends: + - .Windows_Ninja_Base + variables: + <<: *engine-targets + config: "Debug" + +Windows_Ninja_Engine_RelWithDebInfo: + extends: + - .Windows_Ninja_Base + variables: + <<: *engine-targets + config: "RelWithDebInfo" + +Windows_Ninja_CS_Release: extends: - .Windows_Ninja_Base variables: + <<: *cs-targets config: "Release" -Windows_Ninja_Debug: +Windows_Ninja_CS_Debug: extends: - .Windows_Ninja_Base variables: + <<: *cs-targets config: "Debug" -Windows_Ninja_RelWithDebInfo: +Windows_Ninja_CS_RelWithDebInfo: extends: - .Windows_Ninja_Base variables: + <<: *cs-targets config: "RelWithDebInfo" .Windows_MSBuild_Base: @@ -129,7 +159,7 @@ Windows_Ninja_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config + - cmake --build . --config $config --target $targets - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -156,20 +186,44 @@ Windows_Ninja_RelWithDebInfo: - MSVC2019_64/*/*/*/*/*/*/*.log - MSVC2019_64/*/*/*/*/*/*/*/*.log -Windows_MSBuild_Release: +Windows_MSBuild_Engine_Release: + extends: + - .Windows_MSBuild_Base + variables: + <<: *engine-targets + config: "Release" + +Windows_MSBuild_Engine_Debug: + extends: + - .Windows_MSBuild_Base + variables: + <<: *engine-targets + config: "Debug" + +Windows_MSBuild_Engine_RelWithDebInfo: + extends: + - .Windows_MSBuild_Base + variables: + <<: *engine-targets + config: "RelWithDebInfo" + +Windows_MSBuild_CS_Release: extends: - .Windows_MSBuild_Base variables: + <<: *cs-targets config: "Release" -Windows_MSBuild_Debug: +Windows_MSBuild_CS_Debug: extends: - .Windows_MSBuild_Base variables: + <<: *cs-targets config: "Debug" -Windows_MSBuild_RelWithDebInfo: +Windows_MSBuild_CS_RelWithDebInfo: extends: - .Windows_MSBuild_Base variables: + <<: *cs-targets config: "RelWithDebInfo" From a43766bbc82f9e672939d3bea517a38fedbe53b9 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 18:02:05 +0100 Subject: [PATCH 097/107] Try removing bashism reliance --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d0645eda..e70892f18 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,10 +47,10 @@ MacOS: - build/OpenMW-*.dmg variables: &engine-targets - targets: openmw openmw-essimporter openmw-iniimporter openmw-launcher openmw-wizard + targets: "openmw", "openmw-essimporter", "openmw-iniimporter", "openmw-launcher", "openmw-wizard" variables: &cs-targets - targets: openmw-cs bsatool esmtool niftest + targets: "openmw-cs", "bsatool", "esmtool", "niftest" .Windows_Ninja_Base: tags: From a03fd0330299abd29fe924ff52cca4eeb9a56732 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 18:04:25 +0100 Subject: [PATCH 098/107] YAML wants lots of quotes --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e70892f18..90f1c5135 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,10 +47,10 @@ MacOS: - build/OpenMW-*.dmg variables: &engine-targets - targets: "openmw", "openmw-essimporter", "openmw-iniimporter", "openmw-launcher", "openmw-wizard" + targets: '"openmw", "openmw-essimporter", "openmw-iniimporter", "openmw-launcher", "openmw-wizard"' variables: &cs-targets - targets: "openmw-cs", "bsatool", "esmtool", "niftest" + targets: '"openmw-cs", "bsatool", "esmtool", "niftest"' .Windows_Ninja_Base: tags: From 1720e2e1fda17f7a2aa989d935b9970c65cfd661 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 18:47:42 +0100 Subject: [PATCH 099/107] CI kick --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 90f1c5135..1afb7b2ad 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -226,4 +226,4 @@ Windows_MSBuild_CS_RelWithDebInfo: - .Windows_MSBuild_Base variables: <<: *cs-targets - config: "RelWithDebInfo" + config: "RelWithDebInfo" \ No newline at end of file From b7c1c52439021970713276637eda4254c356a853 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 13 Jul 2020 20:04:23 +0200 Subject: [PATCH 100/107] Adjust actor rotation when flee by axis x Otherwise Cliff Racers can go underwater. --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aicombat.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25ed287ee..d9c1c5065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Bug #5499: Faction advance is available when requirements not met Bug #5502: Dead zone for analogue stick movement is too small Bug #5507: Sound volume is not clamped on ingame settings update + Bug #5531: Actors flee using current rotation by axis x Feature #390: 3rd person look "over the shoulder" Feature #2386: Distant Statics in the form of Object Paging Feature #5297: Add a search function to the "Datafiles" tab of the OpenMW launcher diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index a77539a1f..1ae27a9cb 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -344,6 +344,7 @@ namespace MWMechanics { storage.mFleeBlindRunTimer += duration; + storage.mMovement.mRotation[0] = -actor.getRefData().getPosition().rot[0]; storage.mMovement.mRotation[2] = osg::PI + getZAngleToDir(target.getRefData().getPosition().asVec3()-actor.getRefData().getPosition().asVec3()); storage.mMovement.mPosition[1] = 1; updateActorsMovement(actor, duration, storage); From 000b52fc05623e1993fb73036be340cc32eece67 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 22:03:48 +0100 Subject: [PATCH 101/107] Swap quotes around --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1afb7b2ad..01947e374 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,10 +47,10 @@ MacOS: - build/OpenMW-*.dmg variables: &engine-targets - targets: '"openmw", "openmw-essimporter", "openmw-iniimporter", "openmw-launcher", "openmw-wizard"' + targets: "'openmw', 'openmw-essimporter', 'openmw-iniimporter', 'openmw-launcher', 'openmw-wizard'" variables: &cs-targets - targets: '"openmw-cs", "bsatool", "esmtool", "niftest"' + targets: "'openmw-cs', 'bsatool', 'esmtool', 'niftest'" .Windows_Ninja_Base: tags: From cd4ab320d8b8b4cf3391d1b11becfec7e2231ba7 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Jul 2020 22:34:58 +0100 Subject: [PATCH 102/107] Don't bother trying to set a PowerShell array from YAML Just set a string and split it in the script. --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 01947e374..e16aefcc1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,10 +47,10 @@ MacOS: - build/OpenMW-*.dmg variables: &engine-targets - targets: "'openmw', 'openmw-essimporter', 'openmw-iniimporter', 'openmw-launcher', 'openmw-wizard'" + targets: "openmw,openmw-essimporter,openmw-iniimporter,openmw-launcher,openmw-wizard" variables: &cs-targets - targets: "'openmw-cs', 'bsatool', 'esmtool', 'niftest'" + targets: "openmw-cs,bsatool,esmtool,niftest" .Windows_Ninja_Base: tags: @@ -72,7 +72,7 @@ variables: &cs-targets - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V -N - cd MSVC2019_64_Ninja - .\ActivateMSVC.ps1 - - cmake --build . --config $config --target $targets + - cmake --build . --config $config --target ($targets.Split(',')) - cd $config - | if (Get-ChildItem -Recurse *.pdb) { @@ -159,7 +159,7 @@ Windows_Ninja_CS_RelWithDebInfo: - echo "started by ${GITLAB_USER_NAME}" - sh CI/before_script.msvc.sh -c $config -p Win64 -v 2019 -k -V - cd MSVC2019_64 - - cmake --build . --config $config --target $targets + - cmake --build . --config $config --target ($targets.Split(',')) - cd $config - | if (Get-ChildItem -Recurse *.pdb) { From b05d071e69c5c94ccfb9adb8e1c2c859627b91df Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 14 Jul 2020 10:53:01 +0400 Subject: [PATCH 103/107] Resume failed scripts execution after game reload (feature #5524) --- CHANGELOG.md | 1 + apps/openmw/mwbase/scriptmanager.hpp | 2 ++ apps/openmw/mwscript/scriptmanagerimp.cpp | 24 ++++++++++++++++------- apps/openmw/mwscript/scriptmanagerimp.hpp | 17 +++++++++++++++- apps/openmw/mwstate/statemanagerimp.cpp | 2 +- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25ed287ee..e6ec9cf57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Feature #5445: Handle NiLines Feature #5457: Realistic diagonal movement Feature #5486: Fixes trainers to choose their training skills based on their base skill points + Feature #5524: Resume failed script execution after reload Task #5480: Drop Qt4 support 0.46.0 diff --git a/apps/openmw/mwbase/scriptmanager.hpp b/apps/openmw/mwbase/scriptmanager.hpp index da3454d34..ac8333ed1 100644 --- a/apps/openmw/mwbase/scriptmanager.hpp +++ b/apps/openmw/mwbase/scriptmanager.hpp @@ -35,6 +35,8 @@ namespace MWBase virtual ~ScriptManager() {} + virtual void clear() = 0; + virtual bool run (const std::string& name, Interpreter::Context& interpreterContext) = 0; ///< Run the script with the given name (compile first, if not compiled yet) diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index b69eb7f60..0077b7cd0 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -79,8 +79,8 @@ namespace MWScript if (Success) { std::vector code; - mParser.getCode (code); - mScripts.insert (std::make_pair (name, std::make_pair (code, mParser.getLocals()))); + mParser.getCode(code); + mScripts.emplace(name, CompiledScript(code, mParser.getLocals())); return true; } @@ -100,7 +100,7 @@ namespace MWScript { // failed -> ignore script from now on. std::vector empty; - mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals()))); + mScripts.emplace(name, CompiledScript(empty, Compiler::Locals())); return false; } @@ -109,7 +109,7 @@ namespace MWScript } // execute script - if (!iter->second.first.empty()) + if (!iter->second.mByteCode.empty() && iter->second.mActive) try { if (!mOpcodesInstalled) @@ -118,7 +118,7 @@ namespace MWScript mOpcodesInstalled = true; } - mInterpreter.run (&iter->second.first[0], iter->second.first.size(), interpreterContext); + mInterpreter.run (&iter->second.mByteCode[0], iter->second.mByteCode.size(), interpreterContext); return true; } catch (const MissingImplicitRefError& e) @@ -129,11 +129,21 @@ namespace MWScript { Log(Debug::Error) << "Execution of script " << name << " failed: " << e.what(); - iter->second.first.clear(); // don't execute again. + iter->second.mActive = false; // don't execute again. } return false; } + void ScriptManager::clear() + { + for (auto& script : mScripts) + { + script.second.mActive = true; + } + + mGlobalScripts.clear(); + } + std::pair ScriptManager::compileAll() { int count = 0; @@ -163,7 +173,7 @@ namespace MWScript ScriptCollection::iterator iter = mScripts.find (name2); if (iter!=mScripts.end()) - return iter->second.second; + return iter->second.mLocals; } { diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index 27567a191..50cc7afa8 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -41,7 +41,20 @@ namespace MWScript Interpreter::Interpreter mInterpreter; bool mOpcodesInstalled; - typedef std::pair, Compiler::Locals> CompiledScript; + struct CompiledScript + { + std::vector mByteCode; + Compiler::Locals mLocals; + bool mActive; + + CompiledScript(const std::vector& code, const Compiler::Locals& locals) + { + mByteCode = code; + mLocals = locals; + mActive = true; + } + }; + typedef std::map ScriptCollection; ScriptCollection mScripts; @@ -55,6 +68,8 @@ namespace MWScript Compiler::Context& compilerContext, int warningsMode, const std::vector& scriptBlacklist); + virtual void clear(); + virtual bool run (const std::string& name, Interpreter::Context& interpreterContext); ///< Run the script with the given name (compile first, if not compiled yet) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 9974b8f16..d59704bf1 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -47,7 +47,7 @@ void MWState::StateManager::cleanup (bool force) MWBase::Environment::get().getSoundManager()->clear(); MWBase::Environment::get().getDialogueManager()->clear(); MWBase::Environment::get().getJournal()->clear(); - MWBase::Environment::get().getScriptManager()->getGlobalScripts().clear(); + MWBase::Environment::get().getScriptManager()->clear(); MWBase::Environment::get().getWorld()->clear(); MWBase::Environment::get().getWindowManager()->clear(); MWBase::Environment::get().getInputManager()->clear(); From a83b32074f825e1c194f457ba1db1c9c0bf5cf23 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Tue, 14 Jul 2020 22:22:52 +0200 Subject: [PATCH 104/107] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5262fe462..c98dfbe3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Feature #5457: Realistic diagonal movement Feature #5486: Fixes trainers to choose their training skills based on their base skill points Feature #5524: Resume failed script execution after reload + Feature #5525: Search fields tweaks (utf-8) Task #5480: Drop Qt4 support 0.46.0 From 9240833bda3375e57781c015bdb95d83a133038e Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 12 Jul 2020 15:25:14 +0200 Subject: [PATCH 105/107] Init sound by a single object --- apps/openmw/mwsound/sound.hpp | 90 ++++++++++--------------- apps/openmw/mwsound/soundmanagerimp.cpp | 77 +++++++++++++++++---- 2 files changed, 100 insertions(+), 67 deletions(-) diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index 7324b6747..9d264e1b6 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -11,85 +11,65 @@ namespace MWSound inline int operator&(int a, PlayMode b) { return a & static_cast(b); } inline int operator&(PlayMode a, PlayMode b) { return static_cast(a) & static_cast(b); } + struct SoundParams + { + osg::Vec3f mPos; + float mVolume = 1; + float mBaseVolume = 1; + float mPitch = 1; + float mMinDistance = 1; + float mMaxDistance = 1000; + int mFlags = 0; + float mFadeOutTime = 0; + }; + class SoundBase { SoundBase& operator=(const SoundBase&) = delete; SoundBase(const SoundBase&) = delete; SoundBase(SoundBase&&) = delete; - osg::Vec3f mPos; - float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */ - float mBaseVolume; - float mPitch; - float mMinDistance; - float mMaxDistance; - int mFlags; - - float mFadeOutTime; + SoundParams mParams; protected: - Sound_Instance mHandle; + Sound_Instance mHandle = nullptr; friend class OpenAL_Output; public: - void setPosition(const osg::Vec3f &pos) { mPos = pos; } - void setVolume(float volume) { mVolume = volume; } - void setBaseVolume(float volume) { mBaseVolume = volume; } - void setFadeout(float duration) { mFadeOutTime = duration; } + void setPosition(const osg::Vec3f &pos) { mParams.mPos = pos; } + void setVolume(float volume) { mParams.mVolume = volume; } + void setBaseVolume(float volume) { mParams.mBaseVolume = volume; } + void setFadeout(float duration) { mParams.mFadeOutTime = duration; } void updateFade(float duration) { - if(mFadeOutTime > 0.0f) + if (mParams.mFadeOutTime > 0.0f) { - float soundDuration = std::min(duration, mFadeOutTime); - mVolume *= (mFadeOutTime-soundDuration) / mFadeOutTime; - mFadeOutTime -= soundDuration; + float soundDuration = std::min(duration, mParams.mFadeOutTime); + mParams.mVolume *= (mParams.mFadeOutTime - soundDuration) / mParams.mFadeOutTime; + mParams.mFadeOutTime -= soundDuration; } } - const osg::Vec3f &getPosition() const { return mPos; } - float getRealVolume() const { return mVolume * mBaseVolume; } - float getPitch() const { return mPitch; } - float getMinDistance() const { return mMinDistance; } - float getMaxDistance() const { return mMaxDistance; } + const osg::Vec3f &getPosition() const { return mParams.mPos; } + float getRealVolume() const { return mParams.mVolume * mParams.mBaseVolume; } + float getPitch() const { return mParams.mPitch; } + float getMinDistance() const { return mParams.mMinDistance; } + float getMaxDistance() const { return mParams.mMaxDistance; } MWSound::Type getPlayType() const - { return static_cast(mFlags&MWSound::Type::Mask); } - bool getUseEnv() const { return !(mFlags&MWSound::PlayMode::NoEnv); } - bool getIsLooping() const { return mFlags&MWSound::PlayMode::Loop; } - bool getDistanceCull() const { return mFlags&MWSound::PlayMode::RemoveAtDistance; } - bool getIs3D() const { return mFlags&Play_3D; } - - void init(const osg::Vec3f& pos, float vol, float basevol, float pitch, float mindist, float maxdist, int flags) - { - mPos = pos; - mVolume = vol; - mBaseVolume = basevol; - mPitch = pitch; - mMinDistance = mindist; - mMaxDistance = maxdist; - mFlags = flags; - mFadeOutTime = 0.0f; - mHandle = nullptr; - } + { return static_cast(mParams.mFlags & MWSound::Type::Mask); } + bool getUseEnv() const { return !(mParams.mFlags & MWSound::PlayMode::NoEnv); } + bool getIsLooping() const { return mParams.mFlags & MWSound::PlayMode::Loop; } + bool getDistanceCull() const { return mParams.mFlags & MWSound::PlayMode::RemoveAtDistance; } + bool getIs3D() const { return mParams.mFlags & Play_3D; } - void init(float vol, float basevol, float pitch, int flags) + void init(const SoundParams& params) { - mPos = osg::Vec3f(0.0f, 0.0f, 0.0f); - mVolume = vol; - mBaseVolume = basevol; - mPitch = pitch; - mMinDistance = 1.0f; - mMaxDistance = 1000.0f; - mFlags = flags; - mFadeOutTime = 0.0f; + mParams = params; mHandle = nullptr; } - SoundBase() - : mPos(0.0f, 0.0f, 0.0f), mVolume(1.0f), mBaseVolume(1.0f), mPitch(1.0f) - , mMinDistance(1.0f), mMaxDistance(1000.0f), mFlags(0), mFadeOutTime(0.0f) - , mHandle(nullptr) - { } + SoundBase() = default; }; class Sound : public SoundBase { diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index a4241fef2..17aa184a7 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -290,13 +290,25 @@ namespace MWSound StreamPtr sound = getStreamRef(); if(playlocal) { - sound->init(1.0f, basevol, 1.0f, PlayMode::NoEnv|Type::Voice|Play_2D); + sound->init([&] { + SoundParams params; + params.mBaseVolume = basevol; + params.mFlags = PlayMode::NoEnv | Type::Voice | Play_2D; + return params; + } ()); played = mOutput->streamSound(decoder, sound.get(), true); } else { - sound->init(pos, 1.0f, basevol, 1.0f, minDistance, maxDistance, - PlayMode::Normal|Type::Voice|Play_3D); + sound->init([&] { + SoundParams params; + params.mPos = pos; + params.mBaseVolume = basevol; + params.mMinDistance = minDistance; + params.mMaxDistance = maxDistance; + params.mFlags = PlayMode::Normal | Type::Voice | Play_3D; + return params; + } ()); played = mOutput->streamSound3D(decoder, sound.get(), true); } if(!played) @@ -332,8 +344,12 @@ namespace MWSound decoder->open(filename); mMusic = getStreamRef(); - mMusic->init(1.0f, volumeFromType(Type::Music), 1.0f, - PlayMode::NoEnv|Type::Music|Play_2D); + mMusic->init([&] { + SoundParams params; + params.mBaseVolume = volumeFromType(Type::Music); + params.mFlags = PlayMode::NoEnv | Type::Music | Play_2D; + return params; + } ()); mOutput->streamSound(decoder, mMusic.get()); } @@ -561,7 +577,12 @@ namespace MWSound return nullptr; StreamPtr track = getStreamRef(); - track->init(1.0f, volumeFromType(type), 1.0f, PlayMode::NoEnv|type|Play_2D); + track->init([&] { + SoundParams params; + params.mBaseVolume = volumeFromType(type); + params.mFlags = PlayMode::NoEnv | type | Play_2D; + return params; + } ()); if(!mOutput->streamSound(decoder, track.get())) return nullptr; @@ -598,7 +619,14 @@ namespace MWSound stopSound(sfx, MWWorld::ConstPtr()); SoundPtr sound = getSoundRef(); - sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); + sound->init([&] { + SoundParams params; + params.mVolume = volume * sfx->mVolume; + params.mBaseVolume = volumeFromType(type); + params.mPitch = pitch; + params.mFlags = mode | type | Play_2D; + return params; + } ()); if(!mOutput->playSound(sound.get(), sfx->mHandle, offset)) return nullptr; @@ -635,13 +663,29 @@ namespace MWSound SoundPtr sound = getSoundRef(); if(!(mode&PlayMode::NoPlayerLocal) && ptr == MWMechanics::getPlayer()) { - sound->init(volume * sfx->mVolume, volumeFromType(type), pitch, mode|type|Play_2D); + sound->init([&] { + SoundParams params; + params.mVolume = volume * sfx->mVolume; + params.mBaseVolume = volumeFromType(type); + params.mPitch = pitch; + params.mFlags = mode | type | Play_2D; + return params; + } ()); played = mOutput->playSound(sound.get(), sfx->mHandle, offset); } else { - sound->init(objpos, volume * sfx->mVolume, volumeFromType(type), pitch, - sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); + sound->init([&] { + SoundParams params; + params.mPos = objpos; + params.mVolume = volume * sfx->mVolume; + params.mBaseVolume = volumeFromType(type); + params.mPitch = pitch; + params.mMinDistance = sfx->mMinDist; + params.mMaxDistance = sfx->mMaxDist; + params.mFlags = mode | type | Play_3D; + return params; + } ()); played = mOutput->playSound3D(sound.get(), sfx->mHandle, offset); } if(!played) @@ -670,8 +714,17 @@ namespace MWSound if(!sfx) return nullptr; SoundPtr sound = getSoundRef(); - sound->init(initialPos, volume * sfx->mVolume, volumeFromType(type), pitch, - sfx->mMinDist, sfx->mMaxDist, mode|type|Play_3D); + sound->init([&] { + SoundParams params; + params.mPos = initialPos; + params.mVolume = volume * sfx->mVolume; + params.mBaseVolume = volumeFromType(type); + params.mPitch = pitch; + params.mMinDistance = sfx->mMinDist; + params.mMaxDistance = sfx->mMaxDist; + params.mFlags = mode | type | Play_3D; + return params; + } ()); if(!mOutput->playSound3D(sound.get(), sfx->mHandle, offset)) return nullptr; From 68148f5ec70f50b392524a3eccb85776fc360746 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Thu, 16 Jul 2020 22:21:50 +0200 Subject: [PATCH 106/107] 1. Skip smooth camera transition after changing cell; 2. Fix 'zoom out when move' for extremely high speed; --- apps/openmw/mwrender/camera.cpp | 10 ++++++++++ apps/openmw/mwrender/camera.hpp | 2 ++ apps/openmw/mwworld/worldimp.cpp | 2 ++ 3 files changed, 14 insertions(+) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 7531e712b..9e03ff908 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -65,6 +65,7 @@ namespace MWRender mFocalPointCurrentOffset(osg::Vec2d()), mFocalPointTargetOffset(osg::Vec2d()), mFocalPointTransitionSpeedCoef(1.f), + mSkipFocalPointTransition(true), mPreviousTransitionInfluence(0.f), mSmoothedSpeed(0.f), mZoomOutWhenMoveCoef(Settings::Manager::getFloat("zoom out when move coef", "Camera")), @@ -219,6 +220,7 @@ namespace MWRender updateFocalPointOffset(duration); float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); + speed /= (1.f + speed / 500.f); float maxDelta = 300.f * duration; mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); } @@ -235,6 +237,14 @@ namespace MWRender if (duration <= 0) return; + if (mSkipFocalPointTransition) + { + mSkipFocalPointTransition = false; + mPreviousExtraOffset = osg::Vec2d(); + mPreviousTransitionInfluence = 0.f; + mFocalPointCurrentOffset = mFocalPointTargetOffset; + } + osg::Vec2d oldOffset = mFocalPointCurrentOffset; if (mPreviousTransitionInfluence > 0) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 59fa53047..7fa92b3f9 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -59,6 +59,7 @@ namespace MWRender osg::Vec2d mFocalPointCurrentOffset; osg::Vec2d mFocalPointTargetOffset; float mFocalPointTransitionSpeedCoef; + bool mSkipFocalPointTransition; // This fields are used to make focal point transition smooth if previous transition was not finished. float mPreviousTransitionInfluence; @@ -84,6 +85,7 @@ namespace MWRender void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; } void setFocalPointTargetOffset(osg::Vec2d v); + void skipFocalPointTransition() { mSkipFocalPointTransition = true; } void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; } void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 209ab538e..6e459d5e2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -945,6 +945,7 @@ namespace MWWorld removeContainerScripts(getPlayerPtr()); mWorldScene->changeToInteriorCell(cellName, position, adjustPlayerPos, changeEvent); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); + mRendering->getCamera()->skipFocalPointTransition(); } void World::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) @@ -960,6 +961,7 @@ namespace MWWorld removeContainerScripts(getPlayerPtr()); mWorldScene->changeToExteriorCell(position, adjustPlayerPos, changeEvent); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); + mRendering->getCamera()->skipFocalPointTransition(); } void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) From 8ac143c9831af86fe16b523f731858bbbecf25b3 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Thu, 16 Jul 2020 23:32:59 +0200 Subject: [PATCH 107/107] Camera can pull out after clearing obstruction instead of instant snapback. --- apps/openmw/mwrender/camera.cpp | 7 +++++++ apps/openmw/mwrender/camera.hpp | 1 + 2 files changed, 8 insertions(+) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 7531e712b..d074471ad 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -62,6 +62,7 @@ namespace MWRender mVanityToggleQueuedValue(false), mViewModeToggleQueued(false), mCameraDistance(0.f), + mMaxNextCameraDistance(800.f), mFocalPointCurrentOffset(osg::Vec2d()), mFocalPointTargetOffset(osg::Vec2d()), mFocalPointTransitionSpeedCoef(1.f), @@ -221,6 +222,8 @@ namespace MWRender float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); float maxDelta = 300.f * duration; mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); + + mMaxNextCameraDistance = mCameraDistance + duration * (100.f + mBaseCameraDistance); } void Camera::setFocalPointTargetOffset(osg::Vec2d v) @@ -472,7 +475,11 @@ namespace MWRender if (mVanity.enabled || mPreviewMode) mCameraDistance = mPreviewCam.offset; else if (!mFirstPersonView) + { mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection(); + if (mDynamicCameraDistanceEnabled) + mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance); + } mFocalPointAdjustment = osg::Vec3d(); } diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index 59fa53047..041df7afe 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -54,6 +54,7 @@ namespace MWRender bool mViewModeToggleQueued; float mCameraDistance; + float mMaxNextCameraDistance; osg::Vec3d mFocalPointAdjustment; osg::Vec2d mFocalPointCurrentOffset;