From 1d362029ce43462a6b686a989979c39b08c94275 Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Thu, 13 May 2021 23:02:26 +0200 Subject: [PATCH 01/57] Do not copy full dialogue as we only want ot return its id --- apps/openmw/mwworld/store.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index fb66b0a1d7..4da683fc1b 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -1095,7 +1095,7 @@ namespace MWWorld else { found->second.loadData(esm, isDeleted); - dialogue = found->second; + dialogue.mId = found->second.mId; } return RecordId(dialogue.mId, isDeleted); From cff11fbca9bfdfcb50ea4290f5057e219bb649ec Mon Sep 17 00:00:00 2001 From: jvoisin Date: Mon, 21 Jun 2021 14:22:26 +0200 Subject: [PATCH 02/57] Inline a couple of methods in esmreader.cpp --- components/esm/esmreader.cpp | 30 ------------------------------ components/esm/esmreader.hpp | 12 ++++++------ 2 files changed, 6 insertions(+), 36 deletions(-) diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index e5d239570e..ebcba7062b 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -7,11 +7,6 @@ namespace ESM using namespace Misc; - std::string ESMReader::getName() const - { - return mCtx.filename; - } - ESM_Context ESMReader::getContext() { // Update the file position before returning @@ -29,11 +24,6 @@ ESMReader::ESMReader() clearCtx(); } -int ESMReader::getFormat() const -{ - return mHeader.mFormat; -} - void ESMReader::restoreContext(const ESM_Context &rc) { // Reopen the file if necessary @@ -181,11 +171,6 @@ bool ESMReader::peekNextSub(const char *name) return mCtx.subName == name; } -void ESMReader::cacheSubName() -{ - mCtx.subCached = true; -} - // Read subrecord name. This gets called a LOT, so I've optimized it // slightly. void ESMReader::getSubName() @@ -340,19 +325,4 @@ void ESMReader::fail(const std::string &msg) throw std::runtime_error(ss.str()); } -void ESMReader::setEncoder(ToUTF8::Utf8Encoder* encoder) -{ - mEncoder = encoder; -} - -size_t ESMReader::getFileOffset() const -{ - return mEsm->tellg(); -} - -void ESMReader::skip(int bytes) -{ - mEsm->seekg(getFileOffset()+bytes); -} - } diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index d3dd94516f..8c0aa580cf 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -36,10 +36,10 @@ public: const std::string getDesc() const { return mHeader.mData.desc; } const std::vector &getGameFiles() const { return mHeader.mMaster; } const Header& getHeader() const { return mHeader; } - int getFormat() const; + int getFormat() const { return mHeader.mFormat; }; const NAME &retSubName() const { return mCtx.subName; } uint32_t getSubSize() const { return mCtx.leftSub; } - std::string getName() const; + std::string getName() const {return mCtx.filename; }; /************************************************************************* * @@ -73,7 +73,7 @@ public: void openRaw(const std::string &filename); /// Get the current position in the file. Make sure that the file has been opened! - size_t getFileOffset() const; + size_t getFileOffset() const { return mEsm->tellg(); }; // This is a quick hack for multiple esm/esp files. Each plugin introduces its own // terrain palette, but ESMReader does not pass a reference to the correct plugin @@ -185,7 +185,7 @@ public: bool peekNextSub(const char* name); // Store the current subrecord name for the next call of getSubName() - void cacheSubName(); + void cacheSubName() {mCtx.subCached = true; }; // Read subrecord name. This gets called a LOT, so I've optimized it // slightly. @@ -247,13 +247,13 @@ public: // them from native encoding to UTF8 in the process. std::string getString(int size); - void skip(int bytes); + void skip(int bytes) { mEsm->seekg(getFileOffset()+bytes); }; /// Used for error handling void fail(const std::string &msg); /// Sets font encoder for ESM strings - void setEncoder(ToUTF8::Utf8Encoder* encoder); + void setEncoder(ToUTF8::Utf8Encoder* encoder) { mEncoder = encoder; }; /// Get record flags of last record unsigned int getRecordFlags() { return mRecordFlags; } From aec3c74fa53e52d238c4dfa8808d293e01d4bec5 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Thu, 29 Apr 2021 21:30:25 +0200 Subject: [PATCH 03/57] Sprinkle some [[noreturn]] where possible --- components/bsa/bsa_file.cpp | 2 +- components/bsa/bsa_file.hpp | 2 +- components/compiler/parser.cpp | 4 ++-- components/compiler/parser.hpp | 4 ++-- components/esm/esmreader.cpp | 2 +- components/esm/esmreader.hpp | 2 +- components/fontloader/fontloader.cpp | 2 +- components/interpreter/interpreter.cpp | 4 ++-- components/interpreter/interpreter.hpp | 4 ++-- components/nif/niffile.hpp | 6 ++---- components/nifbullet/bulletnifloader.hpp | 2 +- components/settings/parser.cpp | 2 +- components/settings/parser.hpp | 2 +- 13 files changed, 18 insertions(+), 20 deletions(-) diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsa_file.cpp index 129c2bf454..ecbea5e7d9 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsa_file.cpp @@ -33,7 +33,7 @@ using namespace Bsa; /// Error handling -void BSAFile::fail(const std::string &msg) +[[noreturn]] void BSAFile::fail(const std::string &msg) { throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + mFilename); } diff --git a/components/bsa/bsa_file.hpp b/components/bsa/bsa_file.hpp index f9b4d4fa39..d30fc2feb0 100644 --- a/components/bsa/bsa_file.hpp +++ b/components/bsa/bsa_file.hpp @@ -106,7 +106,7 @@ protected: Lookup mLookup; /// Error handling - void fail(const std::string &msg); + [[noreturn]] void fail(const std::string &msg); /// Read header information from the input source virtual void readHeader(); diff --git a/components/compiler/parser.cpp b/components/compiler/parser.cpp index ffa393a29e..dc924b1bab 100644 --- a/components/compiler/parser.cpp +++ b/components/compiler/parser.cpp @@ -10,7 +10,7 @@ namespace Compiler { // Report the error and throw an exception. - void Parser::reportSeriousError (const std::string& message, const TokenLoc& loc) + [[noreturn]] void Parser::reportSeriousError (const std::string& message, const TokenLoc& loc) { mErrorHandler.error (message, loc); throw SourceException(); @@ -25,7 +25,7 @@ namespace Compiler // Report an unexpected EOF condition. - void Parser::reportEOF() + [[noreturn]] void Parser::reportEOF() { mErrorHandler.endOfFile(); throw EOFException(); diff --git a/components/compiler/parser.hpp b/components/compiler/parser.hpp index 2ef6e85b98..1f2a57a489 100644 --- a/components/compiler/parser.hpp +++ b/components/compiler/parser.hpp @@ -23,13 +23,13 @@ namespace Compiler protected: - void reportSeriousError (const std::string& message, const TokenLoc& loc); + [[noreturn]] void reportSeriousError (const std::string& message, const TokenLoc& loc); ///< Report the error and throw a exception. void reportWarning (const std::string& message, const TokenLoc& loc); ///< Report the warning without throwing an exception. - void reportEOF(); + [[noreturn]] void reportEOF(); ///< Report an unexpected EOF condition. ErrorHandler& getErrorHandler(); diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index e3e6a4f335..c9b93100e6 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -315,7 +315,7 @@ std::string ESMReader::getString(int size) return std::string (ptr, size); } -void ESMReader::fail(const std::string &msg) +[[noreturn]] void ESMReader::fail(const std::string &msg) { std::stringstream ss; diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index ea18014b77..3a9734c1b0 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -250,7 +250,7 @@ public: void skip(int bytes); /// Used for error handling - void fail(const std::string &msg); + [[noreturn]] void fail(const std::string &msg); /// Sets font encoder for ESM strings void setEncoder(ToUTF8::Utf8Encoder* encoder); diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index b4739110f7..e068fd781b 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -132,7 +132,7 @@ namespace return encoder.getUtf8(std::string(1, c)); } - void fail (Files::IStreamPtr file, const std::string& fileName, const std::string& message) + [[noreturn]] void fail (Files::IStreamPtr file, const std::string& fileName, const std::string& message) { std::stringstream error; error << "Font loading error: " << message; diff --git a/components/interpreter/interpreter.cpp b/components/interpreter/interpreter.cpp index 0b636092c3..c04352a90f 100644 --- a/components/interpreter/interpreter.cpp +++ b/components/interpreter/interpreter.cpp @@ -81,13 +81,13 @@ namespace Interpreter abortUnknownSegment (code); } - void Interpreter::abortUnknownCode (int segment, int opcode) + [[noreturn]] void Interpreter::abortUnknownCode (int segment, int opcode) { const std::string error = "unknown opcode " + std::to_string(opcode) + " in segment " + std::to_string(segment); throw std::runtime_error (error); } - void Interpreter::abortUnknownSegment (Type_Code code) + [[noreturn]] void Interpreter::abortUnknownSegment (Type_Code code) { const std::string error = "opcode outside of the allocated segment range: " + std::to_string(code); throw std::runtime_error (error); diff --git a/components/interpreter/interpreter.hpp b/components/interpreter/interpreter.hpp index ff3bcf7b7c..3aa5e36d58 100644 --- a/components/interpreter/interpreter.hpp +++ b/components/interpreter/interpreter.hpp @@ -28,9 +28,9 @@ namespace Interpreter void execute (Type_Code code); - void abortUnknownCode (int segment, int opcode); + [[noreturn]] void abortUnknownCode (int segment, int opcode); - void abortUnknownSegment (Type_Code code); + [[noreturn]] void abortUnknownSegment (Type_Code code); void begin(); diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index c6dd8af756..1ed7cbd5d8 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -92,11 +92,9 @@ public: }; /// Used if file parsing fails - void fail(const std::string &msg) const + [[noreturn]] void fail(const std::string &msg) const { - std::string err = " NIFFile Error: " + msg; - err += "\nFile: " + filename; - throw std::runtime_error(err); + throw std::runtime_error(" NIFFile Error: " + msg + "\nFile: " + filename); } /// Used when something goes wrong, but not catastrophically so void warn(const std::string &msg) const diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index 17a0d3e8b9..71c84566a0 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -43,7 +43,7 @@ public: Log(Debug::Warning) << "NIFLoader: Warn: " << msg; } - void fail(const std::string &msg) + [[noreturn]] void fail(const std::string &msg) { Log(Debug::Error) << "NIFLoader: Fail: "<< msg; abort(); diff --git a/components/settings/parser.cpp b/components/settings/parser.cpp index 24f359b315..f2419dfdd6 100644 --- a/components/settings/parser.cpp +++ b/components/settings/parser.cpp @@ -318,7 +318,7 @@ bool Settings::SettingsFileParser::skipWhiteSpace(size_t& i, std::string& str) return i < str.size(); } -void Settings::SettingsFileParser::fail(const std::string& message) +[[noreturn]] void Settings::SettingsFileParser::fail(const std::string& message) { std::stringstream error; error << "Error on line " << mLine << " in " << mFile << ":\n" << message; diff --git a/components/settings/parser.hpp b/components/settings/parser.hpp index 69e9cdaa41..45b1a18f72 100644 --- a/components/settings/parser.hpp +++ b/components/settings/parser.hpp @@ -20,7 +20,7 @@ namespace Settings /// @return false if we have reached the end of the string bool skipWhiteSpace(size_t& i, std::string& str); - void fail(const std::string& message); + [[noreturn]] void fail(const std::string& message); std::string mFile; int mLine = 0; From 22f7d4eee2d95c32856cc3c352bc709235ba1ee5 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 20 Jun 2021 18:02:11 +0200 Subject: [PATCH 04/57] Strip quotes when treating keywords as strings --- CHANGELOG.md | 1 + components/compiler/stringparser.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 285933ad4f..1229785394 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions) Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes Bug #5483: AutoCalc flag is not used to calculate spells cost + Bug #6066: addtopic "return" does not work from within script. No errors thrown Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime 0.47.0 diff --git a/components/compiler/stringparser.cpp b/components/compiler/stringparser.cpp index 1bacf79410..8b20377e1f 100644 --- a/components/compiler/stringparser.cpp +++ b/components/compiler/stringparser.cpp @@ -65,7 +65,11 @@ namespace Compiler keyword==Scanner::K_messagebox || keyword==Scanner::K_set || keyword==Scanner::K_to || keyword==Scanner::K_getsquareroot) { - return parseName (loc.mLiteral, loc, scanner); + // pretend this is not a keyword + std::string name = loc.mLiteral; + if (name.size()>=2 && name[0]=='"' && name[name.size()-1]=='"') + name = name.substr (1, name.size()-2); + return parseName (name, loc, scanner); } return Parser::parseKeyword (keyword, loc, scanner); From 5375b8e71b53aef2967bfc26372fe653720538d9 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 9 Jun 2021 22:25:46 +0200 Subject: [PATCH 05/57] Minor optimisation in VFS::FileSystemArchive::listResources When there is no cache, we can fill the `out` variable as we create it, instead of creating the cache, and then iterating it to fill `out`. Thanks to @cemoc for the help! --- components/vfs/filesystemarchive.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/components/vfs/filesystemarchive.cpp b/components/vfs/filesystemarchive.cpp index 6eef4b93ae..35f44f46cd 100644 --- a/components/vfs/filesystemarchive.cpp +++ b/components/vfs/filesystemarchive.cpp @@ -40,16 +40,20 @@ namespace VFS std::transform(proper.begin() + prefix, proper.end(), std::back_inserter(searchable), normalize_function); - if (!mIndex.insert (std::make_pair (searchable, file)).second) + const auto inserted = mIndex.insert(std::make_pair(searchable, file)); + if (!inserted.second) Log(Debug::Warning) << "Warning: found duplicate file for '" << proper << "', please check your file system for two files with the same name in different cases."; + else + out[inserted.first->first] = &inserted.first->second; } - mBuiltIndex = true; } - - for (index::iterator it = mIndex.begin(); it != mIndex.end(); ++it) + else { - out[it->first] = &it->second; + for (index::iterator it = mIndex.begin(); it != mIndex.end(); ++it) + { + out[it->first] = &it->second; + } } } From 692615fd3c5eb5f6c66515d1b0c3b2f01e4ae935 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 23 Jun 2021 18:08:49 +0200 Subject: [PATCH 06/57] Detach objects from the active grid when attempting to get their animation --- apps/openmw/mwclass/door.cpp | 12 +++++++----- apps/openmw/mwworld/worldimp.cpp | 9 ++++++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 3a5ff0d9ae..849960a093 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -132,12 +132,14 @@ namespace MWClass MWBase::Environment::get().getWorld()->getMaxActivationDistance()) { MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr); + if(animation) + { + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); + int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis"); + const ESM::MagicEffect *effect = store.get().find(index); - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis"); - const ESM::MagicEffect *effect = store.get().find(index); - - animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing + animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing + } } const std::string keyId = ptr.getCellRef().getKey(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 611e535c88..8fecee853f 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2552,7 +2552,14 @@ namespace MWWorld MWRender::Animation* World::getAnimation(const MWWorld::Ptr &ptr) { - return mRendering->getAnimation(ptr); + auto* animation = mRendering->getAnimation(ptr); + if(!animation) { + mWorldScene->removeFromPagedRefs(ptr); + animation = mRendering->getAnimation(ptr); + if(animation) + mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); + } + return animation; } const MWRender::Animation* World::getAnimation(const MWWorld::ConstPtr &ptr) const From 33e035cc95e08d46fd67674a3cefd0846606feea Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 23 Jun 2021 22:19:08 +0200 Subject: [PATCH 07/57] Fix two excessive type casting instances No need to to a string -> char* -> string dance. --- components/esm/weatherstate.cpp | 2 +- components/resource/imagemanager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esm/weatherstate.cpp b/components/esm/weatherstate.cpp index 3d94a445be..cd1a82b0b7 100644 --- a/components/esm/weatherstate.cpp +++ b/components/esm/weatherstate.cpp @@ -49,7 +49,7 @@ namespace ESM void WeatherState::save(ESMWriter& esm) const { - esm.writeHNCString(currentRegionRecord, mCurrentRegion.c_str()); + esm.writeHNCString(currentRegionRecord, mCurrentRegion); esm.writeHNT(timePassedRecord, mTimePassed); esm.writeHNT(fastForwardRecord, mFastForward); esm.writeHNT(weatherUpdateTimeRecord, mWeatherUpdateTime); diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp index dd34ed1a1f..37e76359ff 100644 --- a/components/resource/imagemanager.cpp +++ b/components/resource/imagemanager.cpp @@ -94,7 +94,7 @@ namespace Resource Files::IStreamPtr stream; try { - stream = mVFS->get(normalized.c_str()); + stream = mVFS->get(normalized); } catch (std::exception& e) { From 1123dc46ee69e6bee7f2c6d96c4d4c0d58cc7608 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 23 Jun 2021 23:13:59 +0200 Subject: [PATCH 08/57] Add a ton of const refs --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 +- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwgui/dialogue.hpp | 2 +- apps/openmw/mwmechanics/activespells.cpp | 2 +- apps/openmw/mwmechanics/activespells.hpp | 2 +- apps/openmw/mwmechanics/disease.hpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 2 +- apps/openmw/mwmechanics/pathfinding.hpp | 2 +- apps/openmw/mwmechanics/pickpocket.cpp | 2 +- apps/openmw/mwmechanics/pickpocket.hpp | 2 +- apps/openmw/mwmechanics/weapontype.cpp | 2 +- apps/openmw/mwmechanics/weapontype.hpp | 2 +- apps/openmw/mwphysics/physicssystem.cpp | 4 ++-- apps/openmw/mwphysics/physicssystem.hpp | 2 +- apps/openmw/mwphysics/projectile.cpp | 4 ++-- apps/openmw/mwphysics/projectile.hpp | 4 ++-- apps/openmw/mwphysics/raycasting.hpp | 2 +- apps/openmw/mwscript/interpretercontext.cpp | 2 +- apps/openmw/mwscript/interpretercontext.hpp | 2 +- apps/openmw/mwscript/statsextensions.cpp | 2 +- apps/openmw/mwworld/cellstore.cpp | 2 +- apps/openmw/mwworld/cellstore.hpp | 2 +- apps/openmw/mwworld/cellvisitors.hpp | 2 +- apps/openmw/mwworld/projectilemanager.cpp | 2 +- apps/openmw/mwworld/projectilemanager.hpp | 4 ++-- apps/openmw/mwworld/worldimp.cpp | 4 ++-- components/bsa/compressedbsafile.cpp | 2 +- components/bsa/compressedbsafile.hpp | 2 +- components/detournavigator/navmeshmanager.cpp | 2 +- components/detournavigator/navmeshmanager.hpp | 2 +- components/misc/stringops.hpp | 2 +- components/sceneutil/mwshadowtechnique.cpp | 2 +- components/sceneutil/osgacontroller.cpp | 4 ++-- components/sceneutil/osgacontroller.hpp | 4 ++-- components/sceneutil/util.cpp | 2 +- components/sceneutil/util.hpp | 2 +- components/shader/shadermanager.cpp | 2 +- 38 files changed, 45 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 967504552d..3b0803e9be 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -88,7 +88,7 @@ namespace MWBase virtual void setPlayerClass (const ESM::Class& class_) = 0; ///< Set player class to custom class. - virtual void restoreDynamicStats(MWWorld::Ptr actor, double hours, bool sleep) = 0; + virtual void restoreDynamicStats(const MWWorld::Ptr& actor, double hours, bool sleep) = 0; virtual void rest(double hours, bool sleep) = 0; ///< If the player is sleeping or waiting, this should be called every hour. diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 0fda54ebab..93180adad2 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -488,7 +488,7 @@ namespace MWGui mHistoryContents.clear(); } - bool DialogueWindow::setKeywords(std::list keyWords) + bool DialogueWindow::setKeywords(const std::list& keyWords) { if (mKeywords == keyWords && isCompanion() == mIsCompanion) return false; diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index ac6303e20a..aff09c0211 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -118,7 +118,7 @@ namespace MWGui void setPtr(const MWWorld::Ptr& actor) override; /// @return true if stale keywords were updated successfully - bool setKeywords(std::list keyWord); + bool setKeywords(const std::list& keyWord); void addResponse (const std::string& title, const std::string& text, bool needMargin = true); diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index 928293e649..319d797257 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -140,7 +140,7 @@ namespace MWMechanics return mSpells; } - void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector effects, + void ActiveSpells::addSpell(const std::string &id, bool stack, const std::vector& effects, const std::string &displayName, int casterActorId) { TContainer::iterator it(mSpells.find(id)); diff --git a/apps/openmw/mwmechanics/activespells.hpp b/apps/openmw/mwmechanics/activespells.hpp index 54f662fc26..8bc29aa444 100644 --- a/apps/openmw/mwmechanics/activespells.hpp +++ b/apps/openmw/mwmechanics/activespells.hpp @@ -74,7 +74,7 @@ namespace MWMechanics /// \param effects /// \param displayName Name for display in magic menu. /// - void addSpell (const std::string& id, bool stack, std::vector effects, + void addSpell (const std::string& id, bool stack, const std::vector& effects, const std::string& displayName, int casterActorId); /// Removes the active effects from this spell/potion/.. with \a id diff --git a/apps/openmw/mwmechanics/disease.hpp b/apps/openmw/mwmechanics/disease.hpp index 7933c927e5..5d4bfb682f 100644 --- a/apps/openmw/mwmechanics/disease.hpp +++ b/apps/openmw/mwmechanics/disease.hpp @@ -21,7 +21,7 @@ namespace MWMechanics /// Call when \a actor has got in contact with \a carrier (e.g. hit by him, or loots him) /// @param actor The actor that will potentially catch diseases. Currently only the player can catch diseases. /// @param carrier The disease carrier. - inline void diseaseContact (MWWorld::Ptr actor, MWWorld::Ptr carrier) + inline void diseaseContact (const MWWorld::Ptr& actor, const MWWorld::Ptr& carrier) { if (!carrier.getClass().isActor() || actor != getPlayer()) return; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 7101139821..0d7dd187f7 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -402,7 +402,7 @@ namespace MWMechanics mActors.rest(hours, sleep); } - void MechanicsManager::restoreDynamicStats(MWWorld::Ptr actor, double hours, bool sleep) + void MechanicsManager::restoreDynamicStats(const MWWorld::Ptr& actor, double hours, bool sleep) { mActors.restoreDynamicStats(actor, hours, sleep); } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 3f2c3f5e98..72eb044fa0 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -75,7 +75,7 @@ namespace MWMechanics void setPlayerClass (const ESM::Class& class_) override; ///< Set player class to custom class. - void restoreDynamicStats(MWWorld::Ptr actor, double hours, bool sleep) override; + void restoreDynamicStats(const MWWorld::Ptr& actor, double hours, bool sleep) override; void rest(double hours, bool sleep) override; ///< If the player is sleeping or waiting, this should be called every hour. diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index 987f2c6603..aa6a79c4eb 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -167,7 +167,7 @@ namespace MWMechanics // Caller needs to be careful for very short distances (i.e. less than 1) // or when accumuating the results i.e. (a + b)^2 != a^2 + b^2 // - static float distanceSquared(ESM::Pathgrid::Point point, const osg::Vec3f& pos) + static float distanceSquared(const ESM::Pathgrid::Point& point, const osg::Vec3f& pos) { return (MWMechanics::PathFinder::makeOsgVec3(point) - pos).length2(); } diff --git a/apps/openmw/mwmechanics/pickpocket.cpp b/apps/openmw/mwmechanics/pickpocket.cpp index 05e8a03930..038753f7d1 100644 --- a/apps/openmw/mwmechanics/pickpocket.cpp +++ b/apps/openmw/mwmechanics/pickpocket.cpp @@ -53,7 +53,7 @@ namespace MWMechanics } } - bool Pickpocket::pick(MWWorld::Ptr item, int count) + bool Pickpocket::pick(const MWWorld::Ptr& item, int count) { float stackValue = static_cast(item.getClass().getValue(item) * count); float fPickPocketMod = MWBase::Environment::get().getWorld()->getStore().get() diff --git a/apps/openmw/mwmechanics/pickpocket.hpp b/apps/openmw/mwmechanics/pickpocket.hpp index 4de1e37f84..0957b7a680 100644 --- a/apps/openmw/mwmechanics/pickpocket.hpp +++ b/apps/openmw/mwmechanics/pickpocket.hpp @@ -13,7 +13,7 @@ namespace MWMechanics /// Steal some items /// @return Was the thief detected? - bool pick (MWWorld::Ptr item, int count); + bool pick (const MWWorld::Ptr& item, int count); /// End the pickpocketing process /// @return Was the thief detected? bool finish (); diff --git a/apps/openmw/mwmechanics/weapontype.cpp b/apps/openmw/mwmechanics/weapontype.cpp index 2f8e45f7ff..feecd468ad 100644 --- a/apps/openmw/mwmechanics/weapontype.cpp +++ b/apps/openmw/mwmechanics/weapontype.cpp @@ -4,7 +4,7 @@ namespace MWMechanics { - MWWorld::ContainerStoreIterator getActiveWeapon(MWWorld::Ptr actor, int *weaptype) + MWWorld::ContainerStoreIterator getActiveWeapon(const MWWorld::Ptr& actor, int *weaptype) { MWWorld::InventoryStore &inv = actor.getClass().getInventoryStore(actor); CreatureStats &stats = actor.getClass().getCreatureStats(actor); diff --git a/apps/openmw/mwmechanics/weapontype.hpp b/apps/openmw/mwmechanics/weapontype.hpp index 09fa73c065..4d10e9b1c5 100644 --- a/apps/openmw/mwmechanics/weapontype.hpp +++ b/apps/openmw/mwmechanics/weapontype.hpp @@ -261,7 +261,7 @@ namespace MWMechanics } }; - MWWorld::ContainerStoreIterator getActiveWeapon(MWWorld::Ptr actor, int *weaptype); + MWWorld::ContainerStoreIterator getActiveWeapon(const MWWorld::Ptr& actor, int *weaptype); const ESM::WeaponType* getWeaponType(const int weaponType); } diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 833bb9a161..091d8b1612 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -261,7 +261,7 @@ namespace MWPhysics return 0.f; } - RayCastingResult PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore, std::vector targets, int mask, int group) const + RayCastingResult PhysicsSystem::castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore, const std::vector& targets, int mask, int group) const { if (from == to) { @@ -290,7 +290,7 @@ namespace MWPhysics if (!targets.empty()) { - for (MWWorld::Ptr& target : targets) + for (const MWWorld::Ptr& target : targets) { const Actor* actor = getActor(target); if (actor) diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 3d2a3c580d..bd50bd915a 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -175,7 +175,7 @@ namespace MWPhysics /// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all other actors. RayCastingResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(), - std::vector targets = std::vector(), + const std::vector& targets = std::vector(), int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const override; RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const override; diff --git a/apps/openmw/mwphysics/projectile.cpp b/apps/openmw/mwphysics/projectile.cpp index 252da0a687..0a6e9ac123 100644 --- a/apps/openmw/mwphysics/projectile.cpp +++ b/apps/openmw/mwphysics/projectile.cpp @@ -78,7 +78,7 @@ bool Projectile::canTraverseWater() const return mCanCrossWaterSurface; } -void Projectile::hit(MWWorld::Ptr target, btVector3 pos, btVector3 normal) +void Projectile::hit(const MWWorld::Ptr& target, btVector3 pos, btVector3 normal) { if (!mActive.load(std::memory_order_acquire)) return; @@ -95,7 +95,7 @@ MWWorld::Ptr Projectile::getCaster() const return mCaster; } -void Projectile::setCaster(MWWorld::Ptr caster) +void Projectile::setCaster(const MWWorld::Ptr& caster) { std::scoped_lock lock(mMutex); mCaster = caster; diff --git a/apps/openmw/mwphysics/projectile.hpp b/apps/openmw/mwphysics/projectile.hpp index 81c33d2a5e..7bcf33b38d 100644 --- a/apps/openmw/mwphysics/projectile.hpp +++ b/apps/openmw/mwphysics/projectile.hpp @@ -58,11 +58,11 @@ namespace MWPhysics } MWWorld::Ptr getCaster() const; - void setCaster(MWWorld::Ptr caster); + void setCaster(const MWWorld::Ptr& caster); bool canTraverseWater() const; - void hit(MWWorld::Ptr target, btVector3 pos, btVector3 normal); + void hit(const MWWorld::Ptr& target, btVector3 pos, btVector3 normal); void setValidTargets(const std::vector& targets); bool isValidTarget(const MWWorld::Ptr& target) const; diff --git a/apps/openmw/mwphysics/raycasting.hpp b/apps/openmw/mwphysics/raycasting.hpp index 7c8375cb5a..e13e745fec 100644 --- a/apps/openmw/mwphysics/raycasting.hpp +++ b/apps/openmw/mwphysics/raycasting.hpp @@ -28,7 +28,7 @@ namespace MWPhysics /// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all other actors. virtual RayCastingResult castRay(const osg::Vec3f &from, const osg::Vec3f &to, const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(), - std::vector targets = std::vector(), + const std::vector& targets = std::vector(), int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const = 0; virtual RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const = 0; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 2e8f72e629..6d7dcdda1d 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -415,7 +415,7 @@ namespace MWScript return MWBase::Environment::get().getWorld()->getCellName(); } - void InterpreterContext::executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor) + void InterpreterContext::executeActivation(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) { std::shared_ptr action = (ptr.getClass().activate(ptr, actor)); action->execute (actor); diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index 84982f6356..ee40883eac 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -111,7 +111,7 @@ namespace MWScript std::string getCurrentCellName() const override; - void executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor); + void executeActivation(const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor); ///< Execute the activation action for this ptr. If ptr is mActivated, mark activation as handled. int getMemberShort (const std::string& id, const std::string& name, bool global) const override; diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index ab3287c9a4..073312f538 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -31,7 +31,7 @@ namespace { - std::string getDialogueActorFaction(MWWorld::ConstPtr actor) + std::string getDialogueActorFaction(const MWWorld::ConstPtr& actor) { std::string factionId = actor.getClass().getPrimaryFaction(actor); if (factionId.empty()) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 2e2735e11a..051273f21d 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -1162,7 +1162,7 @@ namespace MWWorld update(mBooks.mList); } - void MWWorld::CellStore::checkItem(Ptr ptr) + void MWWorld::CellStore::checkItem(const Ptr& ptr) { if (ptr.getClass().getEnchantment(ptr).empty()) return; diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index edd8577ae0..6e927fbea6 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -127,7 +127,7 @@ namespace MWWorld void updateRechargingItems(); void rechargeItems(float duration); - void checkItem(Ptr ptr); + void checkItem(const Ptr& ptr); // helper function for forEachInternal template diff --git a/apps/openmw/mwworld/cellvisitors.hpp b/apps/openmw/mwworld/cellvisitors.hpp index e68b383b77..99bbebc126 100644 --- a/apps/openmw/mwworld/cellvisitors.hpp +++ b/apps/openmw/mwworld/cellvisitors.hpp @@ -13,7 +13,7 @@ namespace MWWorld { std::vector mObjects; - bool operator() (MWWorld::Ptr ptr) + bool operator() (const MWWorld::Ptr& ptr) { if (ptr.getRefData().getBaseNode()) { diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 4f0a2098f0..439f5a4605 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -325,7 +325,7 @@ namespace MWWorld mMagicBolts.push_back(state); } - void ProjectileManager::launchProjectile(Ptr actor, ConstPtr projectile, const osg::Vec3f &pos, const osg::Quat &orient, Ptr bow, float speed, float attackStrength) + void ProjectileManager::launchProjectile(const Ptr& actor, const ConstPtr& projectile, const osg::Vec3f &pos, const osg::Quat &orient, const Ptr& bow, float speed, float attackStrength) { ProjectileState state; state.mActorId = actor.getClass().getCreatureStats(actor).getActorId(); diff --git a/apps/openmw/mwworld/projectilemanager.hpp b/apps/openmw/mwworld/projectilemanager.hpp index e4bcae1ae4..4dc250dc5f 100644 --- a/apps/openmw/mwworld/projectilemanager.hpp +++ b/apps/openmw/mwworld/projectilemanager.hpp @@ -51,8 +51,8 @@ namespace MWWorld /// If caster is an actor, the actor's facing orientation is used. Otherwise fallbackDirection is used. void launchMagicBolt (const std::string &spellId, const MWWorld::Ptr& caster, const osg::Vec3f& fallbackDirection); - void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile, - const osg::Vec3f& pos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength); + void launchProjectile (const MWWorld::Ptr& actor, const MWWorld::ConstPtr& projectile, + const osg::Vec3f& pos, const osg::Quat& orient, const MWWorld::Ptr& bow, float speed, float attackStrength); void updateCasters(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 611e535c88..8a0bd46f27 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -753,7 +753,7 @@ namespace MWWorld FindContainerVisitor(const ConstPtr& containedPtr) : mContainedPtr(containedPtr) {} - bool operator() (Ptr ptr) + bool operator() (const Ptr& ptr) { if (mContainedPtr.getContainerStore() == &ptr.getClass().getContainerStore(ptr)) { @@ -3836,7 +3836,7 @@ namespace MWWorld struct ResetActorsVisitor { - bool operator() (Ptr ptr) + bool operator() (const Ptr& ptr) { if (ptr.getClass().isActor() && ptr.getCellRef().hasContentFile()) { diff --git a/components/bsa/compressedbsafile.cpp b/components/bsa/compressedbsafile.cpp index 09a05d2f5f..f066489184 100644 --- a/components/bsa/compressedbsafile.cpp +++ b/components/bsa/compressedbsafile.cpp @@ -406,7 +406,7 @@ Files::IStreamPtr CompressedBSAFile::getFile(const FileRecord& fileRecord) return std::shared_ptr(memoryStreamPtr, (std::istream*)memoryStreamPtr.get()); } -BsaVersion CompressedBSAFile::detectVersion(std::string filePath) +BsaVersion CompressedBSAFile::detectVersion(const std::string& filePath) { namespace bfs = boost::filesystem; bfs::ifstream input(bfs::path(filePath), std::ios_base::binary); diff --git a/components/bsa/compressedbsafile.hpp b/components/bsa/compressedbsafile.hpp index 215a1fc494..ac6e6fdf78 100644 --- a/components/bsa/compressedbsafile.hpp +++ b/components/bsa/compressedbsafile.hpp @@ -87,7 +87,7 @@ namespace Bsa virtual ~CompressedBSAFile(); //checks version of BSA from file header - static BsaVersion detectVersion(std::string filePath); + static BsaVersion detectVersion(const std::string& filePath); /// Read header information from the input source void readHeader() override; diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index de4c21c68a..c42fb5c4be 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -133,7 +133,7 @@ namespace DetourNavigator addChangedTile(tile, ChangeType::update); } - void NavMeshManager::update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents) + void NavMeshManager::update(const osg::Vec3f& playerPosition, const osg::Vec3f& agentHalfExtents) { const auto playerTile = getTilePosition(mSettings, toNavMeshCoordinates(mSettings, playerPosition)); auto& lastRevision = mLastRecastMeshManagerRevision[agentHalfExtents]; diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index 760ddb6b30..b176515e3b 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -43,7 +43,7 @@ namespace DetourNavigator void removeOffMeshConnections(const ObjectId id); - void update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents); + void update(const osg::Vec3f& playerPosition, const osg::Vec3f& agentHalfExtents); void wait(Loading::Listener& listener, WaitConditionType waitConditionType); diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index 48deaa9991..41effafa88 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -279,7 +279,7 @@ public: // TODO: use the std::string_view once we will use the C++17. // It should allow us to avoid data copying while we still will support both string and literal arguments. - static inline void replaceAll(std::string& data, std::string toSearch, std::string replaceStr) + static inline void replaceAll(std::string& data, const std::string& toSearch, const std::string& replaceStr) { size_t pos = data.find(toSearch); diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 88d44d2f69..9209532f7e 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -1996,7 +1996,7 @@ struct ConvexHull } }; - Vertices findInternalEdges(osg::Vec3d mainVertex, Vertices connectedVertices) + Vertices findInternalEdges(const osg::Vec3d& mainVertex, const Vertices& connectedVertices) { Vertices internalEdgeVertices; for (const auto& vertex : connectedVertices) diff --git a/components/sceneutil/osgacontroller.cpp b/components/sceneutil/osgacontroller.cpp index b2d819117f..02c9558ab3 100644 --- a/components/sceneutil/osgacontroller.cpp +++ b/components/sceneutil/osgacontroller.cpp @@ -153,7 +153,7 @@ namespace SceneUtil return osg::Vec3f(); } - void OsgAnimationController::update(float time, std::string animationName) + void OsgAnimationController::update(float time, const std::string& animationName) { for (const auto& mergedAnimationTrack : mMergedAnimationTracks) { @@ -190,7 +190,7 @@ namespace SceneUtil traverse(node, nv); } - void OsgAnimationController::setEmulatedAnimations(std::vector emulatedAnimations) + void OsgAnimationController::setEmulatedAnimations(const std::vector& emulatedAnimations) { mEmulatedAnimations = emulatedAnimations; } diff --git a/components/sceneutil/osgacontroller.hpp b/components/sceneutil/osgacontroller.hpp index f1c1584c2a..46538fa813 100644 --- a/components/sceneutil/osgacontroller.hpp +++ b/components/sceneutil/osgacontroller.hpp @@ -58,13 +58,13 @@ namespace SceneUtil osg::Vec3f getTranslation(float time) const override; /// @brief Calls animation track update() - void update(float time, std::string animationName); + void update(float time, const std::string& animationName); /// @brief Called every frame for osgAnimation void operator() (osg::Node*, osg::NodeVisitor*) override; /// @brief Sets details of the animations - void setEmulatedAnimations(std::vector emulatedAnimations); + void setEmulatedAnimations(const std::vector& emulatedAnimations); /// @brief Adds an animation track to a model void addMergedAnimationTrack(osg::ref_ptr animationTrack); diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index 1fe3685726..fb5264e224 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -218,7 +218,7 @@ bool hasUserDescription(const osg::Node* node, const std::string pattern) return false; } -osg::ref_ptr addEnchantedGlow(osg::ref_ptr node, Resource::ResourceSystem* resourceSystem, osg::Vec4f glowColor, float glowDuration) +osg::ref_ptr addEnchantedGlow(osg::ref_ptr node, Resource::ResourceSystem* resourceSystem, const osg::Vec4f& glowColor, float glowDuration) { std::vector > textures; for (int i=0; i<32; ++i) diff --git a/components/sceneutil/util.hpp b/components/sceneutil/util.hpp index 8103ed87a8..72a368b06a 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -60,7 +60,7 @@ namespace SceneUtil bool hasUserDescription(const osg::Node* node, const std::string pattern); - osg::ref_ptr addEnchantedGlow(osg::ref_ptr node, Resource::ResourceSystem* resourceSystem, osg::Vec4f glowColor, float glowDuration=-1); + osg::ref_ptr addEnchantedGlow(osg::ref_ptr node, Resource::ResourceSystem* resourceSystem, const osg::Vec4f& glowColor, float glowDuration=-1); // Alpha-to-coverage requires a multisampled framebuffer, so we need to set that up for RTTs bool attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::Camera::BufferComponent buffer, osg::Texture* texture, unsigned int level = 0, unsigned int face = 0, bool mipMapGeneration = false); diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 1635d13db7..9b057cdfc6 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -75,7 +75,7 @@ namespace Shader // Recursively replaces include statements with the actual source of the included files. // Adjusts #line statements accordingly and detects cyclic includes. // includingFiles is the set of files that include this file directly or indirectly, and is intentionally not a reference to allow automatic cleanup. - static bool parseIncludes(boost::filesystem::path shaderPath, std::string& source, const std::string& fileName, int& fileNumber, std::set includingFiles) + static bool parseIncludes(const boost::filesystem::path& shaderPath, std::string& source, const std::string& fileName, int& fileNumber, std::set includingFiles) { // An include is cyclic if it is being included by itself if (includingFiles.insert(shaderPath/fileName).second == false) From 895864099cee6c3175fa7edd6c10460da332636d Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 23 Jun 2021 23:29:14 +0200 Subject: [PATCH 09/57] Simplify NodeMapVisitor::apply No need to run a find() before a std::replace --- components/sceneutil/visitor.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/components/sceneutil/visitor.cpp b/components/sceneutil/visitor.cpp index 60f99b2fef..1f5a0ea4cf 100644 --- a/components/sceneutil/visitor.cpp +++ b/components/sceneutil/visitor.cpp @@ -65,11 +65,7 @@ namespace SceneUtil if (trans.libraryName() == std::string("osgAnimation")) { // Convert underscores to whitespaces as a workaround for Collada (OpenMW's animation system uses whitespace-separated names) - std::string underscore = "_"; - std::size_t foundUnderscore = originalNodeName.find(underscore); - - if (foundUnderscore != std::string::npos) - std::replace(originalNodeName.begin(), originalNodeName.end(), '_', ' '); + std::replace(originalNodeName.begin(), originalNodeName.end(), '_', ' '); } const std::string nodeName = originalNodeName; From b2c170efa056cabc6c46043395106333d8a0c460 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 23 Jun 2021 23:36:43 +0200 Subject: [PATCH 10/57] Use initialization lists where possible --- apps/openmw/mwrender/groundcover.hpp | 9 +++------ apps/openmw/mwscript/scriptmanagerimp.hpp | 8 +++----- components/esm/magiceffects.hpp | 9 +++------ 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwrender/groundcover.hpp b/apps/openmw/mwrender/groundcover.hpp index cd80978bef..b92ab97c95 100644 --- a/apps/openmw/mwrender/groundcover.hpp +++ b/apps/openmw/mwrender/groundcover.hpp @@ -48,12 +48,9 @@ namespace MWRender float mScale; std::string mModel; - GroundcoverEntry(const ESM::CellRef& ref, const std::string& model) - { - mPos = ref.mPos; - mScale = ref.mScale; - mModel = model; - } + GroundcoverEntry(const ESM::CellRef& ref, const std::string& model): + mPos(ref.mPos), mScale(ref.mScale), mModel(model) + {} }; private: diff --git a/apps/openmw/mwscript/scriptmanagerimp.hpp b/apps/openmw/mwscript/scriptmanagerimp.hpp index 04693eea6a..aff8318f72 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.hpp +++ b/apps/openmw/mwscript/scriptmanagerimp.hpp @@ -48,11 +48,9 @@ namespace MWScript Compiler::Locals mLocals; std::set mInactive; - CompiledScript(const std::vector& code, const Compiler::Locals& locals) - { - mByteCode = code; - mLocals = locals; - } + CompiledScript(const std::vector& code, const Compiler::Locals& locals): + mByteCode(code), mLocals(locals) + {} }; typedef std::map ScriptCollection; diff --git a/components/esm/magiceffects.hpp b/components/esm/magiceffects.hpp index a931c68fa5..5b8b0c924a 100644 --- a/components/esm/magiceffects.hpp +++ b/components/esm/magiceffects.hpp @@ -21,12 +21,9 @@ namespace ESM struct SummonKey { - SummonKey(int effectId, const std::string& sourceId, int index) - { - mEffectId = effectId; - mSourceId = sourceId; - mEffectIndex = index; - } + SummonKey(int effectId, const std::string& sourceId, int index): + mEffectId(effectId), mSourceId(sourceId), mEffectIndex(index) + {} bool operator==(const SummonKey &other) const { From 5840279f166f48b5dd372118c346d35d34b4585b Mon Sep 17 00:00:00 2001 From: jvoisin Date: Thu, 24 Jun 2021 00:26:15 +0200 Subject: [PATCH 11/57] Use `default` instead of empty constructors/destructors See https://pvs-studio.com/en/docs/warnings/v832/ for details --- apps/openmw/mwdialogue/journalentry.cpp | 4 ---- apps/openmw/mwdialogue/journalentry.hpp | 4 ++-- apps/openmw/mwgui/bookpage.cpp | 4 +--- apps/openmw/mwmechanics/objects.cpp | 4 ---- apps/openmw/mwmechanics/objects.hpp | 2 +- apps/openmw/mwrender/animation.cpp | 5 ----- apps/openmw/mwrender/animation.hpp | 2 +- apps/openmw/mwrender/localmap.cpp | 5 ----- apps/openmw/mwrender/localmap.hpp | 2 +- apps/openmw/mwsound/sound.hpp | 4 ++-- apps/openmw/mwworld/containerstore.hpp | 2 +- components/esm/util.hpp | 4 ++-- components/misc/rng.cpp | 3 --- components/misc/rng.hpp | 2 +- components/shader/shadervisitor.cpp | 5 ----- components/shader/shadervisitor.hpp | 2 +- 16 files changed, 13 insertions(+), 41 deletions(-) diff --git a/apps/openmw/mwdialogue/journalentry.cpp b/apps/openmw/mwdialogue/journalentry.cpp index 5eab6d5cae..32b2b101d9 100644 --- a/apps/openmw/mwdialogue/journalentry.cpp +++ b/apps/openmw/mwdialogue/journalentry.cpp @@ -16,8 +16,6 @@ namespace MWDialogue { - Entry::Entry() {} - Entry::Entry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor) : mInfoId (infoId) { @@ -60,8 +58,6 @@ namespace MWDialogue } - JournalEntry::JournalEntry() {} - JournalEntry::JournalEntry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor) : Entry (topic, infoId, actor), mTopic (topic) {} diff --git a/apps/openmw/mwdialogue/journalentry.hpp b/apps/openmw/mwdialogue/journalentry.hpp index 8711ab53a7..af09908891 100644 --- a/apps/openmw/mwdialogue/journalentry.hpp +++ b/apps/openmw/mwdialogue/journalentry.hpp @@ -22,7 +22,7 @@ namespace MWDialogue std::string mText; std::string mActorName; // optional - Entry(); + Entry() = default; /// actor is optional Entry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor); @@ -41,7 +41,7 @@ namespace MWDialogue { std::string mTopic; - JournalEntry(); + JournalEntry() = default; JournalEntry (const std::string& topic, const std::string& infoId, const MWWorld::Ptr& actor); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index fba136f88f..49fae04619 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -746,9 +746,7 @@ namespace mVertexColourType = MyGUI::RenderManager::getInstance().getVertexFormat(); } - ~GlyphStream () - { - } + ~GlyphStream () = default; MyGUI::Vertex* end () const { return mVertices; } diff --git a/apps/openmw/mwmechanics/objects.cpp b/apps/openmw/mwmechanics/objects.cpp index 5b18fc2c30..eea0655dd8 100644 --- a/apps/openmw/mwmechanics/objects.cpp +++ b/apps/openmw/mwmechanics/objects.cpp @@ -13,10 +13,6 @@ namespace MWMechanics { -Objects::Objects() -{ -} - Objects::~Objects() { for(auto& object : mObjects) diff --git a/apps/openmw/mwmechanics/objects.hpp b/apps/openmw/mwmechanics/objects.hpp index 5160114a3f..ba39fdbd4f 100644 --- a/apps/openmw/mwmechanics/objects.hpp +++ b/apps/openmw/mwmechanics/objects.hpp @@ -26,7 +26,7 @@ namespace MWMechanics PtrControllerMap mObjects; public: - Objects(); + Objects() = default; ~Objects(); void addObject (const MWWorld::Ptr& ptr); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index a11d97779c..53673d8a22 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1973,11 +1973,6 @@ namespace MWRender return SceneUtil::hasUserDescription(mObjectRoot, Constants::HerbalismLabel); } - Animation::AnimState::~AnimState() - { - - } - // ------------------------------ PartHolder::PartHolder(osg::ref_ptr node) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 213a4f7049..24478439c1 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -207,7 +207,7 @@ protected: mLoopCount(0), mPriority(0), mBlendMask(0), mAutoDisable(true) { } - ~AnimState(); + ~AnimState() = default; float getTime() const { diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 686078879d..24c00048d9 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -673,11 +673,6 @@ LocalMap::MapSegment::MapSegment() { } -LocalMap::MapSegment::~MapSegment() -{ - -} - void LocalMap::MapSegment::createFogOfWarTexture() { if (mFogOfWarTexture) diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 83a975aeda..e586f8fb02 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -115,7 +115,7 @@ namespace MWRender struct MapSegment { MapSegment(); - ~MapSegment(); + ~MapSegment() = default; void initFogOfWar(); void loadFogOfWar(const ESM::FogTexture& fog); diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index d2e65c9895..17f052aec0 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -85,7 +85,7 @@ namespace MWSound Sound(Sound&&) = delete; public: - Sound() { } + Sound() = default; }; class Stream : public SoundBase { @@ -94,7 +94,7 @@ namespace MWSound Stream(Stream&&) = delete; public: - Stream() { } + Stream() = default; }; } diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index 5044b0f451..f18a595466 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -58,7 +58,7 @@ namespace MWWorld std::shared_ptr mListener; public: ResolutionHandle(std::shared_ptr listener) : mListener(listener) {} - ResolutionHandle() {} + ResolutionHandle() = default; }; class ContainerStoreListener diff --git a/components/esm/util.hpp b/components/esm/util.hpp index a80df2456f..204de371fb 100644 --- a/components/esm/util.hpp +++ b/components/esm/util.hpp @@ -13,7 +13,7 @@ struct Quaternion { float mValues[4]; - Quaternion() {} + Quaternion() = default; Quaternion(const osg::Quat& q) { @@ -33,7 +33,7 @@ struct Vector3 { float mValues[3]; - Vector3() {} + Vector3() = default; Vector3(const osg::Vec3f& v) { diff --git a/components/misc/rng.cpp b/components/misc/rng.cpp index 4805f0d91c..113e7b1d5b 100644 --- a/components/misc/rng.cpp +++ b/components/misc/rng.cpp @@ -10,9 +10,6 @@ namespace namespace Misc { - - Rng::Seed::Seed() {} - Rng::Seed::Seed(unsigned int seed) { mGenerator.seed(seed); diff --git a/components/misc/rng.hpp b/components/misc/rng.hpp index 998ac0d535..06e94897be 100644 --- a/components/misc/rng.hpp +++ b/components/misc/rng.hpp @@ -17,7 +17,7 @@ public: { std::mt19937 mGenerator; public: - Seed(); + Seed() = default; Seed(const Seed&) = delete; Seed(unsigned int seed); friend class Rng; diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index e8ac7d9c36..3c5898b873 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -38,11 +38,6 @@ namespace Shader { } - ShaderVisitor::ShaderRequirements::~ShaderRequirements() - { - - } - ShaderVisitor::ShaderVisitor(ShaderManager& shaderManager, Resource::ImageManager& imageManager, const std::string &defaultShaderPrefix) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) , mForceShaders(false) diff --git a/components/shader/shadervisitor.hpp b/components/shader/shadervisitor.hpp index 30ff41a33c..a5add473a6 100644 --- a/components/shader/shadervisitor.hpp +++ b/components/shader/shadervisitor.hpp @@ -77,7 +77,7 @@ namespace Shader struct ShaderRequirements { ShaderRequirements(); - ~ShaderRequirements(); + ~ShaderRequirements() = default; // std::map mTextures; From cf11870b1c9042c47d58cd01c8e9cc518118600c Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 23 Jun 2021 21:56:08 +0200 Subject: [PATCH 12/57] Sprinkle some references where it makes sense --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwmechanics/actors.hpp | 2 +- apps/openmw/mwmechanics/character.cpp | 2 +- apps/openmw/mwmechanics/character.hpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 2 +- components/misc/stringops.hpp | 2 +- components/resource/bulletshapemanager.cpp | 4 ++-- components/resource/keyframemanager.cpp | 2 +- components/resource/keyframemanager.hpp | 2 +- components/sceneutil/util.cpp | 2 +- components/sceneutil/util.hpp | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 967504552d..1fe922a47b 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -230,7 +230,7 @@ namespace MWBase virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0; virtual bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const = 0; - virtual void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell) = 0; + virtual void castSpell(const MWWorld::Ptr& ptr, const std::string& spellId, bool manualSpell) = 0; virtual void processChangedSettings (const std::set< std::pair >& settings) = 0; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 87f462d6ff..e62d686ee2 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1667,7 +1667,7 @@ namespace MWMechanics } } - void Actors::castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell) + void Actors::castSpell(const MWWorld::Ptr& ptr, const std::string& spellId, bool manualSpell) { PtrActorMap::iterator iter = mActors.find(ptr); if(iter != mActors.end()) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 0ae9687578..171b45e270 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -101,7 +101,7 @@ namespace MWMechanics void resurrect (const MWWorld::Ptr& ptr); - void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell=false); + void castSpell(const MWWorld::Ptr& ptr, const std::string& spellId, bool manualSpell=false); void updateActor(const MWWorld::Ptr &old, const MWWorld::Ptr& ptr); ///< Updates an actor with a new Ptr diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 54c951187f..d5a1d46a88 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -2852,7 +2852,7 @@ void CharacterController::setAttackingOrSpell(bool attackingOrSpell) mAttackingOrSpell = attackingOrSpell; } -void CharacterController::castSpell(const std::string spellId, bool manualSpell) +void CharacterController::castSpell(const std::string& spellId, bool manualSpell) { mAttackingOrSpell = true; mCastingManualSpell = manualSpell; diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 3f7fa4e1bd..adeaa739af 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -286,7 +286,7 @@ public: void setVisibility(float visibility); void setAttackingOrSpell(bool attackingOrSpell); - void castSpell(const std::string spellId, bool manualSpell=false); + void castSpell(const std::string& spellId, bool manualSpell=false); void setAIAttackType(const std::string& attackType); static void setAttackTypeRandomly(std::string& attackType); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 7101139821..352a6cca43 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -251,7 +251,7 @@ namespace MWMechanics mObjects.addObject(ptr); } - void MechanicsManager::castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell) + void MechanicsManager::castSpell(const MWWorld::Ptr& ptr, const std::string& spellId, bool manualSpell) { if(ptr.getClass().isActor()) mActors.castSpell(ptr, spellId, manualSpell); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 3f2c3f5e98..0b1d7377b2 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -186,7 +186,7 @@ namespace MWMechanics /// Is \a ptr casting spell or using weapon now? bool isAttackingOrSpell(const MWWorld::Ptr &ptr) const override; - void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell=false) override; + void castSpell(const MWWorld::Ptr& ptr, const std::string& spellId, bool manualSpell=false) override; void processChangedSettings(const Settings::CategorySettingVector& settings) override; diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index 48deaa9991..59768b92ac 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -66,7 +66,7 @@ public: return ch; } - static std::string lowerCaseUtf8(const std::string str) + static std::string lowerCaseUtf8(const std::string& str) { if (str.empty()) return str; diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index ad37eda0dd..b1b0f74176 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -45,9 +45,9 @@ struct GetTriangleFunctor } #if OSG_MIN_VERSION_REQUIRED(3,5,6) - void inline operator()( const osg::Vec3 v1, const osg::Vec3 v2, const osg::Vec3 v3 ) + void inline operator()( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3 ) #else - void inline operator()( const osg::Vec3 v1, const osg::Vec3 v2, const osg::Vec3 v3, bool _temp ) + void inline operator()( const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3, bool _temp ) #endif { if (mTriMesh) diff --git a/components/resource/keyframemanager.cpp b/components/resource/keyframemanager.cpp index d7eeeeb971..69986fbcd9 100644 --- a/components/resource/keyframemanager.cpp +++ b/components/resource/keyframemanager.cpp @@ -106,7 +106,7 @@ namespace Resource return time; } - std::string RetrieveAnimationsVisitor::changeFileExtension(const std::string file, const std::string ext) + std::string RetrieveAnimationsVisitor::changeFileExtension(const std::string& file, const std::string& ext) { size_t extPos = file.find_last_of('.'); if (extPos != std::string::npos && extPos+1 < file.size()) diff --git a/components/resource/keyframemanager.hpp b/components/resource/keyframemanager.hpp index 87a20b97a5..75c9cc6ff4 100644 --- a/components/resource/keyframemanager.hpp +++ b/components/resource/keyframemanager.hpp @@ -22,7 +22,7 @@ namespace Resource private: - std::string changeFileExtension(const std::string file, const std::string ext); + std::string changeFileExtension(const std::string& file, const std::string& ext); std::string parseTextKey(const std::string& line); double parseTimeSignature(const std::string& line); diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index 1fe3685726..ad5daa6e02 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -200,7 +200,7 @@ float makeOsgColorComponent(unsigned int value, unsigned int shift) return float((value >> shift) & 0xFFu) / 255.0f; } -bool hasUserDescription(const osg::Node* node, const std::string pattern) +bool hasUserDescription(const osg::Node* node, const std::string& pattern) { if (node == nullptr) return false; diff --git a/components/sceneutil/util.hpp b/components/sceneutil/util.hpp index 8103ed87a8..151f65db79 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -58,7 +58,7 @@ namespace SceneUtil float makeOsgColorComponent (unsigned int value, unsigned int shift); - bool hasUserDescription(const osg::Node* node, const std::string pattern); + bool hasUserDescription(const osg::Node* node, const std::string& pattern); osg::ref_ptr addEnchantedGlow(osg::ref_ptr node, Resource::ResourceSystem* resourceSystem, osg::Vec4f glowColor, float glowDuration=-1); From 2c8f328ac216e2548b1462e0b11ea1f865d1e355 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Fri, 25 Jun 2021 20:55:38 +0200 Subject: [PATCH 13/57] Use make_unique instead of unique_ptr+new --- components/esm/aisequence.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/components/esm/aisequence.cpp b/components/esm/aisequence.cpp index df3c1ca9d0..ca4c21802c 100644 --- a/components/esm/aisequence.cpp +++ b/components/esm/aisequence.cpp @@ -178,49 +178,49 @@ namespace AiSequence { case Ai_Wander: { - std::unique_ptr ptr (new AiWander()); + std::unique_ptr ptr = std::make_unique(); ptr->load(esm); mPackages.back().mPackage = ptr.release(); break; } case Ai_Travel: { - std::unique_ptr ptr (new AiTravel()); + std::unique_ptr ptr = std::make_unique(); ptr->load(esm); mPackages.back().mPackage = ptr.release(); break; } case Ai_Escort: { - std::unique_ptr ptr (new AiEscort()); + std::unique_ptr ptr = std::make_unique(); ptr->load(esm); mPackages.back().mPackage = ptr.release(); break; } case Ai_Follow: { - std::unique_ptr ptr (new AiFollow()); + std::unique_ptr ptr = std::make_unique(); ptr->load(esm); mPackages.back().mPackage = ptr.release(); break; } case Ai_Activate: { - std::unique_ptr ptr (new AiActivate()); + std::unique_ptr ptr = std::make_unique(); ptr->load(esm); mPackages.back().mPackage = ptr.release(); break; } case Ai_Combat: { - std::unique_ptr ptr (new AiCombat()); + std::unique_ptr ptr = std::make_unique(); ptr->load(esm); mPackages.back().mPackage = ptr.release(); break; } case Ai_Pursue: { - std::unique_ptr ptr (new AiPursue()); + std::unique_ptr ptr = std::make_unique(); ptr->load(esm); mPackages.back().mPackage = ptr.release(); break; From 9db7d0278a35c6f9a0ef6ccaa14ab6bd11009bd5 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Fri, 25 Jun 2021 21:52:02 +0200 Subject: [PATCH 14/57] Sprinkle some const ref --- components/contentselector/model/contentmodel.cpp | 2 +- components/contentselector/model/contentmodel.hpp | 2 +- components/detournavigator/cachedrecastmeshmanager.cpp | 2 +- components/detournavigator/cachedrecastmeshmanager.hpp | 2 +- components/detournavigator/recastmeshmanager.cpp | 2 +- components/detournavigator/recastmeshmanager.hpp | 2 +- components/interpreter/defines.cpp | 2 +- components/misc/stringops.hpp | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index e51c1809a9..141ad13517 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -543,7 +543,7 @@ bool ContentSelectorModel::ContentModel::isChecked(const QString& filepath) cons return false; } -bool ContentSelectorModel::ContentModel::isEnabled (QModelIndex index) const +bool ContentSelectorModel::ContentModel::isEnabled (const QModelIndex& index) const { return (flags(index) & Qt::ItemIsEnabled); } diff --git a/components/contentselector/model/contentmodel.hpp b/components/contentselector/model/contentmodel.hpp index 030865b35a..d245a0dcbf 100644 --- a/components/contentselector/model/contentmodel.hpp +++ b/components/contentselector/model/contentmodel.hpp @@ -52,7 +52,7 @@ namespace ContentSelectorModel EsmFile *item(int row); QStringList gameFiles() const; - bool isEnabled (QModelIndex index) const; + bool isEnabled (const QModelIndex& index) const; bool isChecked(const QString &filepath) const; bool setCheckState(const QString &filepath, bool isChecked); void setContentList(const QStringList &fileList); diff --git a/components/detournavigator/cachedrecastmeshmanager.cpp b/components/detournavigator/cachedrecastmeshmanager.cpp index 2788b80461..4666b66a83 100644 --- a/components/detournavigator/cachedrecastmeshmanager.cpp +++ b/components/detournavigator/cachedrecastmeshmanager.cpp @@ -62,7 +62,7 @@ namespace DetourNavigator return mImpl.isEmpty(); } - void CachedRecastMeshManager::reportNavMeshChange(Version recastMeshVersion, Version navMeshVersion) + void CachedRecastMeshManager::reportNavMeshChange(const Version& recastMeshVersion, const Version& navMeshVersion) { mImpl.reportNavMeshChange(recastMeshVersion, navMeshVersion); } diff --git a/components/detournavigator/cachedrecastmeshmanager.hpp b/components/detournavigator/cachedrecastmeshmanager.hpp index ea55348f70..96604c3628 100644 --- a/components/detournavigator/cachedrecastmeshmanager.hpp +++ b/components/detournavigator/cachedrecastmeshmanager.hpp @@ -26,7 +26,7 @@ namespace DetourNavigator bool isEmpty() const; - void reportNavMeshChange(Version recastMeshVersion, Version navMeshVersion); + void reportNavMeshChange(const Version& recastMeshVersion, const Version& navMeshVersion); Version getVersion() const; diff --git a/components/detournavigator/recastmeshmanager.cpp b/components/detournavigator/recastmeshmanager.cpp index bfc0409a51..e79d58de9d 100644 --- a/components/detournavigator/recastmeshmanager.cpp +++ b/components/detournavigator/recastmeshmanager.cpp @@ -83,7 +83,7 @@ namespace DetourNavigator return mObjects.empty(); } - void RecastMeshManager::reportNavMeshChange(Version recastMeshVersion, Version navMeshVersion) + void RecastMeshManager::reportNavMeshChange(const Version& recastMeshVersion, const Version& navMeshVersion) { if (recastMeshVersion.mGeneration != mGeneration) return; diff --git a/components/detournavigator/recastmeshmanager.hpp b/components/detournavigator/recastmeshmanager.hpp index 5922821f26..850865b95e 100644 --- a/components/detournavigator/recastmeshmanager.hpp +++ b/components/detournavigator/recastmeshmanager.hpp @@ -50,7 +50,7 @@ namespace DetourNavigator bool isEmpty() const; - void reportNavMeshChange(Version recastMeshVersion, Version navMeshVersion); + void reportNavMeshChange(const Version& recastMeshVersion, const Version& navMeshVersion); Version getVersion() const; diff --git a/components/interpreter/defines.cpp b/components/interpreter/defines.cpp index d2e7067c6c..48d2ceaa45 100644 --- a/components/interpreter/defines.cpp +++ b/components/interpreter/defines.cpp @@ -26,7 +26,7 @@ namespace Interpreter{ return a.length() > b.length(); } - std::string fixDefinesReal(std::string text, bool dialogue, Context& context) + static std::string fixDefinesReal(const std::string& text, bool dialogue, Context& context) { unsigned int start = 0; std::ostringstream retval; diff --git a/components/misc/stringops.hpp b/components/misc/stringops.hpp index 9f3dfe7c5f..2a865606fd 100644 --- a/components/misc/stringops.hpp +++ b/components/misc/stringops.hpp @@ -290,7 +290,7 @@ public: } } - static inline void replaceLast(std::string& str, std::string substr, std::string with) + static inline void replaceLast(std::string& str, const std::string& substr, const std::string& with) { size_t pos = str.rfind(substr); if (pos == std::string::npos) From 873b3b480055e00006837789cee83e525db5f646 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 26 Jun 2021 19:46:34 +0100 Subject: [PATCH 15/57] Handle empty strings. --- extern/Base64/Base64.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extern/Base64/Base64.h b/extern/Base64/Base64.h index 4e9f517479..49b2d29e35 100644 --- a/extern/Base64/Base64.h +++ b/extern/Base64/Base64.h @@ -95,6 +95,12 @@ class Base64 { size_t in_len = input.size(); if (in_len % 4 != 0) return "Input data size is not a multiple of 4"; + if (in_len == 0) + { + out = ""; + return ""; + } + size_t out_len = in_len / 4 * 3; if (input[in_len - 1] == '=') out_len--; if (input[in_len - 2] == '=') out_len--; From d38126ef1cf09cdc84a95a478b770c8a486fed3c Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 26 Jun 2021 20:00:25 +0100 Subject: [PATCH 16/57] Pack default CS config *Technically* it was already being loaded as if it were packed, but it made no difference because it's supposed to be empty. --- CMakeLists.txt | 6 +++--- apps/opencs/CMakeLists.txt | 4 ++-- apps/opencs/model/prefs/state.cpp | 8 ++++---- apps/opencs/model/prefs/state.hpp | 1 + 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a07cee69f..4661f673f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -458,8 +458,8 @@ else () "${OpenMW_BINARY_DIR}/openmw.cfg") endif () -configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg - "${OpenMW_BINARY_DIR}" "openmw-cs.cfg") +pack_resource_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg + "${OpenMW_BINARY_DIR}" "defaults-cs.bin") # Needs the copy version because the configure version assumes the end of the file has been reached when a null character is reached and there are no CMake expressions to evaluate. copy_resource_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters @@ -928,7 +928,7 @@ elseif(NOT APPLE) INSTALL(FILES "${INSTALL_SOURCE}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") IF(BUILD_OPENCS) - INSTALL(FILES "${INSTALL_SOURCE}/openmw-cs.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") + INSTALL(FILES "${INSTALL_SOURCE}/defaults-cs.bin" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") ENDIF(BUILD_OPENCS) # Install resources diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 19c32df609..88c4233c9c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -158,7 +158,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) if(APPLE) set (OPENCS_MAC_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns") - set (OPENCS_CFG "${OpenMW_BINARY_DIR}/openmw-cs.cfg") + set (OPENCS_CFG "${OpenMW_BINARY_DIR}/defaults-cs.bin") set (OPENCS_DEFAULT_FILTERS_FILE "${OpenMW_BINARY_DIR}/resources/defaultfilters") set (OPENCS_OPENMW_CFG "${OpenMW_BINARY_DIR}/openmw.cfg") else() @@ -270,7 +270,7 @@ if (WIN32) SET(INSTALL_SOURCE "${OpenMW_BINARY_DIR}") endif () - INSTALL(FILES "${INSTALL_SOURCE}/openmw-cs.cfg" DESTINATION ".") + INSTALL(FILES "${INSTALL_SOURCE}/defaults-cs.bin" DESTINATION ".") endif() if (MSVC) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 0958fa8d4d..58a0f296e2 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -17,15 +17,15 @@ CSMPrefs::State *CSMPrefs::State::sThis = nullptr; void CSMPrefs::State::load() { // default settings file - boost::filesystem::path local = mConfigurationManager.getLocalPath() / mConfigFile; - boost::filesystem::path global = mConfigurationManager.getGlobalPath() / mConfigFile; + boost::filesystem::path local = mConfigurationManager.getLocalPath() / mDefaultConfigFile; + boost::filesystem::path global = mConfigurationManager.getGlobalPath() / mDefaultConfigFile; if (boost::filesystem::exists (local)) mSettings.loadDefault (local.string()); else if (boost::filesystem::exists (global)) mSettings.loadDefault (global.string()); else - throw std::runtime_error ("No default settings file found! Make sure the file \"openmw-cs.cfg\" was properly installed."); + throw std::runtime_error ("No default settings file found! Make sure the file \"" + mDefaultConfigFile + "\" was properly installed."); // user settings file boost::filesystem::path user = mConfigurationManager.getUserConfigPath() / mConfigFile; @@ -641,7 +641,7 @@ void CSMPrefs::State::setDefault (const std::string& key, const std::string& def } CSMPrefs::State::State (const Files::ConfigurationManager& configurationManager) -: mConfigFile ("openmw-cs.cfg"), mConfigurationManager (configurationManager), +: mConfigFile ("openmw-cs.cfg"), mDefaultConfigFile("defaults-cs.bin"), mConfigurationManager (configurationManager), mCurrentCategory (mCategories.end()) { if (sThis) diff --git a/apps/opencs/model/prefs/state.hpp b/apps/opencs/model/prefs/state.hpp index aa63de595e..7c9fcbecda 100644 --- a/apps/opencs/model/prefs/state.hpp +++ b/apps/opencs/model/prefs/state.hpp @@ -48,6 +48,7 @@ namespace CSMPrefs private: const std::string mConfigFile; + const std::string mDefaultConfigFile; const Files::ConfigurationManager& mConfigurationManager; ShortcutManager mShortcutManager; Settings::Manager mSettings; From 8a1b4bde8ab8b918e4ac570c54e1afbdef9499a5 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 27 Jun 2021 00:12:07 +0100 Subject: [PATCH 17/57] Ensure original (removed) state overrides replacement state when recreating shaders When the shader visitor replaces state (e.g. changes the deprecated alpha test to a shader-based one) it backs up the original state. If shaders are recreated, we need to know what the canonical state was and create shaders to implement that instead of creating shaders to implement dummy replacement state. This was actually usually working as the removed state got checked after the active state, so overwrote anything derived from it. However, if the active state had the override bit set, that would make it override the removed state. Skipping any active state that duplicates removed state fixes this case. Resolves #6108 --- components/shader/shadervisitor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 3c5898b873..d51dbfa6b9 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -279,6 +279,8 @@ namespace Shader { for (osg::StateSet::AttributeList::const_iterator it = attributeMap.begin(); it != attributeMap.end(); ++it) { + if (attributeMap != removedAttributes && removedAttributes.count(it->first)) + continue; if (it->first.first == osg::StateAttribute::MATERIAL) { // This should probably be moved out of ShaderRequirements and be applied directly now it's a uniform instead of a define From 0e122b1e3d04691b8a9b9f3f1b359c947cd94bf8 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 27 Jun 2021 01:48:06 +0100 Subject: [PATCH 18/57] Avoid copy and deep equality check --- components/shader/shadervisitor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index d51dbfa6b9..b4455c4096 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -275,11 +275,11 @@ namespace Shader osg::StateSet::AttributeList removedAttributes; if (osg::ref_ptr removedState = getRemovedState(*stateset)) removedAttributes = removedState->getAttributeList(); - for (const auto& attributeMap : { attributes, removedAttributes }) + for (const auto* attributeMap : std::initializer_list{ &attributes, &removedAttributes }) { - for (osg::StateSet::AttributeList::const_iterator it = attributeMap.begin(); it != attributeMap.end(); ++it) + for (osg::StateSet::AttributeList::const_iterator it = attributeMap->begin(); it != attributeMap->end(); ++it) { - if (attributeMap != removedAttributes && removedAttributes.count(it->first)) + if (attributeMap != &removedAttributes && removedAttributes.count(it->first)) continue; if (it->first.first == osg::StateAttribute::MATERIAL) { From 84d6dea277451ccebc2cd1bf965993a26a334775 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 27 Jun 2021 02:15:45 +0200 Subject: [PATCH 19/57] Inscribe physical bounding box into navmesh agent cylinder To disallow too narrow navmesh for a bounding box. --- .../detournavigator/navigator.cpp | 586 +++++++++--------- components/detournavigator/settingsutils.hpp | 5 +- 2 files changed, 292 insertions(+), 299 deletions(-) diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index bf8b4a002e..b0fec1a1a3 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -42,8 +42,8 @@ namespace DetourNavigatorNavigatorTest() : mPlayerPosition(0, 0, 0) , mAgentHalfExtents(29, 29, 66) - , mStart(-215, 215, 1) - , mEnd(215, -215, 1) + , mStart(-204, 204, 1) + , mEnd(204, -204, 1) , mOut(mPath) , mStepSize(28.333332061767578125f) { @@ -133,30 +133,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.85963428020477294921875), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), - Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), - Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), - Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), - Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), - Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), - Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), - Vec3fEq(215, -215, 1.87718021869659423828125) - )); + Vec3fEq(-204.0000152587890625, 204, 1.99998295307159423828125), + Vec3fEq(-183.96533203125, 183.9653167724609375, 1.99998819828033447265625), + Vec3fEq(-163.930633544921875, 163.9306182861328125, 1.99999344348907470703125), + Vec3fEq(-143.8959503173828125, 143.89593505859375, -2.720611572265625), + Vec3fEq(-123.86126708984375, 123.86124420166015625, -13.1089687347412109375), + Vec3fEq(-103.82657623291015625, 103.8265533447265625, -23.497333526611328125), + Vec3fEq(-83.7918853759765625, 83.7918548583984375, -33.885692596435546875), + Vec3fEq(-63.757190704345703125, 63.757171630859375, -44.274051666259765625), + Vec3fEq(-43.722503662109375, 43.72248077392578125, -54.66241455078125), + Vec3fEq(-23.687808990478515625, 23.6877918243408203125, -65.05077362060546875), + Vec3fEq(-3.6531188488006591796875, 3.6531002521514892578125, -75.43914031982421875), + Vec3fEq(16.3815746307373046875, -16.381591796875, -69.74927520751953125), + Vec3fEq(36.416263580322265625, -36.416286468505859375, -60.4739532470703125), + Vec3fEq(56.450958251953125, -56.450977325439453125, -51.1986236572265625), + Vec3fEq(76.48564910888671875, -76.4856719970703125, -41.92330169677734375), + Vec3fEq(96.5203399658203125, -96.52036285400390625, -31.46941375732421875), + Vec3fEq(116.55503082275390625, -116.5550537109375, -19.597003936767578125), + Vec3fEq(136.5897216796875, -136.5897369384765625, -7.724592685699462890625), + Vec3fEq(156.624420166015625, -156.624420166015625, 1.99999535083770751953125), + Vec3fEq(176.6591033935546875, -176.65911865234375, 1.99999010562896728515625), + Vec3fEq(196.69378662109375, -196.6938018798828125, 1.99998486042022705078125), + Vec3fEq(204, -204.0000152587890625, 1.99998295307159423828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, add_object_should_change_navmesh) @@ -183,30 +182,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.85963428020477294921875), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), - Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), - Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), - Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), - Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), - Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), - Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), - Vec3fEq(215, -215, 1.87718021869659423828125) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625), + Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125), + Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875), + Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375), + Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125), + Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375), + Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375), + Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125), + Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625), + Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125), + Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125), + Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125), + Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625), + Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375), + Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875), + Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125), + Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625), + Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125), + Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625), + Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); @@ -217,30 +215,30 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.87826788425445556640625), - Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54876613616943359375), - Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97847843170166015625), - Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.408184051513671875), - Vec3fEq(-154.1872711181640625, 119.36397552490234375, -19.837890625), - Vec3fEq(-138.9840850830078125, 95.45496368408203125, -25.2675991058349609375), - Vec3fEq(-123.78090667724609375, 71.54595184326171875, -30.6973056793212890625), - Vec3fEq(-108.57772064208984375, 47.636936187744140625, -36.12701416015625), - Vec3fEq(-93.3745269775390625, 23.7279262542724609375, -40.754688262939453125), - Vec3fEq(-78.17134857177734375, -0.18108306825160980224609375, -37.128787994384765625), - Vec3fEq(-62.968158721923828125, -24.0900936126708984375, -33.50289154052734375), - Vec3fEq(-47.764972686767578125, -47.999103546142578125, -30.797946929931640625), - Vec3fEq(-23.852447509765625, -63.196765899658203125, -33.97112274169921875), - Vec3fEq(0.0600789971649646759033203125, -78.39443206787109375, -37.14543914794921875), - Vec3fEq(23.97260284423828125, -93.5920867919921875, -40.774089813232421875), - Vec3fEq(47.885128021240234375, -108.78974151611328125, -36.05129241943359375), - Vec3fEq(71.7976531982421875, -123.98740386962890625, -30.6235561370849609375), - Vec3fEq(95.71018218994140625, -139.18505859375, -25.1958255767822265625), - Vec3fEq(119.6226959228515625, -154.382720947265625, -19.7680912017822265625), - Vec3fEq(143.53521728515625, -169.58038330078125, -14.34035205841064453125), - Vec3fEq(167.4477386474609375, -184.778045654296875, -8.9126186370849609375), - Vec3fEq(191.360260009765625, -199.9757080078125, -3.4848802089691162109375), - Vec3fEq(215, -215, 1.87826788425445556640625) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-189.9427337646484375, 179.3997802734375, -3.622931003570556640625), + Vec3fEq(-175.8854522705078125, 154.7995452880859375, -9.24583911895751953125), + Vec3fEq(-161.82818603515625, 130.1993255615234375, -14.86874866485595703125), + Vec3fEq(-147.770904541015625, 105.5991058349609375, -20.4916591644287109375), + Vec3fEq(-133.7136383056640625, 80.99887847900390625, -26.1145648956298828125), + Vec3fEq(-119.65636444091796875, 56.39865875244140625, -31.7374725341796875), + Vec3fEq(-105.59909820556640625, 31.798435211181640625, -26.133396148681640625), + Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875), + Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625), + Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125), + Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625), + Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625), + Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625), + Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.8243885040283203125), + Vec3fEq(53.413402557373046875, -120.6742401123046875, -31.3303241729736328125), + Vec3fEq(78.20446014404296875, -134.39215087890625, -25.8431549072265625), + Vec3fEq(102.99552154541015625, -148.110076904296875, -20.3559894561767578125), + Vec3fEq(127.7865753173828125, -161.827972412109375, -14.868824005126953125), + Vec3fEq(152.57763671875, -175.5458984375, -9.3816623687744140625), + Vec3fEq(177.3686981201171875, -189.2638092041015625, -3.894496917724609375), + Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.59266507625579833984375), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, update_changed_object_should_change_navmesh) @@ -268,30 +266,30 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.87826788425445556640625), - Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54876613616943359375), - Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97847843170166015625), - Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.408184051513671875), - Vec3fEq(-154.1872711181640625, 119.36397552490234375, -19.837890625), - Vec3fEq(-138.9840850830078125, 95.45496368408203125, -25.2675991058349609375), - Vec3fEq(-123.78090667724609375, 71.54595184326171875, -30.6973056793212890625), - Vec3fEq(-108.57772064208984375, 47.636936187744140625, -36.12701416015625), - Vec3fEq(-93.3745269775390625, 23.7279262542724609375, -40.754688262939453125), - Vec3fEq(-78.17134857177734375, -0.18108306825160980224609375, -37.128787994384765625), - Vec3fEq(-62.968158721923828125, -24.0900936126708984375, -33.50289154052734375), - Vec3fEq(-47.764972686767578125, -47.999103546142578125, -30.797946929931640625), - Vec3fEq(-23.852447509765625, -63.196765899658203125, -33.97112274169921875), - Vec3fEq(0.0600789971649646759033203125, -78.39443206787109375, -37.14543914794921875), - Vec3fEq(23.97260284423828125, -93.5920867919921875, -40.774089813232421875), - Vec3fEq(47.885128021240234375, -108.78974151611328125, -36.05129241943359375), - Vec3fEq(71.7976531982421875, -123.98740386962890625, -30.6235561370849609375), - Vec3fEq(95.71018218994140625, -139.18505859375, -25.1958255767822265625), - Vec3fEq(119.6226959228515625, -154.382720947265625, -19.7680912017822265625), - Vec3fEq(143.53521728515625, -169.58038330078125, -14.34035205841064453125), - Vec3fEq(167.4477386474609375, -184.778045654296875, -8.9126186370849609375), - Vec3fEq(191.360260009765625, -199.9757080078125, -3.4848802089691162109375), - Vec3fEq(215, -215, 1.87826788425445556640625) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-189.9427337646484375, 179.3997802734375, -3.622931003570556640625), + Vec3fEq(-175.8854522705078125, 154.7995452880859375, -9.24583911895751953125), + Vec3fEq(-161.82818603515625, 130.1993255615234375, -14.86874866485595703125), + Vec3fEq(-147.770904541015625, 105.5991058349609375, -20.4916591644287109375), + Vec3fEq(-133.7136383056640625, 80.99887847900390625, -26.1145648956298828125), + Vec3fEq(-119.65636444091796875, 56.39865875244140625, -31.7374725341796875), + Vec3fEq(-105.59909820556640625, 31.798435211181640625, -26.133396148681640625), + Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875), + Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625), + Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125), + Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625), + Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625), + Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625), + Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.8243885040283203125), + Vec3fEq(53.413402557373046875, -120.6742401123046875, -31.3303241729736328125), + Vec3fEq(78.20446014404296875, -134.39215087890625, -25.8431549072265625), + Vec3fEq(102.99552154541015625, -148.110076904296875, -20.3559894561767578125), + Vec3fEq(127.7865753173828125, -161.827972412109375, -14.868824005126953125), + Vec3fEq(152.57763671875, -175.5458984375, -9.3816623687744140625), + Vec3fEq(177.3686981201171875, -189.2638092041015625, -3.894496917724609375), + Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.59266507625579833984375), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; compoundShape.updateChildTransform(0, btTransform(btMatrix3x3::getIdentity(), btVector3(1000, 0, 0))); @@ -304,30 +302,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.85963428020477294921875), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), - Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), - Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), - Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), - Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), - Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), - Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), - Vec3fEq(215, -215, 1.87718021869659423828125) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625), + Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125), + Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875), + Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375), + Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125), + Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375), + Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375), + Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125), + Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625), + Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125), + Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125), + Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125), + Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625), + Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375), + Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875), + Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125), + Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625), + Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125), + Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625), + Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, for_overlapping_heightfields_should_use_higher) @@ -361,30 +358,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.96328866481781005859375), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -0.242215454578399658203125), - Vec3fEq(-174.930633544921875, 174.930633544921875, -2.447719097137451171875), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -4.65322399139404296875), - Vec3fEq(-134.86126708984375, 134.86126708984375, -6.858726978302001953125), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -9.06423282623291015625), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -11.26973628997802734375), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -13.26497173309326171875), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -15.24860477447509765625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -17.23223876953125), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -19.215869903564453125), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -20.1338443756103515625), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -18.1502132415771484375), - Vec3fEq(45.450958251953125, -45.450958251953125, -16.1665802001953125), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -14.18294620513916015625), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -12.199314117431640625), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -10.08488368988037109375), - Vec3fEq(125.5897216796875, -125.5897216796875, -7.87938022613525390625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -5.673875331878662109375), - Vec3fEq(165.659088134765625, -165.659088134765625, -3.468370914459228515625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -1.26286637783050537109375), - Vec3fEq(205.7284698486328125, -205.7284698486328125, 0.942641556262969970703125), - Vec3fEq(215, -215, 1.96328866481781005859375) - )); + Vec3fEq(-204, 204, 1.999981403350830078125), + Vec3fEq(-183.965301513671875, 183.965301513671875, -0.428465187549591064453125), + Vec3fEq(-163.9306182861328125, 163.9306182861328125, -2.8569104671478271484375), + Vec3fEq(-143.89593505859375, 143.89593505859375, -5.28535556793212890625), + Vec3fEq(-123.86124420166015625, 123.86124420166015625, -7.7138004302978515625), + Vec3fEq(-103.8265533447265625, 103.8265533447265625, -10.142246246337890625), + Vec3fEq(-83.7918548583984375, 83.7918548583984375, -12.3704509735107421875), + Vec3fEq(-63.75716400146484375, 63.75716400146484375, -14.354084014892578125), + Vec3fEq(-43.72247314453125, 43.72247314453125, -16.3377170562744140625), + Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -18.32135009765625), + Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -20.3049831390380859375), + Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -19.044734954833984375), + Vec3fEq(36.416290283203125, -36.416290283203125, -17.061100006103515625), + Vec3fEq(56.450984954833984375, -56.450984954833984375, -15.0774688720703125), + Vec3fEq(76.4856719970703125, -76.4856719970703125, -13.0938358306884765625), + Vec3fEq(96.52036285400390625, -96.52036285400390625, -11.02784252166748046875), + Vec3fEq(116.5550537109375, -116.5550537109375, -8.5993976593017578125), + Vec3fEq(136.5897369384765625, -136.5897369384765625, -6.170953273773193359375), + Vec3fEq(156.6244354248046875, -156.6244354248046875, -3.74250507354736328125), + Vec3fEq(176.6591339111328125, -176.6591339111328125, -1.314060688018798828125), + Vec3fEq(196.693817138671875, -196.693817138671875, 1.1143856048583984375), + Vec3fEq(204, -204, 1.9999811649322509765625) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape) @@ -417,31 +413,30 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.9393787384033203125), - Vec3fEq(-200.8159637451171875, 190.47265625, -0.639537751674652099609375), - Vec3fEq(-186.6319427490234375, 165.9453125, -3.2184507846832275390625), - Vec3fEq(-172.447906494140625, 141.41796875, -5.797363758087158203125), - Vec3fEq(-158.263885498046875, 116.8906097412109375, -8.37627696990966796875), - Vec3fEq(-144.079864501953125, 92.3632659912109375, -10.9551906585693359375), - Vec3fEq(-129.89581298828125, 67.83591461181640625, -13.53410625457763671875), - Vec3fEq(-115.7117919921875, 43.308563232421875, -16.1130199432373046875), - Vec3fEq(-101.5277557373046875, 18.7812137603759765625, -18.6919345855712890625), - Vec3fEq(-87.34372711181640625, -5.7461376190185546875, -20.4680538177490234375), - Vec3fEq(-67.02922821044921875, -25.4970550537109375, -20.514247894287109375), - Vec3fEq(-46.714717864990234375, -45.2479705810546875, -20.560443878173828125), - Vec3fEq(-26.40021514892578125, -64.99889373779296875, -20.6066417694091796875), - Vec3fEq(-6.085712432861328125, -84.74980926513671875, -20.652835845947265625), - Vec3fEq(14.22879505157470703125, -104.50072479248046875, -18.151397705078125), - Vec3fEq(39.05098724365234375, -118.16222381591796875, -15.66748714447021484375), - Vec3fEq(63.87317657470703125, -131.82373046875, -13.18358135223388671875), - Vec3fEq(88.69537353515625, -145.4852142333984375, -10.699672698974609375), - Vec3fEq(113.51757049560546875, -159.146697998046875, -8.21576786041259765625), - Vec3fEq(138.3397674560546875, -172.808197021484375, -5.731859683990478515625), - Vec3fEq(163.1619720458984375, -186.469696044921875, -3.2479507923126220703125), - Vec3fEq(187.984161376953125, -200.1311798095703125, -0.764044821262359619140625), - Vec3fEq(212.8063507080078125, -213.7926788330078125, 1.719865322113037109375), - Vec3fEq(215, -215, 1.9393787384033203125) - )); + Vec3fEq(-204, 204, 1.99997997283935546875), + Vec3fEq(-191.328948974609375, 178.65789794921875, -0.815807759761810302734375), + Vec3fEq(-178.65789794921875, 153.3157806396484375, -3.6315968036651611328125), + Vec3fEq(-165.986846923828125, 127.9736785888671875, -6.4473857879638671875), + Vec3fEq(-153.3157806396484375, 102.6315765380859375, -9.26317310333251953125), + Vec3fEq(-140.6447296142578125, 77.28946685791015625, -12.07896137237548828125), + Vec3fEq(-127.9736785888671875, 51.947368621826171875, -14.894748687744140625), + Vec3fEq(-115.3026275634765625, 26.6052646636962890625, -17.7105388641357421875), + Vec3fEq(-102.63158416748046875, 1.2631585597991943359375, -20.5263233184814453125), + Vec3fEq(-89.9605712890625, -24.0789661407470703125, -19.591716766357421875), + Vec3fEq(-68.54410552978515625, -42.629238128662109375, -19.847625732421875), + Vec3fEq(-47.127635955810546875, -61.17951202392578125, -20.1035366058349609375), + Vec3fEq(-25.711170196533203125, -79.72978973388671875, -20.359447479248046875), + Vec3fEq(-4.294706821441650390625, -98.280059814453125, -20.6153545379638671875), + Vec3fEq(17.121753692626953125, -116.83034515380859375, -17.3710460662841796875), + Vec3fEq(42.7990570068359375, -128.80755615234375, -14.7094440460205078125), + Vec3fEq(68.4763641357421875, -140.7847747802734375, -12.0478420257568359375), + Vec3fEq(94.15366363525390625, -152.761993408203125, -9.3862361907958984375), + Vec3fEq(119.83097076416015625, -164.7392120361328125, -6.724635601043701171875), + Vec3fEq(145.508270263671875, -176.7164306640625, -4.06303119659423828125), + Vec3fEq(171.185577392578125, -188.69366455078125, -1.40142619609832763671875), + Vec3fEq(196.862884521484375, -200.6708831787109375, 1.2601754665374755859375), + Vec3fEq(204, -204, 1.999979496002197265625) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_ground_lower_than_water_with_only_swim_flag) @@ -469,25 +464,24 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mAreaCosts, mOut), Status::Success); - EXPECT_EQ(mPath, std::deque({ - osg::Vec3f(0, 215, 185.33331298828125), - osg::Vec3f(0, 186.6666717529296875, 185.33331298828125), - osg::Vec3f(0, 158.333343505859375, 185.33331298828125), - osg::Vec3f(0, 130.0000152587890625, 185.33331298828125), - osg::Vec3f(0, 101.66667938232421875, 185.33331298828125), - osg::Vec3f(0, 73.333343505859375, 185.33331298828125), - osg::Vec3f(0, 45.0000152587890625, 185.33331298828125), - osg::Vec3f(0, 16.6666812896728515625, 185.33331298828125), - osg::Vec3f(0, -11.66664981842041015625, 185.33331298828125), - osg::Vec3f(0, -39.999980926513671875, 185.33331298828125), - osg::Vec3f(0, -68.33331298828125, 185.33331298828125), - osg::Vec3f(0, -96.66664886474609375, 185.33331298828125), - osg::Vec3f(0, -124.99997711181640625, 185.33331298828125), - osg::Vec3f(0, -153.33331298828125, 185.33331298828125), - osg::Vec3f(0, -181.6666412353515625, 185.33331298828125), - osg::Vec3f(0, -209.999969482421875, 185.33331298828125), - osg::Vec3f(0, -215, 185.33331298828125), - })) << mPath; + EXPECT_THAT(mPath, ElementsAre( + Vec3fEq(0, 204, 185.33331298828125), + Vec3fEq(0, 175.6666717529296875, 185.33331298828125), + Vec3fEq(0, 147.3333282470703125, 185.33331298828125), + Vec3fEq(0, 119, 185.33331298828125), + Vec3fEq(0, 90.6666717529296875, 185.33331298828125), + Vec3fEq(0, 62.333339691162109375, 185.33331298828125), + Vec3fEq(0, 34.00000762939453125, 185.33331298828125), + Vec3fEq(0, 5.66667461395263671875, 185.33331298828125), + Vec3fEq(0, -22.6666584014892578125, 185.33331298828125), + Vec3fEq(0, -50.999988555908203125, 185.33331298828125), + Vec3fEq(0, -79.33332061767578125, 185.33331298828125), + Vec3fEq(0, -107.666656494140625, 185.33331298828125), + Vec3fEq(0, -135.9999847412109375, 185.33331298828125), + Vec3fEq(0, -164.33331298828125, 185.33331298828125), + Vec3fEq(0, -192.666656494140625, 185.33331298828125), + Vec3fEq(0, -204, 185.33331298828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_when_ground_cross_water_with_swim_and_walk_flags) @@ -516,25 +510,24 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mOut), Status::Success); - EXPECT_EQ(mPath, std::deque({ - osg::Vec3f(0, 215, -94.75363922119140625), - osg::Vec3f(0, 186.6666717529296875, -106.0000152587890625), - osg::Vec3f(0, 158.333343505859375, -115.85507965087890625), - osg::Vec3f(0, 130.0000152587890625, -125.71016693115234375), - osg::Vec3f(0, 101.66667938232421875, -135.5652313232421875), - osg::Vec3f(0, 73.333343505859375, -143.3333587646484375), - osg::Vec3f(0, 45.0000152587890625, -143.3333587646484375), - osg::Vec3f(0, 16.6666812896728515625, -143.3333587646484375), - osg::Vec3f(0, -11.66664981842041015625, -143.3333587646484375), - osg::Vec3f(0, -39.999980926513671875, -143.3333587646484375), - osg::Vec3f(0, -68.33331298828125, -143.3333587646484375), - osg::Vec3f(0, -96.66664886474609375, -137.3043670654296875), - osg::Vec3f(0, -124.99997711181640625, -127.44930267333984375), - osg::Vec3f(0, -153.33331298828125, -117.59423065185546875), - osg::Vec3f(0, -181.6666412353515625, -107.73915863037109375), - osg::Vec3f(0, -209.999969482421875, -97.7971343994140625), - osg::Vec3f(0, -215, -94.75363922119140625), - })) << mPath; + EXPECT_THAT(mPath, ElementsAre( + Vec3fEq(0, 204, -98.000030517578125), + Vec3fEq(0, 175.6666717529296875, -108.30306243896484375), + Vec3fEq(0, 147.3333282470703125, -118.6060791015625), + Vec3fEq(0, 119, -128.90911865234375), + Vec3fEq(0, 90.6666717529296875, -139.2121429443359375), + Vec3fEq(0, 62.333339691162109375, -143.3333587646484375), + Vec3fEq(0, 34.00000762939453125, -143.3333587646484375), + Vec3fEq(0, 5.66667461395263671875, -143.3333587646484375), + Vec3fEq(0, -22.6666584014892578125, -143.3333587646484375), + Vec3fEq(0, -50.999988555908203125, -143.3333587646484375), + Vec3fEq(0, -79.33332061767578125, -143.3333587646484375), + Vec3fEq(0, -107.666656494140625, -133.0303192138671875), + Vec3fEq(0, -135.9999847412109375, -122.72728729248046875), + Vec3fEq(0, -164.33331298828125, -112.4242706298828125), + Vec3fEq(0, -192.666656494140625, -102.12123870849609375), + Vec3fEq(0, -204, -98.00002288818359375) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_water_when_ground_cross_water_with_max_int_cells_size_and_swim_and_walk_flags) @@ -563,25 +556,24 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mAreaCosts, mOut), Status::Success); - EXPECT_EQ(mPath, std::deque({ - osg::Vec3f(0, 215, -94.75363922119140625), - osg::Vec3f(0, 186.6666717529296875, -106.0000152587890625), - osg::Vec3f(0, 158.333343505859375, -115.85507965087890625), - osg::Vec3f(0, 130.0000152587890625, -125.71016693115234375), - osg::Vec3f(0, 101.66667938232421875, -135.5652313232421875), - osg::Vec3f(0, 73.333343505859375, -143.3333587646484375), - osg::Vec3f(0, 45.0000152587890625, -143.3333587646484375), - osg::Vec3f(0, 16.6666812896728515625, -143.3333587646484375), - osg::Vec3f(0, -11.66664981842041015625, -143.3333587646484375), - osg::Vec3f(0, -39.999980926513671875, -143.3333587646484375), - osg::Vec3f(0, -68.33331298828125, -143.3333587646484375), - osg::Vec3f(0, -96.66664886474609375, -137.3043670654296875), - osg::Vec3f(0, -124.99997711181640625, -127.44930267333984375), - osg::Vec3f(0, -153.33331298828125, -117.59423065185546875), - osg::Vec3f(0, -181.6666412353515625, -107.73915863037109375), - osg::Vec3f(0, -209.999969482421875, -97.7971343994140625), - osg::Vec3f(0, -215, -94.75363922119140625), - })) << mPath; + EXPECT_THAT(mPath, ElementsAre( + Vec3fEq(0, 204, -98.000030517578125), + Vec3fEq(0, 175.6666717529296875, -108.30306243896484375), + Vec3fEq(0, 147.3333282470703125, -118.6060791015625), + Vec3fEq(0, 119, -128.90911865234375), + Vec3fEq(0, 90.6666717529296875, -139.2121429443359375), + Vec3fEq(0, 62.333339691162109375, -143.3333587646484375), + Vec3fEq(0, 34.00000762939453125, -143.3333587646484375), + Vec3fEq(0, 5.66667461395263671875, -143.3333587646484375), + Vec3fEq(0, -22.6666584014892578125, -143.3333587646484375), + Vec3fEq(0, -50.999988555908203125, -143.3333587646484375), + Vec3fEq(0, -79.33332061767578125, -143.3333587646484375), + Vec3fEq(0, -107.666656494140625, -133.0303192138671875), + Vec3fEq(0, -135.9999847412109375, -122.72728729248046875), + Vec3fEq(0, -164.33331298828125, -112.4242706298828125), + Vec3fEq(0, -192.666656494140625, -102.12123870849609375), + Vec3fEq(0, -204, -98.00002288818359375) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, path_should_be_over_ground_when_ground_cross_water_with_only_walk_flag) @@ -610,25 +602,24 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(0, 215, -94.75363922119140625), - Vec3fEq(9.8083515167236328125, 188.4185333251953125, -105.199951171875), - Vec3fEq(19.6167049407958984375, 161.837066650390625, -114.25495147705078125), - Vec3fEq(29.42505645751953125, 135.255615234375, -123.309967041015625), - Vec3fEq(39.23340606689453125, 108.674163818359375, -132.3649749755859375), - Vec3fEq(49.04175567626953125, 82.09270477294921875, -137.2874755859375), - Vec3fEq(58.8501129150390625, 55.5112457275390625, -139.2451171875), - Vec3fEq(68.6584625244140625, 28.9297885894775390625, -141.2027740478515625), - Vec3fEq(78.4668121337890625, 2.3483295440673828125, -143.1604156494140625), - Vec3fEq(88.27516937255859375, -24.233127593994140625, -141.3894805908203125), - Vec3fEq(83.73651885986328125, -52.2005767822265625, -142.3761444091796875), - Vec3fEq(79.19786834716796875, -80.16802978515625, -143.114837646484375), - Vec3fEq(64.8477935791015625, -104.598602294921875, -137.840911865234375), - Vec3fEq(50.497714996337890625, -129.0291748046875, -131.45831298828125), - Vec3fEq(36.147632598876953125, -153.459747314453125, -121.42321014404296875), - Vec3fEq(21.7975559234619140625, -177.8903350830078125, -111.38811492919921875), - Vec3fEq(7.44747829437255859375, -202.3209075927734375, -101.19382476806640625), - Vec3fEq(0, -215, -94.75363922119140625) - )); + Vec3fEq(0, 204, -98.000030517578125), + Vec3fEq(10.26930999755859375, 177.59320068359375, -107.4711456298828125), + Vec3fEq(20.5386199951171875, 151.1864166259765625, -116.9422607421875), + Vec3fEq(30.8079280853271484375, 124.77960968017578125, -126.41339111328125), + Vec3fEq(41.077239990234375, 98.37281036376953125, -135.8845062255859375), + Vec3fEq(51.346546173095703125, 71.96601104736328125, -138.2003936767578125), + Vec3fEq(61.615856170654296875, 45.559215545654296875, -140.0838470458984375), + Vec3fEq(71.88516998291015625, 19.1524181365966796875, -141.9673004150390625), + Vec3fEq(82.15447235107421875, -7.254379749298095703125, -142.3074798583984375), + Vec3fEq(81.04636383056640625, -35.56603240966796875, -142.7104339599609375), + Vec3fEq(79.93825531005859375, -63.877685546875, -143.1133880615234375), + Vec3fEq(78.83014678955078125, -92.18933868408203125, -138.7660675048828125), + Vec3fEq(62.50392913818359375, -115.3460235595703125, -130.237823486328125), + Vec3fEq(46.17771148681640625, -138.502716064453125, -121.8172149658203125), + Vec3fEq(29.85149383544921875, -161.6594085693359375, -113.39659881591796875), + Vec3fEq(13.52527523040771484375, -184.81610107421875, -104.97599029541015625), + Vec3fEq(0, -204, -98.00002288818359375) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, update_remove_and_update_then_find_path_should_return_path) @@ -659,30 +650,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.85963428020477294921875), - Vec3fEq(-194.9653167724609375, 194.9653167724609375, -6.57602214813232421875), - Vec3fEq(-174.930633544921875, 174.930633544921875, -15.01167774200439453125), - Vec3fEq(-154.8959503173828125, 154.8959503173828125, -23.4473361968994140625), - Vec3fEq(-134.86126708984375, 134.86126708984375, -31.8829936981201171875), - Vec3fEq(-114.82657623291015625, 114.82657623291015625, -40.3186492919921875), - Vec3fEq(-94.7918853759765625, 94.7918853759765625, -47.3990631103515625), - Vec3fEq(-74.75719451904296875, 74.75719451904296875, -53.7258148193359375), - Vec3fEq(-54.722499847412109375, 54.722499847412109375, -60.052555084228515625), - Vec3fEq(-34.68780517578125, 34.68780517578125, -66.37931060791015625), - Vec3fEq(-14.6531162261962890625, 14.6531162261962890625, -72.70604705810546875), - Vec3fEq(5.3815765380859375, -5.3815765380859375, -75.35065460205078125), - Vec3fEq(25.41626739501953125, -25.41626739501953125, -67.9694671630859375), - Vec3fEq(45.450958251953125, -45.450958251953125, -60.5882568359375), - Vec3fEq(65.48564910888671875, -65.48564910888671875, -53.20705413818359375), - Vec3fEq(85.5203399658203125, -85.5203399658203125, -45.8258514404296875), - Vec3fEq(105.55503082275390625, -105.55503082275390625, -38.44464874267578125), - Vec3fEq(125.5897216796875, -125.5897216796875, -31.063449859619140625), - Vec3fEq(145.6244049072265625, -145.6244049072265625, -23.6822509765625), - Vec3fEq(165.659088134765625, -165.659088134765625, -16.3010501861572265625), - Vec3fEq(185.6937713623046875, -185.6937713623046875, -8.91985416412353515625), - Vec3fEq(205.7284698486328125, -205.7284698486328125, -1.5386505126953125), - Vec3fEq(215, -215, 1.87718021869659423828125) - )); + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-183.965301513671875, 183.965301513671875, 1.99998819828033447265625), + Vec3fEq(-163.9306182861328125, 163.9306182861328125, 1.99999344348907470703125), + Vec3fEq(-143.89593505859375, 143.89593505859375, -2.7206256389617919921875), + Vec3fEq(-123.86124420166015625, 123.86124420166015625, -13.1089839935302734375), + Vec3fEq(-103.8265533447265625, 103.8265533447265625, -23.4973468780517578125), + Vec3fEq(-83.7918548583984375, 83.7918548583984375, -33.885707855224609375), + Vec3fEq(-63.75716400146484375, 63.75716400146484375, -44.27407073974609375), + Vec3fEq(-43.72247314453125, 43.72247314453125, -54.662433624267578125), + Vec3fEq(-23.6877803802490234375, 23.6877803802490234375, -65.0507965087890625), + Vec3fEq(-3.653090000152587890625, 3.653090000152587890625, -75.43915557861328125), + Vec3fEq(16.3816013336181640625, -16.3816013336181640625, -69.749267578125), + Vec3fEq(36.416290283203125, -36.416290283203125, -60.4739532470703125), + Vec3fEq(56.450984954833984375, -56.450984954833984375, -51.1986236572265625), + Vec3fEq(76.4856719970703125, -76.4856719970703125, -41.92330169677734375), + Vec3fEq(96.52036285400390625, -96.52036285400390625, -31.46941375732421875), + Vec3fEq(116.5550537109375, -116.5550537109375, -19.597003936767578125), + Vec3fEq(136.5897369384765625, -136.5897369384765625, -7.724592685699462890625), + Vec3fEq(156.6244354248046875, -156.6244354248046875, 1.99999535083770751953125), + Vec3fEq(176.6591339111328125, -176.6591339111328125, 1.99999010562896728515625), + Vec3fEq(196.693817138671875, -196.693817138671875, 1.99998486042022705078125), + Vec3fEq(204, -204, 1.99998295307159423828125) + )) << mPath; } TEST_F(DetourNavigatorNavigatorTest, update_then_find_random_point_around_circle_should_return_position) @@ -706,11 +696,12 @@ namespace const auto result = mNavigator->findRandomPointAroundCircle(mAgentHalfExtents, mStart, 100.0, Flag_walk); - ASSERT_THAT(result, Optional(Vec3fEq(-209.95985412597656, 129.89768981933594, -0.26253718137741089))); + ASSERT_THAT(result, Optional(Vec3fEq(-198.909332275390625, 123.06096649169921875, 1.99998414516448974609375))) + << (result ? *result : osg::Vec3f()); const auto distance = (*result - mStart).length(); - EXPECT_FLOAT_EQ(distance, 85.260780334472656); + EXPECT_FLOAT_EQ(distance, 81.105133056640625) << distance; } TEST_F(DetourNavigatorNavigatorTest, multiple_threads_should_lock_tiles) @@ -754,29 +745,29 @@ namespace EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); EXPECT_THAT(mPath, ElementsAre( - Vec3fEq(-215, 215, 1.8782780170440673828125), - Vec3fEq(-199.7968292236328125, 191.09100341796875, -3.54875946044921875), - Vec3fEq(-184.5936431884765625, 167.1819915771484375, -8.97846889495849609375), - Vec3fEq(-169.3904571533203125, 143.2729949951171875, -14.40818119049072265625), - Vec3fEq(-154.1872711181640625, 119.363983154296875, -19.837886810302734375), - Vec3fEq(-138.9840850830078125, 95.4549713134765625, -25.2675952911376953125), - Vec3fEq(-123.78090667724609375, 71.54595947265625, -30.6973056793212890625), - Vec3fEq(-108.57772064208984375, 47.63695526123046875, -36.12701416015625), - Vec3fEq(-93.3745269775390625, 23.72794342041015625, -40.754695892333984375), - Vec3fEq(-78.17134857177734375, -0.18106450140476226806640625, -37.128795623779296875), - Vec3fEq(-62.968158721923828125, -24.0900726318359375, -33.50289154052734375), - Vec3fEq(-47.764972686767578125, -47.99908447265625, -30.797946929931640625), - Vec3fEq(-23.8524494171142578125, -63.196746826171875, -33.97112274169921875), - Vec3fEq(0.0600722394883632659912109375, -78.3944091796875, -37.14543914794921875), - Vec3fEq(23.97259521484375, -93.592071533203125, -40.774089813232421875), - Vec3fEq(47.885120391845703125, -108.78974151611328125, -36.051296234130859375), - Vec3fEq(71.797637939453125, -123.98740386962890625, -30.62355804443359375), - Vec3fEq(95.71016693115234375, -139.18505859375, -25.195819854736328125), - Vec3fEq(119.6226806640625, -154.382720947265625, -19.768085479736328125), - Vec3fEq(143.5352020263671875, -169.5803680419921875, -14.34035015106201171875), - Vec3fEq(167.447723388671875, -184.7780303955078125, -8.912616729736328125), - Vec3fEq(191.3602294921875, -199.9756927490234375, -3.48488140106201171875), - Vec3fEq(215, -215, 1.8782813549041748046875) + Vec3fEq(-204, 204, 1.99998295307159423828125), + Vec3fEq(-189.9427337646484375, 179.3997802734375, 1.9999866485595703125), + Vec3fEq(-175.8854522705078125, 154.7995452880859375, 1.99999034404754638671875), + Vec3fEq(-161.82818603515625, 130.1993255615234375, -3.701923847198486328125), + Vec3fEq(-147.770904541015625, 105.5991058349609375, -15.67664432525634765625), + Vec3fEq(-133.7136383056640625, 80.99887847900390625, -27.6513614654541015625), + Vec3fEq(-119.65636444091796875, 56.39865875244140625, -20.1209163665771484375), + Vec3fEq(-105.59909820556640625, 31.798435211181640625, -25.0669879913330078125), + Vec3fEq(-91.54183197021484375, 7.1982135772705078125, -31.5624217987060546875), + Vec3fEq(-77.48455810546875, -17.402008056640625, -26.98972320556640625), + Vec3fEq(-63.427295684814453125, -42.00223541259765625, -19.9045581817626953125), + Vec3fEq(-42.193531036376953125, -60.761363983154296875, -20.4544773101806640625), + Vec3fEq(-20.9597682952880859375, -79.5204925537109375, -23.599918365478515625), + Vec3fEq(3.8312885761260986328125, -93.2384033203125, -30.7141361236572265625), + Vec3fEq(28.6223468780517578125, -106.95632171630859375, -24.1782474517822265625), + Vec3fEq(53.413402557373046875, -120.6742401123046875, -19.4096889495849609375), + Vec3fEq(78.20446014404296875, -134.39215087890625, -27.6632633209228515625), + Vec3fEq(102.99552154541015625, -148.110076904296875, -15.8613681793212890625), + Vec3fEq(127.7865753173828125, -161.827972412109375, -4.059485912322998046875), + Vec3fEq(152.57763671875, -175.5458984375, 1.9999904632568359375), + Vec3fEq(177.3686981201171875, -189.2638092041015625, 1.9999866485595703125), + Vec3fEq(202.1597442626953125, -202.9817047119140625, 1.9999830722808837890625), + Vec3fEq(204, -204, 1.99998295307159423828125) )) << mPath; } @@ -836,7 +827,8 @@ namespace const auto result = mNavigator->raycast(mAgentHalfExtents, mStart, mEnd, Flag_walk); - ASSERT_THAT(result, Optional(Vec3fEq(mEnd.x(), mEnd.y(), 1.87719))); + ASSERT_THAT(result, Optional(Vec3fEq(mEnd.x(), mEnd.y(), 1.99998295307159423828125))) + << (result ? *result : osg::Vec3f()); } TEST_F(DetourNavigatorNavigatorTest, update_for_oscillating_object_that_does_not_change_navmesh_should_not_trigger_navmesh_update) diff --git a/components/detournavigator/settingsutils.hpp b/components/detournavigator/settingsutils.hpp index 8f1c96e286..245e4a7e56 100644 --- a/components/detournavigator/settingsutils.hpp +++ b/components/detournavigator/settingsutils.hpp @@ -12,7 +12,8 @@ #include #include -#include +#include +#include namespace DetourNavigator { @@ -28,7 +29,7 @@ namespace DetourNavigator inline float getRadius(const Settings& settings, const osg::Vec3f& agentHalfExtents) { - return agentHalfExtents.x() * settings.mRecastScaleFactor; + return std::max(agentHalfExtents.x(), agentHalfExtents.y()) * std::sqrt(2) * settings.mRecastScaleFactor; } inline float toNavMeshCoordinates(const Settings& settings, float value) From 3e98db8d60174b1fb8ed5ac61dfefc6e50f89223 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 27 Jun 2021 15:23:15 +0200 Subject: [PATCH 20/57] Fix styleguide --- components/detournavigator/offmeshconnectionsmanager.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/detournavigator/offmeshconnectionsmanager.hpp b/components/detournavigator/offmeshconnectionsmanager.hpp index 1ad96e3b97..2755adc8ba 100644 --- a/components/detournavigator/offmeshconnectionsmanager.hpp +++ b/components/detournavigator/offmeshconnectionsmanager.hpp @@ -47,9 +47,8 @@ namespace DetourNavigator const auto byId = values->mById.equal_range(id); - if (byId.first == byId.second) { + if (byId.first == byId.second) return {}; - } std::set removed; From 7f65a2c4c24865d93e70a5e7d738db64a2831bee Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 27 Jun 2021 16:38:43 +0200 Subject: [PATCH 21/57] Remove unused code --- components/detournavigator/offmeshconnectionsmanager.hpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/components/detournavigator/offmeshconnectionsmanager.hpp b/components/detournavigator/offmeshconnectionsmanager.hpp index 2755adc8ba..6050da8a01 100644 --- a/components/detournavigator/offmeshconnectionsmanager.hpp +++ b/components/detournavigator/offmeshconnectionsmanager.hpp @@ -98,14 +98,6 @@ namespace DetourNavigator const Settings& mSettings; Misc::ScopeGuarded mValues; - - void removeByTilePosition(std::map>& valuesByTilePosition, - const TilePosition& tilePosition, const ObjectId id) - { - const auto it = valuesByTilePosition.find(tilePosition); - if (it != valuesByTilePosition.end()) - it->second.erase(id); - } }; } From 81e569c3d985d2d22549472642564c5e43aee6ac Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 27 Jun 2021 16:22:30 +0200 Subject: [PATCH 22/57] Move OffMeshConnectionsManager implementation into cpp --- components/CMakeLists.txt | 1 + .../offmeshconnectionsmanager.cpp | 80 +++++++++++++++++++ .../offmeshconnectionsmanager.hpp | 71 +--------------- 3 files changed, 85 insertions(+), 67 deletions(-) create mode 100644 components/detournavigator/offmeshconnectionsmanager.cpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 06ae0791d7..7860f492ce 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -183,6 +183,7 @@ add_component_dir(detournavigator raycast navmeshtileview oscillatingrecastmeshobject + offmeshconnectionsmanager ) set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui diff --git a/components/detournavigator/offmeshconnectionsmanager.cpp b/components/detournavigator/offmeshconnectionsmanager.cpp new file mode 100644 index 0000000000..bb2ed773a5 --- /dev/null +++ b/components/detournavigator/offmeshconnectionsmanager.cpp @@ -0,0 +1,80 @@ +#include "offmeshconnectionsmanager.hpp" +#include "settings.hpp" +#include "settingsutils.hpp" +#include "tileposition.hpp" +#include "objectid.hpp" +#include "offmeshconnection.hpp" + +#include +#include +#include + +namespace DetourNavigator +{ + OffMeshConnectionsManager::OffMeshConnectionsManager(const Settings& settings) + : mSettings(settings) + {} + + void OffMeshConnectionsManager::add(const ObjectId id, const OffMeshConnection& value) + { + const auto values = mValues.lock(); + + values->mById.insert(std::make_pair(id, value)); + + const auto startTilePosition = getTilePosition(mSettings, value.mStart); + const auto endTilePosition = getTilePosition(mSettings, value.mEnd); + + values->mByTilePosition[startTilePosition].insert(id); + + if (startTilePosition != endTilePosition) + values->mByTilePosition[endTilePosition].insert(id); + } + + std::set OffMeshConnectionsManager::remove(const ObjectId id) + { + const auto values = mValues.lock(); + + const auto byId = values->mById.equal_range(id); + + if (byId.first == byId.second) + return {}; + + std::set removed; + + std::for_each(byId.first, byId.second, [&] (const auto& v) { + const auto startTilePosition = getTilePosition(mSettings, v.second.mStart); + const auto endTilePosition = getTilePosition(mSettings, v.second.mEnd); + + removed.emplace(startTilePosition); + if (startTilePosition != endTilePosition) + removed.emplace(endTilePosition); + }); + + values->mById.erase(byId.first, byId.second); + + return removed; + } + + std::vector OffMeshConnectionsManager::get(const TilePosition& tilePosition) + { + std::vector result; + + const auto values = mValues.lock(); + + const auto itByTilePosition = values->mByTilePosition.find(tilePosition); + + if (itByTilePosition == values->mByTilePosition.end()) + return result; + + std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), + [&] (const ObjectId v) + { + const auto byId = values->mById.equal_range(v); + std::for_each(byId.first, byId.second, [&] (const auto& v) { result.push_back(v.second); }); + }); + + std::sort(result.begin(), result.end()); + + return result; + } +} diff --git a/components/detournavigator/offmeshconnectionsmanager.hpp b/components/detournavigator/offmeshconnectionsmanager.hpp index 6050da8a01..20a6427cd5 100644 --- a/components/detournavigator/offmeshconnectionsmanager.hpp +++ b/components/detournavigator/offmeshconnectionsmanager.hpp @@ -2,16 +2,12 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTIONSMANAGER_H #include "settings.hpp" -#include "settingsutils.hpp" #include "tileposition.hpp" #include "objectid.hpp" #include "offmeshconnection.hpp" #include -#include - -#include #include #include #include @@ -22,72 +18,13 @@ namespace DetourNavigator class OffMeshConnectionsManager { public: - OffMeshConnectionsManager(const Settings& settings) - : mSettings(settings) - {} + OffMeshConnectionsManager(const Settings& settings); - void add(const ObjectId id, const OffMeshConnection& value) - { - const auto values = mValues.lock(); + void add(const ObjectId id, const OffMeshConnection& value); - values->mById.insert(std::make_pair(id, value)); + std::set remove(const ObjectId id); - const auto startTilePosition = getTilePosition(mSettings, value.mStart); - const auto endTilePosition = getTilePosition(mSettings, value.mEnd); - - values->mByTilePosition[startTilePosition].insert(id); - - if (startTilePosition != endTilePosition) - values->mByTilePosition[endTilePosition].insert(id); - } - - std::set remove(const ObjectId id) - { - const auto values = mValues.lock(); - - const auto byId = values->mById.equal_range(id); - - if (byId.first == byId.second) - return {}; - - std::set removed; - - std::for_each(byId.first, byId.second, [&] (const auto& v) { - const auto startTilePosition = getTilePosition(mSettings, v.second.mStart); - const auto endTilePosition = getTilePosition(mSettings, v.second.mEnd); - - removed.emplace(startTilePosition); - if (startTilePosition != endTilePosition) - removed.emplace(endTilePosition); - }); - - values->mById.erase(byId.first, byId.second); - - return removed; - } - - std::vector get(const TilePosition& tilePosition) - { - std::vector result; - - const auto values = mValues.lock(); - - const auto itByTilePosition = values->mByTilePosition.find(tilePosition); - - if (itByTilePosition == values->mByTilePosition.end()) - return result; - - std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), - [&] (const ObjectId v) - { - const auto byId = values->mById.equal_range(v); - std::for_each(byId.first, byId.second, [&] (const auto& v) { result.push_back(v.second); }); - }); - - std::sort(result.begin(), result.end()); - - return result; - } + std::vector get(const TilePosition& tilePosition); private: struct Values From a8ba9a0e2a778ffb36bb308b613923ffdad60f5b Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 27 Jun 2021 16:25:56 +0200 Subject: [PATCH 23/57] Cleanup unused tile positions from OffMeshConnectionsManager --- .../detournavigator/offmeshconnectionsmanager.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/detournavigator/offmeshconnectionsmanager.cpp b/components/detournavigator/offmeshconnectionsmanager.cpp index bb2ed773a5..c483934fb4 100644 --- a/components/detournavigator/offmeshconnectionsmanager.cpp +++ b/components/detournavigator/offmeshconnectionsmanager.cpp @@ -50,6 +50,16 @@ namespace DetourNavigator removed.emplace(endTilePosition); }); + for (const TilePosition& tilePosition : removed) + { + const auto it = values->mByTilePosition.find(tilePosition); + if (it == values->mByTilePosition.end()) + continue; + it->second.erase(id); + if (it->second.empty()) + values->mByTilePosition.erase(it); + } + values->mById.erase(byId.first, byId.second); return removed; From ff1af5e8ec5a2a8a52e7ef8ad90181b4f25d79aa Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 27 Jun 2021 16:36:28 +0200 Subject: [PATCH 24/57] Use only off mesh connections starting or ending in a given tile --- components/detournavigator/offmeshconnectionsmanager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/detournavigator/offmeshconnectionsmanager.cpp b/components/detournavigator/offmeshconnectionsmanager.cpp index c483934fb4..a673ae3e68 100644 --- a/components/detournavigator/offmeshconnectionsmanager.cpp +++ b/components/detournavigator/offmeshconnectionsmanager.cpp @@ -80,7 +80,12 @@ namespace DetourNavigator [&] (const ObjectId v) { const auto byId = values->mById.equal_range(v); - std::for_each(byId.first, byId.second, [&] (const auto& v) { result.push_back(v.second); }); + std::for_each(byId.first, byId.second, [&] (const auto& v) + { + if (getTilePosition(mSettings, v.second.mStart) == tilePosition + || getTilePosition(mSettings, v.second.mEnd) == tilePosition) + result.push_back(v.second); + }); }); std::sort(result.begin(), result.end()); From 1552e7e3e32fcc2ba686f04a45968df917dca7a1 Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 27 Jun 2021 17:45:40 +0200 Subject: [PATCH 25/57] Add pathgrid edges as one direction off mesh connection --- components/detournavigator/makenavmesh.cpp | 2 +- components/detournavigator/navigatorimpl.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index bcfd1b22fd..422fdffb1d 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -389,7 +389,7 @@ namespace const auto offMeshConVerts = getOffMeshVerts(offMeshConnections); const std::vector offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents)); - const std::vector offMeshConDir(offMeshConnections.size(), DT_OFFMESH_CON_BIDIR); + const std::vector offMeshConDir(offMeshConnections.size(), 0); const std::vector offMeshConAreas = getOffMeshConAreas(offMeshConnections); const std::vector offMeshConFlags = getOffMeshFlags(offMeshConnections); diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index b7b3bbd586..1aa4768de5 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -55,12 +55,10 @@ namespace DetourNavigator { if (addObject(id, static_cast(shapes), transform)) { - mNavMeshManager.addOffMeshConnection( - id, - toNavMeshCoordinates(mSettings, shapes.mConnectionStart), - toNavMeshCoordinates(mSettings, shapes.mConnectionEnd), - AreaType_door - ); + const osg::Vec3f start = toNavMeshCoordinates(mSettings, shapes.mConnectionStart); + const osg::Vec3f end = toNavMeshCoordinates(mSettings, shapes.mConnectionEnd); + mNavMeshManager.addOffMeshConnection(id, start, end, AreaType_door); + mNavMeshManager.addOffMeshConnection(id, end, start, AreaType_door); return true; } return false; From 8d2cdedc87243f23f75e69edd60b9f9bb51009c8 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 28 Jun 2021 00:18:41 +0200 Subject: [PATCH 26/57] Show number of pathgrid node in a tooltip To allow users faster understand what node it is. --- apps/opencs/view/render/cellarrow.cpp | 2 +- apps/opencs/view/render/cellarrow.hpp | 2 +- apps/opencs/view/render/object.cpp | 2 +- apps/opencs/view/render/object.hpp | 2 +- apps/opencs/view/render/pathgrid.cpp | 6 +++++- apps/opencs/view/render/pathgrid.hpp | 2 +- apps/opencs/view/render/tagbase.cpp | 2 +- apps/opencs/view/render/tagbase.hpp | 4 +++- apps/opencs/view/render/worldspacewidget.cpp | 2 +- 9 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/opencs/view/render/cellarrow.cpp b/apps/opencs/view/render/cellarrow.cpp index 4d61551236..a654171fce 100644 --- a/apps/opencs/view/render/cellarrow.cpp +++ b/apps/opencs/view/render/cellarrow.cpp @@ -23,7 +23,7 @@ CSVRender::CellArrow *CSVRender::CellArrowTag::getCellArrow() const return mArrow; } -QString CSVRender::CellArrowTag::getToolTip (bool hideBasics) const +QString CSVRender::CellArrowTag::getToolTip(bool hideBasics, const WorldspaceHitResult& /*hit*/) const { QString text ("Direction: "); diff --git a/apps/opencs/view/render/cellarrow.hpp b/apps/opencs/view/render/cellarrow.hpp index 9a49b80db0..ed71410610 100644 --- a/apps/opencs/view/render/cellarrow.hpp +++ b/apps/opencs/view/render/cellarrow.hpp @@ -27,7 +27,7 @@ namespace CSVRender CellArrow *getCellArrow() const; - QString getToolTip (bool hideBasics) const override; + QString getToolTip(bool hideBasics, const WorldspaceHitResult& hit) const override; }; diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index 2bb537d74a..d0e4dbe04a 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -61,7 +61,7 @@ CSVRender::ObjectTag::ObjectTag (Object* object) : TagBase (Mask_Reference), mObject (object) {} -QString CSVRender::ObjectTag::getToolTip (bool hideBasics) const +QString CSVRender::ObjectTag::getToolTip(bool /*hideBasics*/, const WorldspaceHitResult& /*hit*/) const { return QString::fromUtf8 (mObject->getReferenceableId().c_str()); } diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index a19d642234..56337cf037 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -54,7 +54,7 @@ namespace CSVRender Object* mObject; - QString getToolTip (bool hideBasics) const override; + QString getToolTip (bool hideBasics, const WorldspaceHitResult& hit) const override; }; class ObjectMarkerTag : public ObjectTag diff --git a/apps/opencs/view/render/pathgrid.cpp b/apps/opencs/view/render/pathgrid.cpp index 470a3d0928..6a52c3f8ac 100644 --- a/apps/opencs/view/render/pathgrid.cpp +++ b/apps/opencs/view/render/pathgrid.cpp @@ -16,6 +16,7 @@ #include "../../model/world/commandmacro.hpp" #include "../../model/world/data.hpp" #include "../../model/world/idtree.hpp" +#include "worldspacewidget.hpp" namespace CSVRender { @@ -40,10 +41,13 @@ namespace CSVRender return mPathgrid; } - QString PathgridTag::getToolTip(bool hideBasics) const + QString PathgridTag::getToolTip(bool /*hideBasics*/, const WorldspaceHitResult& hit) const { QString text("Pathgrid: "); text += mPathgrid->getId().c_str(); + text += " ("; + text += QString::number(SceneUtil::getPathgridNode(static_cast(hit.index0))); + text += ")"; return text; } diff --git a/apps/opencs/view/render/pathgrid.hpp b/apps/opencs/view/render/pathgrid.hpp index 8f5d45a487..fa1b360e78 100644 --- a/apps/opencs/view/render/pathgrid.hpp +++ b/apps/opencs/view/render/pathgrid.hpp @@ -40,7 +40,7 @@ namespace CSVRender Pathgrid* getPathgrid () const; - QString getToolTip (bool hideBasics) const override; + QString getToolTip (bool hideBasics, const WorldspaceHitResult& hit) const override; private: diff --git a/apps/opencs/view/render/tagbase.cpp b/apps/opencs/view/render/tagbase.cpp index 3ddd68690f..61a94215dd 100644 --- a/apps/opencs/view/render/tagbase.cpp +++ b/apps/opencs/view/render/tagbase.cpp @@ -8,7 +8,7 @@ CSVRender::Mask CSVRender::TagBase::getMask() const return mMask; } -QString CSVRender::TagBase::getToolTip (bool hideBasics) const +QString CSVRender::TagBase::getToolTip (bool hideBasics, const WorldspaceHitResult& /*hit*/) const { return ""; } diff --git a/apps/opencs/view/render/tagbase.hpp b/apps/opencs/view/render/tagbase.hpp index d1ecd2cfd9..50295d508d 100644 --- a/apps/opencs/view/render/tagbase.hpp +++ b/apps/opencs/view/render/tagbase.hpp @@ -9,6 +9,8 @@ namespace CSVRender { + struct WorldspaceHitResult; + class TagBase : public osg::Referenced { Mask mMask; @@ -19,7 +21,7 @@ namespace CSVRender Mask getMask() const; - virtual QString getToolTip (bool hideBasics) const; + virtual QString getToolTip (bool hideBasics, const WorldspaceHitResult& hit) const; }; } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 723ffcb6a2..b14b7953ab 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -592,7 +592,7 @@ void CSVRender::WorldspaceWidget::showToolTip() if (hit.tag) { bool hideBasics = CSMPrefs::get()["Tooltips"]["scene-hide-basic"].isTrue(); - QToolTip::showText (pos, hit.tag->getToolTip (hideBasics), this); + QToolTip::showText(pos, hit.tag->getToolTip(hideBasics, hit), this); } } } From 2147c18cf57d40c7f0978a0f2450e71732e364db Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 28 Jun 2021 00:11:31 +0100 Subject: [PATCH 27/57] Do not overwrite old removed state with old dummy state --- components/shader/shadervisitor.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index b4455c4096..8a84dfc68b 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -402,9 +402,12 @@ namespace Shader { writableStateSet->addUniform(new osg::Uniform("alphaRef", reqs.mAlphaRef)); - const auto* alphaFunc = writableStateSet->getAttributePair(osg::StateAttribute::ALPHAFUNC); - if (alphaFunc) - removedState->setAttribute(alphaFunc->first, alphaFunc->second); + if (!removedState->getAttributePair(osg::StateAttribute::ALPHAFUNC)) + { + const auto* alphaFunc = writableStateSet->getAttributePair(osg::StateAttribute::ALPHAFUNC); + if (alphaFunc) + removedState->setAttribute(alphaFunc->first, alphaFunc->second); + } // This prevents redundant glAlphaFunc calls while letting the shadows bin still see the test writableStateSet->setAttribute(RemovedAlphaFunc::getInstance(reqs.mAlphaFunc), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); From c795e0bce636eb3605adc516022524b244f9a231 Mon Sep 17 00:00:00 2001 From: fredzio Date: Fri, 5 Feb 2021 14:55:42 +0100 Subject: [PATCH 28/57] Some actors are supposed to spawn on an object that belongs to an adjacent cell. Since actors can be active in 3x3 grid around the player, we need to first load all objects in a 5x5 grid around the player. Split load and unloading in 2 phases. Add an mInactiveCells set into the scene, which contains all cells inside the aforementioned 5x5 grid. These cells contains only heightfields and non-animated physics objects. Animated objects are tied to the scene graph, which doesn't exists yet in these cells, so we skip them. --- CHANGELOG.md | 1 + apps/openmw/mwclass/activator.cpp | 4 +- apps/openmw/mwclass/activator.hpp | 2 +- apps/openmw/mwclass/actor.cpp | 6 +- apps/openmw/mwclass/actor.hpp | 10 +- apps/openmw/mwclass/apparatus.cpp | 5 - apps/openmw/mwclass/apparatus.hpp | 2 - apps/openmw/mwclass/armor.cpp | 5 - apps/openmw/mwclass/armor.hpp | 2 - apps/openmw/mwclass/bodypart.cpp | 4 - apps/openmw/mwclass/bodypart.hpp | 2 - apps/openmw/mwclass/book.cpp | 5 - apps/openmw/mwclass/book.hpp | 2 - apps/openmw/mwclass/clothing.cpp | 5 - apps/openmw/mwclass/clothing.hpp | 2 - apps/openmw/mwclass/container.cpp | 4 +- apps/openmw/mwclass/container.hpp | 2 +- apps/openmw/mwclass/door.cpp | 4 +- apps/openmw/mwclass/door.hpp | 2 +- apps/openmw/mwclass/ingredient.cpp | 5 - apps/openmw/mwclass/ingredient.hpp | 2 - apps/openmw/mwclass/light.cpp | 4 +- apps/openmw/mwclass/light.hpp | 2 +- apps/openmw/mwclass/lockpick.cpp | 5 - apps/openmw/mwclass/lockpick.hpp | 2 - apps/openmw/mwclass/misc.cpp | 5 - apps/openmw/mwclass/misc.hpp | 2 - apps/openmw/mwclass/potion.cpp | 5 - apps/openmw/mwclass/potion.hpp | 2 - apps/openmw/mwclass/probe.cpp | 5 - apps/openmw/mwclass/probe.hpp | 2 - apps/openmw/mwclass/repair.cpp | 5 - apps/openmw/mwclass/repair.hpp | 2 - apps/openmw/mwclass/static.cpp | 4 +- apps/openmw/mwclass/static.hpp | 2 +- apps/openmw/mwclass/weapon.cpp | 5 - apps/openmw/mwclass/weapon.hpp | 2 - apps/openmw/mwphysics/actor.cpp | 6 +- apps/openmw/mwphysics/actor.hpp | 2 +- apps/openmw/mwphysics/object.cpp | 10 +- apps/openmw/mwphysics/object.hpp | 4 +- apps/openmw/mwphysics/physicssystem.cpp | 15 +- apps/openmw/mwphysics/physicssystem.hpp | 4 +- apps/openmw/mwworld/cellvisitors.hpp | 13 +- apps/openmw/mwworld/class.cpp | 6 +- apps/openmw/mwworld/class.hpp | 13 +- apps/openmw/mwworld/scene.cpp | 456 ++++++++++++++---------- apps/openmw/mwworld/scene.hpp | 15 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/resource/bulletshape.cpp | 5 + components/resource/bulletshape.hpp | 2 + 51 files changed, 345 insertions(+), 338 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23814425a8..10ef6513c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions) Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes + Bug #5379: Wandering NPCs falling through cantons Bug #5453: Magic effect VFX are offset for creatures Bug #5483: AutoCalc flag is not used to calculate spells cost Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index c54b1c3691..0b4d9ef836 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -38,10 +38,10 @@ namespace MWClass } } - void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const + void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { if(!model.empty()) - physics.addObject(ptr, model); + physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); } std::string Activator::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 10ace6f74d..7af47680b3 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -17,7 +17,7 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/actor.cpp b/apps/openmw/mwclass/actor.cpp index 33aeb26bb0..6621df1ec8 100644 --- a/apps/openmw/mwclass/actor.cpp +++ b/apps/openmw/mwclass/actor.cpp @@ -17,16 +17,12 @@ namespace MWClass { - Actor::Actor() {} - - Actor::~Actor() {} - void Actor::adjustPosition(const MWWorld::Ptr& ptr, bool force) const { MWBase::Environment::get().getWorld()->adjustPosition(ptr, force); } - void Actor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const + void Actor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { if (!model.empty()) { diff --git a/apps/openmw/mwclass/actor.hpp b/apps/openmw/mwclass/actor.hpp index 3d509b2768..cc1d0c9089 100644 --- a/apps/openmw/mwclass/actor.hpp +++ b/apps/openmw/mwclass/actor.hpp @@ -15,16 +15,16 @@ namespace MWClass { protected: - Actor(); + Actor() = default; public: - virtual ~Actor(); + ~Actor() override = default; void adjustPosition(const MWWorld::Ptr& ptr, bool force) const override; ///< Adjust position to stand on ground. Must be called post model load /// @param force do this even if the ptr is flying - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; bool useAnim() const override; @@ -46,8 +46,8 @@ namespace MWClass float getCurrentSpeed(const MWWorld::Ptr& ptr) const override; // not implemented - Actor(const Actor&); - Actor& operator= (const Actor&); + Actor(const Actor&) = delete; + Actor& operator= (const Actor&) = delete; }; } diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 518695fabf..e09e4804ce 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -26,11 +26,6 @@ namespace MWClass } } - void Apparatus::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Apparatus::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 8087c57ba3..828abef25e 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -17,8 +17,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 3f9bfb859f..817adbc1f5 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -34,11 +34,6 @@ namespace MWClass } } - void Armor::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Armor::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 4f04e0824b..f64f138a29 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -16,8 +16,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/bodypart.cpp b/apps/openmw/mwclass/bodypart.cpp index 0315d3ddb0..7fe798e27d 100644 --- a/apps/openmw/mwclass/bodypart.cpp +++ b/apps/openmw/mwclass/bodypart.cpp @@ -22,10 +22,6 @@ namespace MWClass } } - void BodyPart::insertObject(const MWWorld::Ptr &ptr, const std::string &model, MWPhysics::PhysicsSystem &physics) const - { - } - std::string BodyPart::getName(const MWWorld::ConstPtr &ptr) const { return std::string(); diff --git a/apps/openmw/mwclass/bodypart.hpp b/apps/openmw/mwclass/bodypart.hpp index 13d9141386..0e372b884a 100644 --- a/apps/openmw/mwclass/bodypart.hpp +++ b/apps/openmw/mwclass/bodypart.hpp @@ -15,8 +15,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 4ea71e3ac2..51b9e39d7a 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -31,11 +31,6 @@ namespace MWClass } } - void Book::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Book::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index c58e68ad87..f3d34c5168 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -14,8 +14,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 6d7960aac2..400cd97e41 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -29,11 +29,6 @@ namespace MWClass } } - void Clothing::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Clothing::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index a87e0cbe00..3d5c162aa4 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -14,8 +14,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index de560608c0..b88d756cbc 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -106,10 +106,10 @@ namespace MWClass } } - void Container::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const + void Container::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { if(!model.empty()) - physics.addObject(ptr, model); + physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); } std::string Container::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 1c89370068..02ec9b1012 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -42,7 +42,7 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 3a5ff0d9ae..ca0d647f9c 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -55,10 +55,10 @@ namespace MWClass } } - void Door::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const + void Door::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { if(!model.empty()) - physics.addObject(ptr, model, MWPhysics::CollisionType_Door); + physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_Door, skipAnimated); // Resume the door's opening/closing animation if it wasn't finished if (ptr.getRefData().getCustomData()) diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index 6c2fa26b80..f80c9bb416 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -18,7 +18,7 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; bool isDoor() const override; diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index a007ad115f..20f9576dff 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -28,11 +28,6 @@ namespace MWClass } } - void Ingredient::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Ingredient::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 5219cf39ce..2aa831f868 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -14,8 +14,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 3bdf10f475..ca744be7bc 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -33,7 +33,7 @@ namespace MWClass renderingInterface.getObjects().insertModel(ptr, model, true, !(ref->mBase->mData.mFlags & ESM::Light::OffDefault)); } - void Light::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const + void Light::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { MWWorld::LiveCellRef *ref = ptr.get(); @@ -41,7 +41,7 @@ namespace MWClass // TODO: add option somewhere to enable collision for placeable objects if (!model.empty() && (ref->mBase->mData.mFlags & ESM::Light::Carry) == 0) - physics.addObject(ptr, model); + physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); if (!ref->mBase->mSound.empty() && !(ref->mBase->mData.mFlags & ESM::Light::OffDefault)) MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0, diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index e37dddc250..7641722788 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -14,7 +14,7 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; bool useAnim() const override; diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 9b8abc8f23..985b087711 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -28,11 +28,6 @@ namespace MWClass } } - void Lockpick::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Lockpick::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index fabae33435..d4b265e397 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -14,8 +14,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 8d3cda6fe5..facab9d51c 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -37,11 +37,6 @@ namespace MWClass } } - void Miscellaneous::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Miscellaneous::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 9bff85ca56..18788c7ed8 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -14,8 +14,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 4af97e6345..56d9dff279 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -30,11 +30,6 @@ namespace MWClass } } - void Potion::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Potion::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 75d923f0ba..75b962164b 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -14,8 +14,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index dba4e8c063..51273337a6 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -28,11 +28,6 @@ namespace MWClass } } - void Probe::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Probe::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index a0a41dcfb6..ef9273a379 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -14,8 +14,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 8907c8212e..f1b88e422b 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -25,11 +25,6 @@ namespace MWClass } } - void Repair::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Repair::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index b9791e9cf4..c403449e18 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -14,8 +14,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 5551b3d731..323e482bf0 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -23,10 +23,10 @@ namespace MWClass } } - void Static::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const + void Static::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { if(!model.empty()) - physics.addObject(ptr, model); + physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); } std::string Static::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index 6bc783dad0..211b93de2a 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -14,7 +14,7 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; + void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 0d6a27cf60..6246c8fb09 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -34,11 +34,6 @@ namespace MWClass } } - void Weapon::insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const - { - // TODO: add option somewhere to enable collision for placeable objects - } - std::string Weapon::getModel(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index f1824b7d14..db17e6b70f 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -15,8 +15,6 @@ namespace MWClass void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering - void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const override; - std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index f0bc234138..21736543ab 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -68,7 +68,7 @@ Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, Physic updateScale(); if(!mRotationallyInvariant) - updateRotation(); + setRotation(mPtr.getRefData().getBaseNode()->getAttitude()); updatePosition(); addCollisionMask(getCollisionMask()); @@ -197,10 +197,10 @@ osg::Vec3f Actor::getPreviousPosition() const return mPreviousPosition; } -void Actor::updateRotation () +void Actor::setRotation(osg::Quat quat) { std::scoped_lock lock(mPositionMutex); - mRotation = mPtr.getRefData().getBaseNode()->getAttitude(); + mRotation = quat; } bool Actor::isRotationallyInvariant() const diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index 7b53e8812a..dd4ea45714 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -48,7 +48,7 @@ namespace MWPhysics void enableCollisionBody(bool collision); void updateScale(); - void updateRotation(); + void setRotation(osg::Quat quat); /** * Return true if the collision shape looks the same no matter how its Z rotated. diff --git a/apps/openmw/mwphysics/object.cpp b/apps/openmw/mwphysics/object.cpp index 6363065323..2a94d28f12 100644 --- a/apps/openmw/mwphysics/object.cpp +++ b/apps/openmw/mwphysics/object.cpp @@ -14,7 +14,7 @@ namespace MWPhysics { - Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance, int collisionType, PhysicsTaskScheduler* scheduler) + Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance, osg::Quat rotation, int collisionType, PhysicsTaskScheduler* scheduler) : mShapeInstance(shapeInstance) , mSolid(true) , mTaskScheduler(scheduler) @@ -27,7 +27,7 @@ namespace MWPhysics mCollisionObject->setUserPointer(this); setScale(ptr.getCellRef().getScale()); - setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude())); + setRotation(rotation); setOrigin(Misc::Convert::toBullet(ptr.getRefData().getPosition().asVec3())); commitPositionChange(); @@ -51,10 +51,10 @@ namespace MWPhysics mScaleUpdatePending = true; } - void Object::setRotation(const btQuaternion& quat) + void Object::setRotation(osg::Quat quat) { std::unique_lock lock(mPositionMutex); - mLocalTransform.setRotation(quat); + mLocalTransform.setRotation(Misc::Convert::toBullet(quat)); mTransformUpdatePending = true; } @@ -108,7 +108,7 @@ namespace MWPhysics bool Object::isAnimated() const { - return !mShapeInstance->mAnimatedShapes.empty(); + return mShapeInstance->isAnimated(); } bool Object::animateCollisionShapes() diff --git a/apps/openmw/mwphysics/object.hpp b/apps/openmw/mwphysics/object.hpp index cae8771809..c2273831e5 100644 --- a/apps/openmw/mwphysics/object.hpp +++ b/apps/openmw/mwphysics/object.hpp @@ -26,12 +26,12 @@ namespace MWPhysics class Object final : public PtrHolder { public: - Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance, int collisionType, PhysicsTaskScheduler* scheduler); + Object(const MWWorld::Ptr& ptr, osg::ref_ptr shapeInstance, osg::Quat rotation, int collisionType, PhysicsTaskScheduler* scheduler); ~Object() override; const Resource::BulletShapeInstance* getShapeInstance() const; void setScale(float scale); - void setRotation(const btQuaternion& quat); + void setRotation(osg::Quat quat); void setOrigin(const btVector3& vec); void commitPositionChange(); btCollisionObject* getCollisionObject(); diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 833bb9a161..460347795a 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -461,13 +461,18 @@ namespace MWPhysics return heightField->second.get(); } - void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, int collisionType) + void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, osg::Quat rotation, int collisionType, bool skipAnimated) { osg::ref_ptr shapeInstance = mShapeManager->getInstance(mesh); if (!shapeInstance || !shapeInstance->getCollisionShape()) return; - auto obj = std::make_shared(ptr, shapeInstance, collisionType, mTaskScheduler.get()); + if (skipAnimated && shapeInstance->isAnimated()) + return; + + assert(!getObject(ptr)); + + auto obj = std::make_shared(ptr, shapeInstance, rotation, collisionType, mTaskScheduler.get()); mObjects.emplace(ptr, obj); if (obj->isAnimated()) @@ -625,12 +630,12 @@ namespace MWPhysics mTaskScheduler->updateSingleAabb(foundProjectile->second); } - void PhysicsSystem::updateRotation(const MWWorld::Ptr &ptr) + void PhysicsSystem::updateRotation(const MWWorld::Ptr &ptr, osg::Quat rotate) { ObjectMap::iterator found = mObjects.find(ptr); if (found != mObjects.end()) { - found->second->setRotation(Misc::Convert::toBullet(ptr.getRefData().getBaseNode()->getAttitude())); + found->second->setRotation(rotate); mTaskScheduler->updateSingleAabb(found->second); return; } @@ -639,7 +644,7 @@ namespace MWPhysics { if (!foundActor->second->isRotationallyInvariant()) { - foundActor->second->updateRotation(); + foundActor->second->setRotation(rotate); mTaskScheduler->updateSingleAabb(foundActor->second); } return; diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 3d2a3c580d..b3a2266e65 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -122,7 +122,7 @@ namespace MWPhysics void setWaterHeight(float height); void disableWater(); - void addObject (const MWWorld::Ptr& ptr, const std::string& mesh, int collisionType = CollisionType_World); + void addObject (const MWWorld::Ptr& ptr, const std::string& mesh, osg::Quat rotation, int collisionType = CollisionType_World, bool skipAnimated = false); void addActor (const MWWorld::Ptr& ptr, const std::string& mesh); int addProjectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius, bool canTraverseWater); @@ -143,7 +143,7 @@ namespace MWPhysics void remove (const MWWorld::Ptr& ptr); void updateScale (const MWWorld::Ptr& ptr); - void updateRotation (const MWWorld::Ptr& ptr); + void updateRotation (const MWWorld::Ptr& ptr, osg::Quat rotate); void updatePosition (const MWWorld::Ptr& ptr); void addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject); diff --git a/apps/openmw/mwworld/cellvisitors.hpp b/apps/openmw/mwworld/cellvisitors.hpp index e68b383b77..5985d06fb6 100644 --- a/apps/openmw/mwworld/cellvisitors.hpp +++ b/apps/openmw/mwworld/cellvisitors.hpp @@ -18,12 +18,23 @@ namespace MWWorld if (ptr.getRefData().getBaseNode()) { ptr.getRefData().setBaseNode(nullptr); - mObjects.push_back (ptr); } + mObjects.push_back (ptr); return true; } }; + + struct ListObjectsVisitor + { + std::vector mObjects; + + bool operator() (MWWorld::Ptr ptr) + { + mObjects.push_back (ptr); + return true; + } + }; } #endif diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 950c8a6d49..04dfba6b97 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -25,16 +25,12 @@ namespace MWWorld { std::map > Class::sClasses; - Class::Class() {} - - Class::~Class() {} - void Class::insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const { } - void Class::insertObject(const Ptr& ptr, const std::string& mesh, MWPhysics::PhysicsSystem& physics) const + void Class::insertObject(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 1b3d4029e4..e225e0187c 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "ptr.hpp" @@ -57,13 +58,9 @@ namespace MWWorld std::string mTypeName; - // not implemented - Class (const Class&); - Class& operator= (const Class&); - protected: - Class(); + Class() = default; std::shared_ptr defaultItemActivate(const Ptr &ptr, const Ptr &actor) const; ///< Generate default action for activating inventory items @@ -72,14 +69,16 @@ namespace MWWorld public: - virtual ~Class(); + virtual ~Class() = default; + Class (const Class&) = delete; + Class& operator= (const Class&) = delete; const std::string& getTypeName() const { return mTypeName; } virtual void insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const; - virtual void insertObject(const Ptr& ptr, const std::string& mesh, MWPhysics::PhysicsSystem& physics) const; + virtual void insertObject(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const; ///< Add reference into a cell for rendering (default implementation: don't render anything). virtual std::string getName (const ConstPtr& ptr) const = 0; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 85b312dd57..45b0c5d9f8 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -73,18 +73,20 @@ namespace * osg::Quat(xr, osg::Vec3(-1, 0, 0)); } - void setNodeRotation(const MWWorld::Ptr& ptr, MWRender::RenderingManager& rendering, RotationOrder order) + osg::Quat makeNodeRotation(const MWWorld::Ptr& ptr, RotationOrder order) { - if (!ptr.getRefData().getBaseNode()) - return; + const auto pos = ptr.getRefData().getPosition(); - rendering.rotateObject(ptr, - ptr.getClass().isActor() - ? makeActorOsgQuat(ptr.getRefData().getPosition()) - : (order == RotationOrder::inverse - ? makeInversedOrderObjectOsgQuat(ptr.getRefData().getPosition()) - : makeObjectOsgQuat(ptr.getRefData().getPosition())) - ); + const auto rot = ptr.getClass().isActor() ? makeActorOsgQuat(pos) + : (order == RotationOrder::inverse ? makeInversedOrderObjectOsgQuat(pos) : makeObjectOsgQuat(pos)); + + return rot; + } + + void setNodeRotation(const MWWorld::Ptr& ptr, MWRender::RenderingManager& rendering, osg::Quat rotation) + { + if (ptr.getRefData().getBaseNode()) + rendering.rotateObject(ptr, rotation); } std::string getModel(const MWWorld::Ptr &ptr, const VFS::Manager *vfs) @@ -101,7 +103,7 @@ namespace } void addObject(const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, - MWRender::RenderingManager& rendering, std::set& pagedRefs) + MWRender::RenderingManager& rendering, std::set& pagedRefs, bool onlyPhysics) { if (ptr.getRefData().getBaseNode() || physics.getActor(ptr)) { @@ -109,19 +111,23 @@ namespace return; } - bool useAnim = ptr.getClass().useAnim(); std::string model = getModel(ptr, rendering.getResourceSystem()->getVFS()); + const auto rotation = makeNodeRotation(ptr, RotationOrder::direct); + if (onlyPhysics && !physics.getObject(ptr) && !ptr.getClass().isActor()) + { + // When we preload physics object we need to skip animated objects. They are dependant on the scene graph which doesn't yet exist. + ptr.getClass().insertObject (ptr, model, rotation, physics, true); + return; + } const ESM::RefNum& refnum = ptr.getCellRef().getRefNum(); if (!refnum.hasContentFile() || pagedRefs.find(refnum) == pagedRefs.end()) ptr.getClass().insertObjectRendering(ptr, model, rendering); else ptr.getRefData().setBaseNode(new SceneUtil::PositionAttitudeTransform); // FIXME remove this when physics code is fixed not to depend on basenode - setNodeRotation(ptr, rendering, RotationOrder::direct); + setNodeRotation(ptr, rendering, rotation); - ptr.getClass().insertObject (ptr, model, physics); - - if (useAnim) + if (ptr.getClass().useAnim()) MWBase::Environment::get().getMechanicsManager()->add(ptr); if (ptr.getClass().isActor()) @@ -129,6 +135,9 @@ namespace // Restore effect particles MWBase::Environment::get().getWorld()->applyLoopingParticles(ptr); + + if (!physics.getObject(ptr)) + ptr.getClass().insertObject (ptr, model, rotation, physics); } void addObject(const MWWorld::Ptr& ptr, const MWPhysics::PhysicsSystem& physics, DetourNavigator::Navigator& navigator) @@ -199,11 +208,12 @@ namespace { MWWorld::CellStore& mCell; Loading::Listener& mLoadingListener; + bool mOnlyObjects; bool mTest; std::vector mToInsert; - InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool test); + InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool onlyObjects, bool test); bool operator() (const MWWorld::Ptr& ptr); @@ -211,8 +221,8 @@ namespace void insert(AddObject&& addObject); }; - InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool test) - : mCell (cell), mLoadingListener (loadingListener), mTest(test) + InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, Loading::Listener& loadingListener, bool onlyObjects, bool test) + : mCell (cell), mLoadingListener (loadingListener), mOnlyObjects(onlyObjects), mTest(test) {} bool InsertVisitor::operator() (const MWWorld::Ptr& ptr) @@ -228,7 +238,7 @@ namespace { for (MWWorld::Ptr& ptr : mToInsert) { - if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled()) + if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled() && (!mOnlyObjects || !ptr.getClass().isActor())) { try { @@ -261,6 +271,16 @@ namespace return std::abs(cellPosition.first) + std::abs(cellPosition.second); } + bool isCellInCollection(int x, int y, MWWorld::Scene::CellStoreCollection& collection) + { + for (auto *cell : collection) + { + assert(cell->getCell()->isExterior()); + if (x == cell->getCell()->getGridX() && y == cell->getCell()->getGridY()) + return true; + } + return false; + } } @@ -274,7 +294,7 @@ namespace MWWorld { if (!ptr.getRefData().getBaseNode()) return; ptr.getClass().insertObjectRendering(ptr, getModel(ptr, mRendering.getResourceSystem()->getVFS()), mRendering); - setNodeRotation(ptr, mRendering, RotationOrder::direct); + setNodeRotation(ptr, mRendering, makeNodeRotation(ptr, RotationOrder::direct)); reloadTerrain(); } } @@ -290,8 +310,9 @@ namespace MWWorld void Scene::updateObjectRotation(const Ptr &ptr, RotationOrder order) { - setNodeRotation(ptr, mRendering, order); - mPhysics->updateRotation(ptr); + const auto rot = makeNodeRotation(ptr, order); + setNodeRotation(ptr, mRendering, rot); + mPhysics->updateRotation(ptr, rot); } void Scene::updateObjectScale(const Ptr &ptr) @@ -311,165 +332,213 @@ namespace MWWorld mRendering.update (duration, paused); } - void Scene::unloadCell (CellStoreCollection::iterator iter, bool test) + void Scene::unloadInactiveCell (CellStore* cell, bool test) { + assert(mActiveCells.find(cell) == mActiveCells.end()); + assert(mInactiveCells.find(cell) != mInactiveCells.end()); if (!test) - Log(Debug::Info) << "Unloading cell " << (*iter)->getCell()->getDescription(); + Log(Debug::Info) << "Unloading cell " << cell->getCell()->getDescription(); + + ListObjectsVisitor visitor; + + cell->forEach(visitor); + for (const auto& ptr : visitor.mObjects) + mPhysics->remove(ptr); + + if (cell->getCell()->isExterior()) + { + const auto cellX = cell->getCell()->getGridX(); + const auto cellY = cell->getCell()->getGridY(); + mPhysics->removeHeightField(cellX, cellY); + } + + mInactiveCells.erase(cell); + } + + void Scene::deactivateCell(CellStore* cell, bool test) + { + assert(mInactiveCells.find(cell) != mInactiveCells.end()); + if (mActiveCells.find(cell) == mActiveCells.end()) + return; + if (!test) + Log(Debug::Info) << "Deactivate cell " << cell->getCell()->getDescription(); const auto navigator = MWBase::Environment::get().getWorld()->getNavigator(); ListAndResetObjectsVisitor visitor; - (*iter)->forEach(visitor); + cell->forEach(visitor); const auto world = MWBase::Environment::get().getWorld(); for (const auto& ptr : visitor.mObjects) { if (const auto object = mPhysics->getObject(ptr)) + { navigator->removeObject(DetourNavigator::ObjectId(object)); + if (object->isAnimated()) + mPhysics->remove(ptr); + } else if (mPhysics->getActor(ptr)) { navigator->removeAgent(world->getPathfindingHalfExtents(ptr)); mRendering.removeActorPath(ptr); + mPhysics->remove(ptr); } - mPhysics->remove(ptr); } - const auto cellX = (*iter)->getCell()->getGridX(); - const auto cellY = (*iter)->getCell()->getGridY(); + const auto cellX = cell->getCell()->getGridX(); + const auto cellY = cell->getCell()->getGridY(); - if ((*iter)->getCell()->isExterior()) + if (cell->getCell()->isExterior()) { if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) navigator->removeObject(DetourNavigator::ObjectId(heightField)); - mPhysics->removeHeightField(cellX, cellY); } - if ((*iter)->getCell()->hasWater()) + if (cell->getCell()->hasWater()) navigator->removeWater(osg::Vec2i(cellX, cellY)); - if (const auto pathgrid = world->getStore().get().search(*(*iter)->getCell())) + if (const auto pathgrid = world->getStore().get().search(*cell->getCell())) navigator->removePathgrid(*pathgrid); const auto player = world->getPlayerPtr(); navigator->update(player.getRefData().getPosition().asVec3()); - MWBase::Environment::get().getMechanicsManager()->drop (*iter); + MWBase::Environment::get().getMechanicsManager()->drop (cell); - mRendering.removeCell(*iter); - MWBase::Environment::get().getWindowManager()->removeCell(*iter); + mRendering.removeCell(cell); + MWBase::Environment::get().getWindowManager()->removeCell(cell); - MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter); + MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (cell); - MWBase::Environment::get().getSoundManager()->stopSound (*iter); - mActiveCells.erase(*iter); + MWBase::Environment::get().getSoundManager()->stopSound (cell); + mActiveCells.erase(cell); } - void Scene::loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test) + void Scene::activateCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test) { - std::pair result = mActiveCells.insert(cell); + assert(mActiveCells.find(cell) == mActiveCells.end()); + assert(mInactiveCells.find(cell) != mInactiveCells.end()); + mActiveCells.insert(cell); - if(result.second) + if (test) + Log(Debug::Info) << "Testing cell " << cell->getCell()->getDescription(); + else + Log(Debug::Info) << "Loading cell " << cell->getCell()->getDescription(); + + const auto world = MWBase::Environment::get().getWorld(); + const auto navigator = world->getNavigator(); + + const int cellX = cell->getCell()->getGridX(); + const int cellY = cell->getCell()->getGridY(); + + if (!test && cell->getCell()->isExterior()) { - if (test) - Log(Debug::Info) << "Testing cell " << cell->getCell()->getDescription(); - else - Log(Debug::Info) << "Loading cell " << cell->getCell()->getDescription(); + if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) + navigator->addObject(DetourNavigator::ObjectId(heightField), *heightField->getShape(), + heightField->getCollisionObject()->getWorldTransform()); + } - float verts = ESM::Land::LAND_SIZE; - float worldsize = ESM::Land::REAL_SIZE; + if (const auto pathgrid = world->getStore().get().search(*cell->getCell())) + navigator->addPathgrid(*cell->getCell(), *pathgrid); - const auto world = MWBase::Environment::get().getWorld(); - const auto navigator = world->getNavigator(); + // register local scripts + // do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice + MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell); - const int cellX = cell->getCell()->getGridX(); - const int cellY = cell->getCell()->getGridY(); + if (respawn) + cell->respawn(); - // Load terrain physics first... - if (!test && cell->getCell()->isExterior()) + insertCell (*cell, loadingListener, false, test); + + mRendering.addCell(cell); + if (!test) + { + MWBase::Environment::get().getWindowManager()->addCell(cell); + bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior(); + float waterLevel = cell->getWaterLevel(); + mRendering.setWaterEnabled(waterEnabled); + if (waterEnabled) { - osg::ref_ptr land = mRendering.getLandManager()->getLand(cellX, cellY); - const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr; - if (data) + mPhysics->enableWater(waterLevel); + mRendering.setWaterHeight(waterLevel); + + if (cell->getCell()->isExterior()) { - mPhysics->addHeightField (data->mHeights, cellX, cellY, worldsize / (verts-1), verts, data->mMinHeight, data->mMaxHeight, land.get()); - } - else - { - static std::vector defaultHeight; - defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT); - mPhysics->addHeightField (&defaultHeight[0], cell->getCell()->getGridX(), cell->getCell()->getGridY(), worldsize / (verts-1), verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get()); - } - - if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) - navigator->addObject(DetourNavigator::ObjectId(heightField), *heightField->getShape(), - heightField->getCollisionObject()->getWorldTransform()); - } - - if (const auto pathgrid = world->getStore().get().search(*cell->getCell())) - navigator->addPathgrid(*cell->getCell(), *pathgrid); - - // register local scripts - // do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice - MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell); - - if (respawn) - cell->respawn(); - - // ... then references. This is important for adjustPosition to work correctly. - insertCell (*cell, loadingListener, test); - - mRendering.addCell(cell); - if (!test) - { - MWBase::Environment::get().getWindowManager()->addCell(cell); - bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior(); - float waterLevel = cell->getWaterLevel(); - mRendering.setWaterEnabled(waterEnabled); - if (waterEnabled) - { - mPhysics->enableWater(waterLevel); - mRendering.setWaterHeight(waterLevel); - - if (cell->getCell()->isExterior()) - { - if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) - navigator->addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE, + if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) + navigator->addWater(osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE, cell->getWaterLevel(), heightField->getCollisionObject()->getWorldTransform()); - } - else - { - navigator->addWater(osg::Vec2i(cellX, cellY), std::numeric_limits::max(), - cell->getWaterLevel(), btTransform::getIdentity()); - } } else - mPhysics->disableWater(); - - const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - - // By default the player is grounded, with the scene fully loaded, we validate and correct this. - if (player.mCell == cell) // Only run once, during initial cell load. { - mPhysics->traceDown(player, player.getRefData().getPosition().asVec3(), 10.f); - } - - navigator->update(player.getRefData().getPosition().asVec3()); - - if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx)) - { - mRendering.configureAmbient(cell->getCell()); + navigator->addWater(osg::Vec2i(cellX, cellY), std::numeric_limits::max(), + cell->getWaterLevel(), btTransform::getIdentity()); } } + else + mPhysics->disableWater(); + + const auto player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + + // By default the player is grounded, with the scene fully loaded, we validate and correct this. + if (player.mCell == cell) // Only run once, during initial cell load. + { + mPhysics->traceDown(player, player.getRefData().getPosition().asVec3(), 10.f); + } + + navigator->update(player.getRefData().getPosition().asVec3()); + + if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx)) + mRendering.configureAmbient(cell->getCell()); } mPreloader->notifyLoaded(cell); } + void Scene::loadInactiveCell (CellStore *cell, Loading::Listener* loadingListener, bool test) + { + assert(mActiveCells.find(cell) == mActiveCells.end()); + assert(mInactiveCells.find(cell) == mInactiveCells.end()); + mInactiveCells.insert(cell); + + if (test) + Log(Debug::Info) << "Testing inactive cell " << cell->getCell()->getDescription(); + else + Log(Debug::Info) << "Loading inactive cell " << cell->getCell()->getDescription(); + + if (!test && cell->getCell()->isExterior()) + { + float verts = ESM::Land::LAND_SIZE; + float worldsize = ESM::Land::REAL_SIZE; + + const int cellX = cell->getCell()->getGridX(); + const int cellY = cell->getCell()->getGridY(); + + osg::ref_ptr land = mRendering.getLandManager()->getLand(cellX, cellY); + const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr; + if (data) + { + mPhysics->addHeightField (data->mHeights, cellX, cellY, worldsize / (verts-1), verts, data->mMinHeight, data->mMaxHeight, land.get()); + } + else + { + static std::vector defaultHeight; + defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT); + mPhysics->addHeightField (&defaultHeight[0], cellX, cellY, worldsize / (verts-1), verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get()); + } + } + + insertCell (*cell, loadingListener, true, test); + } + void Scene::clear() { - CellStoreCollection::iterator active = mActiveCells.begin(); - while (active!=mActiveCells.end()) - unloadCell (active++); + for (auto iter = mInactiveCells.begin(); iter!=mInactiveCells.end(); ) + { + auto* cell = *iter++; + deactivateCell(cell); + unloadInactiveCell (cell); + } assert(mActiveCells.empty()); + assert(mInactiveCells.empty()); mCurrentCell = nullptr; mPreloader->clear(); @@ -512,20 +581,24 @@ namespace MWWorld void Scene::changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent) { - CellStoreCollection::iterator active = mActiveCells.begin(); - while (active!=mActiveCells.end()) + for (auto iter = mInactiveCells.begin(); iter != mInactiveCells.end(); ) { - if ((*active)->getCell()->isExterior()) + auto* cell = *iter++; + if (cell->getCell()->isExterior()) { - if (std::abs (playerCellX-(*active)->getCell()->getGridX())<=mHalfGridSize && - std::abs (playerCellY-(*active)->getCell()->getGridY())<=mHalfGridSize) - { - // keep cells within the new grid - ++active; - continue; - } + const auto dx = std::abs(playerCellX - cell->getCell()->getGridX()); + const auto dy = std::abs(playerCellY - cell->getCell()->getGridY()); + if (dx > mHalfGridSize || dy > mHalfGridSize) + deactivateCell(cell); + + if (dx > mHalfGridSize+1 || dy > mHalfGridSize+1) + unloadInactiveCell(cell); + } + else + { + deactivateCell(cell); + unloadInactiveCell(cell); } - unloadCell (active++); } mCurrentGridCenter = osg::Vec2i(playerCellX, playerCellY); @@ -537,32 +610,24 @@ namespace MWWorld mRendering.getPagedRefnums(newGrid, mPagedRefs); std::size_t refsToLoad = 0; - std::vector> cellsPositionsToLoad; - // get the number of refs to load - for (int x = playerCellX - mHalfGridSize; x <= playerCellX + mHalfGridSize; ++x) + const auto cellsToLoad = [&playerCellX,&playerCellY,&refsToLoad](CellStoreCollection& collection, int range) -> std::vector> { - for (int y = playerCellY - mHalfGridSize; y <= playerCellY + mHalfGridSize; ++y) + std::vector> cellsPositionsToLoad; + for (int x = playerCellX - range; x <= playerCellX + range; ++x) { - CellStoreCollection::iterator iter = mActiveCells.begin(); - - while (iter!=mActiveCells.end()) + for (int y = playerCellY - range; y <= playerCellY + range; ++y) { - assert ((*iter)->getCell()->isExterior()); - - if (x==(*iter)->getCell()->getGridX() && - y==(*iter)->getCell()->getGridY()) - break; - - ++iter; - } - - if (iter==mActiveCells.end()) - { - refsToLoad += MWBase::Environment::get().getWorld()->getExterior(x, y)->count(); - cellsPositionsToLoad.emplace_back(x, y); + if (!isCellInCollection(x, y, collection)) + { + refsToLoad += MWBase::Environment::get().getWorld()->getExterior(x, y)->count(); + cellsPositionsToLoad.emplace_back(x, y); + } } } - } + return cellsPositionsToLoad; + }; + auto cellsPositionsToLoad = cellsToLoad(mActiveCells,mHalfGridSize); + auto cellsPositionsToLoadInactive = cellsToLoad(mInactiveCells,mHalfGridSize+1); Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); Loading::ScopedLoad load(loadingListener); @@ -585,30 +650,26 @@ namespace MWWorld return getCellPositionPriority(lhs) < getCellPositionPriority(rhs); }); + std::sort(cellsPositionsToLoadInactive.begin(), cellsPositionsToLoadInactive.end(), + [&] (const std::pair& lhs, const std::pair& rhs) { + return getCellPositionPriority(lhs) < getCellPositionPriority(rhs); + }); + // Load cells - for (const auto& cellPosition : cellsPositionsToLoad) + for (const auto& [x,y] : cellsPositionsToLoadInactive) { - const auto x = cellPosition.first; - const auto y = cellPosition.second; - - CellStoreCollection::iterator iter = mActiveCells.begin(); - - while (iter != mActiveCells.end()) - { - assert ((*iter)->getCell()->isExterior()); - - if (x == (*iter)->getCell()->getGridX() && - y == (*iter)->getCell()->getGridY()) - break; - - ++iter; - } - - if (iter == mActiveCells.end()) + if (!isCellInCollection(x, y, mInactiveCells)) { CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y); - - loadCell (cell, loadingListener, changeEvent); + loadInactiveCell (cell, loadingListener); + } + } + for (const auto& [x,y] : cellsPositionsToLoad) + { + if (!isCellInCollection(x, y, mActiveCells)) + { + CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(x, y); + activateCell (cell, loadingListener, changeEvent); } } @@ -643,7 +704,8 @@ namespace MWWorld CellStoreCollection::iterator iter = mActiveCells.begin(); CellStore *cell = MWBase::Environment::get().getWorld()->getExterior(it->mData.mX, it->mData.mY); - loadCell (cell, loadingListener, false, true); + loadInactiveCell (cell, loadingListener, true); + activateCell (cell, loadingListener, false, true); iter = mActiveCells.begin(); while (iter != mActiveCells.end()) @@ -651,7 +713,8 @@ namespace MWWorld if (it->isExterior() && it->mData.mX == (*iter)->getCell()->getGridX() && it->mData.mY == (*iter)->getCell()->getGridY()) { - unloadCell(iter, true); + deactivateCell(*iter, true); + unloadInactiveCell (*iter, true); break; } @@ -689,7 +752,8 @@ namespace MWWorld loadingListener->setLabel("Testing interior cells ("+std::to_string(i)+"/"+std::to_string(cells.getIntSize())+")..."); CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(it->mName); - loadCell (cell, loadingListener, false, true); + loadInactiveCell (cell, loadingListener, true); + activateCell (cell, loadingListener, false, true); CellStoreCollection::iterator iter = mActiveCells.begin(); while (iter != mActiveCells.end()) @@ -698,7 +762,8 @@ namespace MWWorld if (it->mName == (*iter)->getCell()->mName) { - unloadCell(iter, true); + deactivateCell(*iter, true); + unloadInactiveCell (*iter, true); break; } @@ -820,15 +885,21 @@ namespace MWWorld Log(Debug::Info) << "Changing to interior"; // unload - CellStoreCollection::iterator active = mActiveCells.begin(); - while (active!=mActiveCells.end()) - unloadCell (active++); + for (auto iter = mInactiveCells.begin(); iter!=mInactiveCells.end(); ) + { + auto* cell = *iter++; + deactivateCell(cell); + unloadInactiveCell(cell); + } + assert(mActiveCells.empty()); + assert(mInactiveCells.empty()); loadingListener->setProgressRange(cell->count()); // Load cell. mPagedRefs.clear(); - loadCell (cell, loadingListener, changeEvent); + loadInactiveCell (cell, loadingListener); + activateCell (cell, loadingListener, changeEvent); changePlayerCell(cell, position, adjustPlayerPos); @@ -878,23 +949,26 @@ namespace MWWorld mCellChanged = false; } - void Scene::insertCell (CellStore &cell, Loading::Listener* loadingListener, bool test) + void Scene::insertCell (CellStore &cell, Loading::Listener* loadingListener, bool onlyObjects, bool test) { - InsertVisitor insertVisitor (cell, *loadingListener, test); + InsertVisitor insertVisitor (cell, *loadingListener, onlyObjects, test); cell.forEach (insertVisitor); - insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mRendering, mPagedRefs); }); - insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mNavigator); }); + insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mRendering, mPagedRefs, onlyObjects); }); + if (!onlyObjects) + { + insertVisitor.insert([&] (const MWWorld::Ptr& ptr) { addObject(ptr, *mPhysics, mNavigator); }); - // do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order - PositionVisitor posVisitor; - cell.forEach (posVisitor); + // do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order + PositionVisitor posVisitor; + cell.forEach (posVisitor); + } } void Scene::addObjectToScene (const Ptr& ptr) { try { - addObject(ptr, *mPhysics, mRendering, mPagedRefs); + addObject(ptr, *mPhysics, mRendering, mPagedRefs, false); addObject(ptr, *mPhysics, mNavigator); MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale()); const auto navigator = MWBase::Environment::get().getWorld()->getNavigator(); diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index f87a0ca733..bc9c2386bb 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -64,13 +64,13 @@ namespace MWWorld class Scene { public: - - typedef std::set CellStoreCollection; + using CellStoreCollection = std::set; private: CellStore* mCurrentCell; // the cell the player is in CellStoreCollection mActiveCells; + CellStoreCollection mInactiveCells; bool mCellChanged; MWPhysics::PhysicsSystem *mPhysics; MWRender::RenderingManager& mRendering; @@ -91,7 +91,7 @@ namespace MWWorld std::set mPagedRefs; - void insertCell (CellStore &cell, Loading::Listener* loadingListener, bool test = false); + void insertCell (CellStore &cell, Loading::Listener* loadingListener, bool onlyObjects, bool test = false); osg::Vec2i mCurrentGridCenter; // Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center @@ -107,6 +107,11 @@ namespace MWWorld osg::Vec4i gridCenterToBounds(const osg::Vec2i ¢erCell) const; osg::Vec2i getNewGridCenter(const osg::Vec3f &pos, const osg::Vec2i *currentGridCenter = nullptr) const; + void unloadInactiveCell (CellStore* cell, bool test = false); + void deactivateCell (CellStore* cell, bool test = false); + void activateCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test = false); + void loadInactiveCell (CellStore *cell, Loading::Listener* loadingListener, bool test = false); + public: Scene (MWRender::RenderingManager& rendering, MWPhysics::PhysicsSystem *physics, @@ -118,10 +123,6 @@ namespace MWWorld void preloadTerrain(const osg::Vec3f& pos, bool sync=false); void reloadTerrain(); - void unloadCell (CellStoreCollection::iterator iter, bool test = false); - - void loadCell (CellStore *cell, Loading::Listener* loadingListener, bool respawn, bool test = false); - void playerMoved (const osg::Vec3f& pos); void changePlayerCell (CellStore* newCell, const ESM::Position& position, bool adjustPlayerPos); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 611e535c88..89b24a8651 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1421,7 +1421,7 @@ namespace MWWorld mWorldScene->removeFromPagedRefs(ptr); mRendering->rotateObject(ptr, rotate); - mPhysics->updateRotation(ptr); + mPhysics->updateRotation(ptr, rotate); if (const auto object = mPhysics->getObject(ptr)) updateNavigatorObject(object); diff --git a/components/resource/bulletshape.cpp b/components/resource/bulletshape.cpp index fc68c55458..c6f6369dba 100644 --- a/components/resource/bulletshape.cpp +++ b/components/resource/bulletshape.cpp @@ -95,6 +95,11 @@ void BulletShape::setLocalScaling(const btVector3& scale) mAvoidCollisionShape->setLocalScaling(scale); } +bool BulletShape::isAnimated() const +{ + return !mAnimatedShapes.empty(); +} + osg::ref_ptr BulletShape::makeInstance() const { osg::ref_ptr instance (new BulletShapeInstance(this)); diff --git a/components/resource/bulletshape.hpp b/components/resource/bulletshape.hpp index 8ad13fae14..6ac8064cb3 100644 --- a/components/resource/bulletshape.hpp +++ b/components/resource/bulletshape.hpp @@ -52,6 +52,8 @@ namespace Resource void setLocalScaling(const btVector3& scale); + bool isAnimated() const; + private: void deleteShape(btCollisionShape* shape); From 770f91de776c4cc84ee57691a92e19e720d935cf Mon Sep 17 00:00:00 2001 From: jvoisin Date: Thu, 20 May 2021 18:53:55 +0200 Subject: [PATCH 29/57] Clean the fontloader's hack for polish font up - The map can be static and const - The map can be initialized inline - No need to do a `find` + `[]` instead of `at` --- components/fontloader/fontloader.cpp | 84 +++++++++++++++------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index e068fd781b..4c9cc11bd6 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -85,47 +85,51 @@ namespace { // Hacks for polish font unsigned char win1250; - std::map conv; - conv[0x80] = 0xc6; - conv[0x81] = 0x9c; - conv[0x82] = 0xe6; - conv[0x83] = 0xb3; - conv[0x84] = 0xf1; - conv[0x85] = 0xb9; - conv[0x86] = 0xbf; - conv[0x87] = 0x9f; - conv[0x88] = 0xea; - conv[0x89] = 0xea; - conv[0x8a] = 0x0; // not contained in win1250 - conv[0x8b] = 0x0; // not contained in win1250 - conv[0x8c] = 0x8f; - conv[0x8d] = 0xaf; - conv[0x8e] = 0xa5; - conv[0x8f] = 0x8c; - conv[0x90] = 0xca; - conv[0x93] = 0xa3; - conv[0x94] = 0xf6; - conv[0x95] = 0xf3; - conv[0x96] = 0xaf; - conv[0x97] = 0x8f; - conv[0x99] = 0xd3; - conv[0x9a] = 0xd1; - conv[0x9c] = 0x0; // not contained in win1250 - conv[0xa0] = 0xb9; - conv[0xa1] = 0xaf; - conv[0xa2] = 0xf3; - conv[0xa3] = 0xbf; - conv[0xa4] = 0x0; // not contained in win1250 - conv[0xe1] = 0x8c; - // Can't remember if this was supposed to read 0xe2, or is it just an extraneous copypaste? - //conv[0xe1] = 0x8c; - conv[0xe3] = 0x0; // not contained in win1250 - conv[0xf5] = 0x0; // not contained in win1250 - - if (conv.find(c) != conv.end()) - win1250 = conv[c]; - else + static const std::map conv { + {0x80, 0xc6}, + {0x81, 0x9c}, + {0x82, 0xe6}, + {0x83, 0xb3}, + {0x84, 0xf1}, + {0x85, 0xb9}, + {0x86, 0xbf}, + {0x87, 0x9f}, + {0x88, 0xea}, + {0x89, 0xea}, + {0x8a, 0x00}, // not contained in win1250 + {0x8b, 0x00}, // not contained in win1250 + {0x8c, 0x8f}, + {0x8d, 0xaf}, + {0x8e, 0xa5}, + {0x8f, 0x8c}, + {0x90, 0xca}, + {0x93, 0xa3}, + {0x94, 0xf6}, + {0x95, 0xf3}, + {0x96, 0xaf}, + {0x97, 0x8f}, + {0x99, 0xd3}, + {0x9a, 0xd1}, + {0x9c, 0x00}, // not contained in win1250 + {0xa0, 0xb9}, + {0xa1, 0xaf}, + {0xa2, 0xf3}, + {0xa3, 0xbf}, + {0xa4, 0x00}, // not contained in win1250 + {0xe1, 0x8c}, + // Can't remember if this was supposed to read 0xe2, or is it just an extraneous copypaste? + //{0xe1, 0x8c}, + {0xe3, 0x0}, // not contained in win1250 + {0xf5, 0x0} // not contained in win1250 + }; + try + { + win1250 = conv.at(c); + } + catch (std::out_of_range) + { win1250 = c; + } return encoder.getUtf8(std::string(1, win1250)); } else From 5470b3168bb343b33098add052d26ccaac01f405 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Fri, 21 May 2021 12:56:46 +0200 Subject: [PATCH 30/57] Use a switch-case instead of a map, on elsid@' advice elsid@ said: > From my measurements static map + exceptions is slower than original code when loading polish morrowind localization by 25% with GCC 10.2.0. Switch-based solution is about 25x times faster than the original and static map with find only is ~20x faster. --- components/fontloader/fontloader.cpp | 94 +++++++++++++--------------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index 4c9cc11bd6..ef71d8edbb 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -75,63 +75,55 @@ namespace return unicode; } + /// This is a hack for Polish font + unsigned char mapUtf8Char(unsigned char c) { + switch(c){ + case 0x80: return 0xc6; + case 0x81: return 0x9c; + case 0x82: return 0xe6; + case 0x83: return 0xb3; + case 0x84: return 0xf1; + case 0x85: return 0xb9; + case 0x86: return 0xbf; + case 0x87: return 0x9f; + case 0x88: return 0xea; + case 0x89: return 0xea; + case 0x8a: return 0x00; // not contained in win1250 + case 0x8b: return 0x00; // not contained in win1250 + case 0x8c: return 0x8f; + case 0x8d: return 0xaf; + case 0x8e: return 0xa5; + case 0x8f: return 0x8c; + case 0x90: return 0xca; + case 0x93: return 0xa3; + case 0x94: return 0xf6; + case 0x95: return 0xf3; + case 0x96: return 0xaf; + case 0x97: return 0x8f; + case 0x99: return 0xd3; + case 0x9a: return 0xd1; + case 0x9c: return 0x00; // not contained in win1250 + case 0xa0: return 0xb9; + case 0xa1: return 0xaf; + case 0xa2: return 0xf3; + case 0xa3: return 0xbf; + case 0xa4: return 0x00; // not contained in win1250 + case 0xe1: return 0x8c; + // case 0xe1: return 0x8c; // Can't remember if this was supposed to read 0xe2, or is it just an extraneous copypaste? + case 0xe3: return 0x00; // not contained in win1250 + case 0xf5: return 0x00; // not contained in win1250 + default: return c; + } + } + // getUtf8, aka the worst function ever written. // This includes various hacks for dealing with Morrowind's .fnt files that are *mostly* // in the expected win12XX encoding, but also have randomly swapped characters sometimes. // Looks like the Morrowind developers found standard encodings too boring and threw in some twists for fun. std::string getUtf8 (unsigned char c, ToUTF8::Utf8Encoder& encoder, ToUTF8::FromType encoding) { - if (encoding == ToUTF8::WINDOWS_1250) - { - // Hacks for polish font - unsigned char win1250; - static const std::map conv { - {0x80, 0xc6}, - {0x81, 0x9c}, - {0x82, 0xe6}, - {0x83, 0xb3}, - {0x84, 0xf1}, - {0x85, 0xb9}, - {0x86, 0xbf}, - {0x87, 0x9f}, - {0x88, 0xea}, - {0x89, 0xea}, - {0x8a, 0x00}, // not contained in win1250 - {0x8b, 0x00}, // not contained in win1250 - {0x8c, 0x8f}, - {0x8d, 0xaf}, - {0x8e, 0xa5}, - {0x8f, 0x8c}, - {0x90, 0xca}, - {0x93, 0xa3}, - {0x94, 0xf6}, - {0x95, 0xf3}, - {0x96, 0xaf}, - {0x97, 0x8f}, - {0x99, 0xd3}, - {0x9a, 0xd1}, - {0x9c, 0x00}, // not contained in win1250 - {0xa0, 0xb9}, - {0xa1, 0xaf}, - {0xa2, 0xf3}, - {0xa3, 0xbf}, - {0xa4, 0x00}, // not contained in win1250 - {0xe1, 0x8c}, - // Can't remember if this was supposed to read 0xe2, or is it just an extraneous copypaste? - //{0xe1, 0x8c}, - {0xe3, 0x0}, // not contained in win1250 - {0xf5, 0x0} // not contained in win1250 - }; - try - { - win1250 = conv.at(c); - } - catch (std::out_of_range) - { - win1250 = c; - } - return encoder.getUtf8(std::string(1, win1250)); - } + if (encoding == ToUTF8::WINDOWS_1250) // Hack for polish font + return encoder.getUtf8(std::string(1, mapUtf8Char(c))); else return encoder.getUtf8(std::string(1, c)); } From 8561245fda48448160ecc493d40e9f568abae3e9 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 29 Jun 2021 18:43:47 +0200 Subject: [PATCH 31/57] Minor refactor making use of std::clamp --- components/esm/cellref.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index b4d6ac7a72..20edf00a8b 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -72,10 +72,7 @@ void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted) break; case ESM::FourCC<'X','S','C','L'>::value: esm.getHT(mScale); - if (mScale < 0.5) - mScale = 0.5; - else if (mScale > 2) - mScale = 2; + mScale = std::clamp(mScale, 0.5f, 2.0f); break; case ESM::FourCC<'A','N','A','M'>::value: mOwner = esm.getHString(); @@ -153,12 +150,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory, bool } if (mScale != 1.0) { - float scale = mScale; - if (scale < 0.5) - scale = 0.5; - else if (scale > 2) - scale = 2; - esm.writeHNT("XSCL", scale); + esm.writeHNT("XSCL", std::clamp(mScale, 0.5f, 2.0f)); } if (!inInventory) From 5c02e4dddc41311a122b93a1a40f53b2a694d275 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 29 Jun 2021 22:52:40 +0200 Subject: [PATCH 32/57] Delete an outdated/irrelevant comment --- components/fontloader/fontloader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index ef71d8edbb..487b7bd70b 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -109,7 +109,6 @@ namespace case 0xa3: return 0xbf; case 0xa4: return 0x00; // not contained in win1250 case 0xe1: return 0x8c; - // case 0xe1: return 0x8c; // Can't remember if this was supposed to read 0xe2, or is it just an extraneous copypaste? case 0xe3: return 0x00; // not contained in win1250 case 0xf5: return 0x00; // not contained in win1250 default: return c; From 6575b95448c2daf22bff0ba11d7657562570882d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 30 Jun 2021 15:34:40 +1000 Subject: [PATCH 33/57] Support moved references (i.e. with MVRF sub-records) that do not occur at the beginning of the cell references block. --- apps/openmw/mwworld/store.cpp | 52 +++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 944d311229..26b63d59a9 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -36,16 +36,16 @@ namespace MWWorld : mId(id), mIsDeleted(isDeleted) {} - template + template IndexedStore::IndexedStore() { } - template + template typename IndexedStore::iterator IndexedStore::begin() const { return mStatic.begin(); } - template + template typename IndexedStore::iterator IndexedStore::end() const { return mStatic.end(); @@ -192,7 +192,7 @@ namespace MWWorld template typename Store::iterator Store::begin() const { - return mShared.begin(); + return mShared.begin(); } template typename Store::iterator Store::end() const @@ -407,7 +407,7 @@ namespace MWWorld if (mStatic.size() < num) mStatic.resize(num); } - + // Land //========================================================================= Store::~Store() @@ -496,21 +496,29 @@ namespace MWWorld } return search(cell.mName); } + + // this method *must* be called right after esm.loadCell() void Store::handleMovedCellRefs(ESM::ESMReader& esm, ESM::Cell* cell) { - //Handling MovedCellRefs, there is no way to do it inside loadcell - while (esm.isNextSub("MVRF")) { - ESM::CellRef ref; - ESM::MovedCellRef cMRef; - cell->getNextMVRF(esm, cMRef); + ESM::CellRef ref; + ESM::MovedCellRef cMRef; + cMRef.mRefNum.mIndex = 0; + bool deleted = false; + + ESM::ESM_Context ctx = esm.getContext(); + + // Handling MovedCellRefs, there is no way to do it inside loadcell + // TODO: verify above comment + // + // Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following + // implementation when the oher implementation works as well. + while (cell->getNextRef(esm, ref, deleted, /*ignoreMoves*/true, &cMRef)) + { + if (!cMRef.mRefNum.mIndex) + continue; // ignore refs that are not moved ESM::Cell *cellAlt = const_cast(searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1])); - // Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following - // implementation when the oher implementation works as well. - bool deleted = false; - cell->getNextRef(esm, ref, deleted); - // Add data required to make reference appear in the correct cell. // We should not need to test for duplicates, as this part of the code is pre-cell merge. cell->mMovedRefs.push_back(cMRef); @@ -521,7 +529,11 @@ namespace MWWorld cellAlt->mLeasedRefs.emplace_back(std::move(ref), deleted); else *iter = std::make_pair(std::move(ref), deleted); + + cMRef.mRefNum.mIndex = 0; } + + esm.restoreContext(ctx); } const ESM::Cell *Store::search(const std::string &id) const { @@ -642,7 +654,7 @@ namespace MWWorld ESM::Cell cell; bool isDeleted = false; - // Load the (x,y) coordinates of the cell, if it is an exterior cell, + // Load the (x,y) coordinates of the cell, if it is an exterior cell, // so we can find the cell we need to merge with cell.loadNameAndData(esm, isDeleted); std::string idLower = Misc::StringUtils::lowerCase(cell.mName); @@ -870,7 +882,7 @@ namespace MWWorld return true; } - + // Pathgrid //========================================================================= @@ -972,7 +984,7 @@ namespace MWWorld // Skill //========================================================================= - + Store::Store() { } @@ -1013,7 +1025,7 @@ namespace MWWorld } void Store::setUp() { - for (int i = 0; i < ESM::Attribute::Length; ++i) + for (int i = 0; i < ESM::Attribute::Length; ++i) { ESM::Attribute newAttribute; newAttribute.mId = ESM::Attribute::sAttributeIds[i]; @@ -1035,7 +1047,7 @@ namespace MWWorld return mStatic.end(); } - + // Dialogue //========================================================================= From a3942a1e0ab27b42493ef31255bc9f98a4dc2cdd Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 30 Jun 2021 19:58:11 +0200 Subject: [PATCH 34/57] Remove redundant check for y coordinate in inRange function --- components/detournavigator/findsmoothpath.cpp | 2 +- components/detournavigator/findsmoothpath.hpp | 19 ++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/components/detournavigator/findsmoothpath.cpp b/components/detournavigator/findsmoothpath.cpp index 8974be5321..ae4ab497ef 100644 --- a/components/detournavigator/findsmoothpath.cpp +++ b/components/detournavigator/findsmoothpath.cpp @@ -125,7 +125,7 @@ namespace DetourNavigator { // Stop at Off-Mesh link or when point is further than slop away. if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - !inRange(Misc::Convert::makeOsgVec3f(&steerPath[ns * 3]), startPos, minTargetDist, 1000.0f)) + !inRange(Misc::Convert::makeOsgVec3f(&steerPath[ns * 3]), startPos, minTargetDist)) break; ns++; } diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 0a9b5bed86..3a5a1f57fc 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -26,10 +26,10 @@ namespace DetourNavigator { struct Settings; - inline bool inRange(const osg::Vec3f& v1, const osg::Vec3f& v2, const float r, const float h) + inline bool inRange(const osg::Vec3f& v1, const osg::Vec3f& v2, const float r) { const auto d = v2 - v1; - return (d.x() * d.x() + d.z() * d.z()) < r * r && std::abs(d.y()) < h; + return (d.x() * d.x() + d.z() * d.z()) < r * r; } std::vector fixupCorridor(const std::vector& path, const std::vector& visited); @@ -201,13 +201,8 @@ namespace DetourNavigator polygonPath = fixupCorridor(polygonPath, result->mVisited); polygonPath = fixupShortcuts(polygonPath, navMeshQuery); - float h = 0; - navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &h); - iterPos = result->mResultPos; - iterPos.y() = h; - // Handle end of path and off-mesh links when close enough. - if (endOfPath && inRange(iterPos, steerTarget->steerPos, slop, 1.0f)) + if (endOfPath && inRange(result->mResultPos, steerTarget->steerPos, slop)) { // Reached end of path. iterPos = targetPos; @@ -215,7 +210,7 @@ namespace DetourNavigator ++smoothPathSize; break; } - else if (offMeshConnection && inRange(iterPos, steerTarget->steerPos, slop, 1.0f)) + else if (offMeshConnection && inRange(result->mResultPos, steerTarget->steerPos, slop)) { // Advance the path up to and over the off-mesh connection. dtPolyRef prevRef = 0; @@ -251,14 +246,16 @@ namespace DetourNavigator // Move position at the other side of the off-mesh link. iterPos = endPos; const auto height = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos); - if (!height) return Status::GetPolyHeightFailed; - iterPos.y() = *height; } } + navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &iterPos.y()); + iterPos.x() = result->mResultPos.x(); + iterPos.z() = result->mResultPos.z(); + // Store results. *out++ = iterPos; ++smoothPathSize; From cc08a45c310f5b24cc465a5200be006848327084 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 30 Jun 2021 20:02:08 +0200 Subject: [PATCH 35/57] Move include where it is needed --- components/detournavigator/findsmoothpath.cpp | 2 ++ components/detournavigator/findsmoothpath.hpp | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/detournavigator/findsmoothpath.cpp b/components/detournavigator/findsmoothpath.cpp index ae4ab497ef..5871d05fa3 100644 --- a/components/detournavigator/findsmoothpath.cpp +++ b/components/detournavigator/findsmoothpath.cpp @@ -1,5 +1,7 @@ #include "findsmoothpath.hpp" +#include + #include #include diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 3a5a1f57fc..5b1ec32fa1 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -14,9 +14,8 @@ #include #include -#include - #include + #include #include From 7e1630a7ad3f57df6fd3a899928e6c8a0c0f7824 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 30 Jun 2021 20:04:16 +0200 Subject: [PATCH 36/57] Remove redundant getPolyHeight wrapper --- components/detournavigator/findsmoothpath.hpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 5b1ec32fa1..8baa8206c6 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -142,15 +142,6 @@ namespace DetourNavigator return {std::move(result)}; } - inline std::optional getPolyHeight(const dtNavMeshQuery& navMeshQuery, const dtPolyRef ref, const osg::Vec3f& pos) - { - float result = 0.0f; - const auto status = navMeshQuery.getPolyHeight(ref, pos.ptr(), &result); - if (!dtStatusSucceed(status)) - return {}; - return result; - } - template Status makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery, const dtQueryFilter& filter, const osg::Vec3f& start, const osg::Vec3f& end, const float stepSize, @@ -243,11 +234,10 @@ namespace DetourNavigator } // Move position at the other side of the off-mesh link. - iterPos = endPos; - const auto height = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos); - if (!height) + if (dtStatusFailed(navMeshQuery.getPolyHeight(polygonPath.front(), endPos.ptr(), &iterPos.y()))) return Status::GetPolyHeightFailed; - iterPos.y() = *height; + iterPos.x() = endPos.x(); + iterPos.z() = endPos.z(); } } From 793c30ab8daa80658c55c54a42fd9b5cd57b704a Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 30 Jun 2021 20:06:45 +0200 Subject: [PATCH 37/57] Check dtNavMeshQuery::getPolyHeight status Otherwise when it fails a node with zero height will be added to a path. --- components/detournavigator/findsmoothpath.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 8baa8206c6..4e656e6270 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -241,7 +241,8 @@ namespace DetourNavigator } } - navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &iterPos.y()); + if (dtStatusFailed(navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &iterPos.y()))) + return Status::GetPolyHeightFailed; iterPos.x() = result->mResultPos.x(); iterPos.z() = result->mResultPos.z(); From a54c4bc2e9588974c710f373262c7eb9ca8c749d Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 30 Jun 2021 20:10:34 +0200 Subject: [PATCH 38/57] Check dtNavMeshQuery::findStraightPath status --- components/detournavigator/findsmoothpath.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/detournavigator/findsmoothpath.cpp b/components/detournavigator/findsmoothpath.cpp index 5871d05fa3..6598263398 100644 --- a/components/detournavigator/findsmoothpath.cpp +++ b/components/detournavigator/findsmoothpath.cpp @@ -105,7 +105,7 @@ namespace DetourNavigator return result; } - std::optional getSteerTarget(const dtNavMeshQuery& navQuery, const osg::Vec3f& startPos, + std::optional getSteerTarget(const dtNavMeshQuery& navMeshQuery, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const float minTargetDist, const std::vector& path) { // Find steer target. @@ -115,8 +115,11 @@ namespace DetourNavigator std::array steerPathFlags; std::array steerPathPolys; int nsteerPath = 0; - navQuery.findStraightPath(startPos.ptr(), endPos.ptr(), path.data(), int(path.size()), steerPath.data(), - steerPathFlags.data(), steerPathPolys.data(), &nsteerPath, maxSteerPoints); + const dtStatus status = navMeshQuery.findStraightPath(startPos.ptr(), endPos.ptr(), path.data(), + static_cast(path.size()), steerPath.data(), steerPathFlags.data(), steerPathPolys.data(), + &nsteerPath, maxSteerPoints); + if (dtStatusFailed(status)) + return std::nullopt; assert(nsteerPath >= 0); if (!nsteerPath) return std::nullopt; From 94e460ba1e675fd9482834a8ebc007cc09bf92ff Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 30 Jun 2021 20:11:38 +0200 Subject: [PATCH 39/57] Use proper check for distance To avoid invalid results for r < 1. --- components/detournavigator/findsmoothpath.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index 4e656e6270..db2219b2cd 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -27,8 +27,7 @@ namespace DetourNavigator inline bool inRange(const osg::Vec3f& v1, const osg::Vec3f& v2, const float r) { - const auto d = v2 - v1; - return (d.x() * d.x() + d.z() * d.z()) < r * r; + return (osg::Vec2f(v1.x(), v1.z()) - osg::Vec2f(v2.x(), v2.z())).length() < r; } std::vector fixupCorridor(const std::vector& path, const std::vector& visited); From 5624fe19112f2ba0f29239fa2914fba094ed842b Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 30 Jun 2021 19:50:39 +0200 Subject: [PATCH 40/57] Consider path not found when there is navmesh query error Fix a specific case when the guard at the start of the game fails to find path due to failed getPolyHeight call that results into a partial path to the target. --- apps/openmw/mwmechanics/pathfinding.cpp | 33 ++++++++++++++++--------- apps/openmw/mwmechanics/pathfinding.hpp | 8 +++--- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index f6283831d5..2f8e830434 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -369,7 +369,13 @@ namespace MWMechanics mPath.clear(); // If it's not possible to build path over navmesh due to disabled navmesh generation fallback to straight path - if (!buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath))) + DetourNavigator::Status status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, + areaCosts, std::back_inserter(mPath)); + + if (status != DetourNavigator::Status::Success) + mPath.clear(); + + if (status == DetourNavigator::Status::NavMeshNotFound) mPath.push_back(endPoint); mConstructed = !mPath.empty(); @@ -382,25 +388,33 @@ namespace MWMechanics mPath.clear(); mCell = cell; - bool hasNavMesh = false; + DetourNavigator::Status status = DetourNavigator::Status::NavMeshNotFound; if (!actor.getClass().isPureWaterCreature(actor) && !actor.getClass().isPureFlyingCreature(actor)) - hasNavMesh = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath)); + { + status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, areaCosts, std::back_inserter(mPath)); + if (status != DetourNavigator::Status::Success) + mPath.clear(); + } - if (hasNavMesh && mPath.empty()) - buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, + if (status != DetourNavigator::Status::NavMeshNotFound && mPath.empty()) + { + status = buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags | DetourNavigator::Flag_usePathgrid, areaCosts, std::back_inserter(mPath)); + if (status != DetourNavigator::Status::Success) + mPath.clear(); + } if (mPath.empty()) buildPathByPathgridImpl(startPoint, endPoint, pathgridGraph, std::back_inserter(mPath)); - if (!hasNavMesh && mPath.empty()) + if (status == DetourNavigator::Status::NavMeshNotFound && mPath.empty()) mPath.push_back(endPoint); mConstructed = !mPath.empty(); } - bool PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, + DetourNavigator::Status PathFinder::buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator> out) { @@ -409,9 +423,6 @@ namespace MWMechanics const auto navigator = world->getNavigator(); const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, areaCosts, out); - if (status == DetourNavigator::Status::NavMeshNotFound) - return false; - if (status != DetourNavigator::Status::Success) { Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status) @@ -420,7 +431,7 @@ namespace MWMechanics << DetourNavigator::WriteFlags {flags} << ")"; } - return true; + return status; } void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents, diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index aa6a79c4eb..0ada08d3fb 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -209,9 +210,10 @@ namespace MWMechanics void buildPathByPathgridImpl(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const PathgridGraph& pathgridGraph, std::back_insert_iterator> out); - bool buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, const osg::Vec3f& startPoint, - const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags, - const DetourNavigator::AreaCosts& areaCosts, std::back_insert_iterator> out); + [[nodiscard]] DetourNavigator::Status buildPathByNavigatorImpl(const MWWorld::ConstPtr& actor, + const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, + const DetourNavigator::Flags flags, const DetourNavigator::AreaCosts& areaCosts, + std::back_insert_iterator> out); }; } From 2cb948289322afb6945b899c875b10e458c13f00 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Thu, 1 Jul 2021 23:09:08 +0000 Subject: [PATCH 41/57] Use a std::vector instead of a std::list in hypertextparser.cpp --- apps/openmw/mwdialogue/hypertextparser.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwdialogue/hypertextparser.cpp b/apps/openmw/mwdialogue/hypertextparser.cpp index fa7de97d2e..caafa5f324 100644 --- a/apps/openmw/mwdialogue/hypertextparser.cpp +++ b/apps/openmw/mwdialogue/hypertextparser.cpp @@ -50,15 +50,16 @@ namespace MWDialogue const MWWorld::Store & dialogs = MWBase::Environment::get().getWorld()->getStore().get(); - std::list keywordList; - for (MWWorld::Store::iterator it = dialogs.begin(); it != dialogs.end(); ++it) - keywordList.push_back(Misc::StringUtils::lowerCase(it->mId)); - keywordList.sort(Misc::StringUtils::ciLess); + std::vector keywordList; + keywordList.reserve(dialogs.getSize()); + for (const auto& it : dialogs) + keywordList.push_back(Misc::StringUtils::lowerCase(it.mId)); + sort(keywordList.begin(), keywordList.end()); KeywordSearch keywordSearch; - for (std::list::const_iterator it = keywordList.begin(); it != keywordList.end(); ++it) - keywordSearch.seed(*it, 0 /*unused*/); + for (const auto& it : keywordList) + keywordSearch.seed(it, 0 /*unused*/); std::vector::Match> matches; keywordSearch.highlightKeywords(text.begin(), text.end(), matches); From 3cab69c389d5759a5ae3f29079f386c97626fca0 Mon Sep 17 00:00:00 2001 From: Dobrohotov Alexei Date: Sat, 3 Jul 2021 01:03:57 +0300 Subject: [PATCH 42/57] Fix ShowMap partial match filtering (bug #6115) --- CHANGELOG.md | 1 + apps/openmw/mwscript/guiextensions.cpp | 13 +++++-------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 828bc1d9ff..5bcf27301a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Bug #5483: AutoCalc flag is not used to calculate spells cost Bug #6066: addtopic "return" does not work from within script. No errors thrown Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime + Bug #6115: Showmap overzealous matching 0.47.0 ------ diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index cb1e5cd91d..f0bc90e044 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -124,17 +124,14 @@ namespace MWScript const MWWorld::Store &cells = MWBase::Environment::get().getWorld()->getStore().get(); - MWWorld::Store::iterator it = cells.extBegin(); - for (; it != cells.extEnd(); ++it) + MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager(); + + for (auto it = cells.extBegin(); it != cells.extEnd(); ++it) { std::string name = it->mName; ::Misc::StringUtils::lowerCaseInPlace(name); - if (name.find(cell) != std::string::npos) - MWBase::Environment::get().getWindowManager()->addVisitedLocation ( - it->mName, - it->getGridX(), - it->getGridY() - ); + if (name.length() >= cell.length() && name.substr(0, cell.length()) == cell) + winMgr->addVisitedLocation(it->mName, it->getGridX(), it->getGridY()); } } }; From 5e4beb217ae4208d211a712e2016380dbb0776a5 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 27 Jun 2021 13:14:23 +0200 Subject: [PATCH 43/57] Make fatigue and magicka recalculation behave the same way --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwmechanics/creaturestats.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bcf27301a..789871c4a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Bug #5483: AutoCalc flag is not used to calculate spells cost Bug #6066: addtopic "return" does not work from within script. No errors thrown Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime + Bug #6107: Fatigue is incorrectly recalculated when fortify effect is applied or removed Bug #6115: Showmap overzealous matching 0.47.0 diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index e62d686ee2..e9eab2991b 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -826,7 +826,7 @@ namespace MWMechanics DynamicStat magicka = creatureStats.getMagicka(); float diff = (static_cast(magickaFactor*intelligence)) - magicka.getBase(); - float currentToBaseRatio = (magicka.getCurrent() / magicka.getBase()); + float currentToBaseRatio = magicka.getBase() > 0 ? magicka.getCurrent() / magicka.getBase() : 0; magicka.setModified(magicka.getModified() + diff, 0); magicka.setCurrent(magicka.getBase() * currentToBaseRatio, false, true); creatureStats.setMagicka(magicka); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index c6561af961..1ff44fcbb0 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -159,7 +159,7 @@ namespace MWMechanics float diff = (strength+willpower+agility+endurance) - fatigue.getBase(); float currentToBaseRatio = fatigue.getBase() > 0 ? (fatigue.getCurrent() / fatigue.getBase()) : 0; fatigue.setModified(fatigue.getModified() + diff, 0); - fatigue.setCurrent(fatigue.getBase() * currentToBaseRatio); + fatigue.setCurrent(fatigue.getBase() * currentToBaseRatio, false, true); setFatigue(fatigue); } } From 6bb030aa55fd5df9bbc73e1d1c3516346a56bcf8 Mon Sep 17 00:00:00 2001 From: NeveHanter Date: Sat, 3 Jul 2021 13:40:36 +0200 Subject: [PATCH 44/57] Ignore actors siding with player in awarness check to allow training the sneaking or knowing whether player is detected by other actors in the siding actor line of sight --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/actors.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bcf27301a..b508d518d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Bug #6066: addtopic "return" does not work from within script. No errors thrown Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime Bug #6115: Showmap overzealous matching + Bug #6133: Cannot reliably sneak or steal in the sight of the NPCs siding with player 0.47.0 ------ diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index e62d686ee2..43d0264764 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -2396,11 +2396,17 @@ namespace MWMechanics float radius = std::min(fSneakUseDist, mActorsProcessingRange); getObjectsInRange(position, radius, observers); + std::set sidingActors; + getActorsSidingWith(player, sidingActors); + for (const MWWorld::Ptr &observer : observers) { if (observer == player || observer.getClass().getCreatureStats(observer).isDead()) continue; + if (sidingActors.find(observer) != sidingActors.cend()) + continue; + if (world->getLOS(player, observer)) { if (MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, observer)) From 0e57622bbeeb63fd50c5afa77bcd0658c7a0f352 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sat, 3 Jul 2021 21:04:17 +0100 Subject: [PATCH 45/57] Correctly track added and removed state --- components/shader/shadervisitor.cpp | 176 ++++++++++++++++++++++++---- 1 file changed, 156 insertions(+), 20 deletions(-) diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 8a84dfc68b..9747d61acc 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -22,6 +22,68 @@ namespace Shader { + class AddedState : public osg::Object + { + public: + AddedState() = default; + AddedState(const AddedState& rhs, const osg::CopyOp& copyOp) + : osg::Object(rhs, copyOp) + , mUniforms(rhs.mUniforms) + , mModes(rhs.mModes) + , mAttributes(rhs.mAttributes) + { + } + + void addUniform(const std::string& name) { mUniforms.emplace(name); } + void setMode(osg::StateAttribute::GLMode mode) { mModes.emplace(mode); } + void setAttribute(osg::StateAttribute::TypeMemberPair typeMemberPair) { mAttributes.emplace(typeMemberPair); } + + void setAttribute(const osg::StateAttribute* attribute) + { + mAttributes.emplace(attribute->getTypeMemberPair()); + } + template + void setAttribute(osg::ref_ptr attribute) { setAttribute(attribute.get()); } + + void setAttributeAndModes(const osg::StateAttribute* attribute) + { + setAttribute(attribute); + InterrogateModesHelper helper(this); + attribute->getModeUsage(helper); + } + template + void setAttributeAndModes(osg::ref_ptr attribute) { setAttributeAndModes(attribute.get()); } + + bool hasUniform(const std::string& name) { return mUniforms.count(name); } + bool hasMode(osg::StateAttribute::GLMode mode) { return mModes.count(mode); } + bool hasAttribute(osg::StateAttribute::TypeMemberPair typeMemberPair) { return mAttributes.count(typeMemberPair); } + bool hasAttribute(osg::StateAttribute::Type type, unsigned int member) { return hasAttribute(osg::StateAttribute::TypeMemberPair(type, member)); } + + const std::set& getAttributes() { return mAttributes; } + + bool empty() + { + return mUniforms.empty() && mModes.empty() && mAttributes.empty(); + } + + META_Object(Shader, AddedState) + + private: + class InterrogateModesHelper : public osg::StateAttribute::ModeUsage + { + public: + InterrogateModesHelper(AddedState* tracker) : mTracker(tracker) {} + void usesMode(osg::StateAttribute::GLMode mode) override { mTracker->setMode(mode); } + void usesTextureMode(osg::StateAttribute::GLMode mode) override {} + + private: + AddedState* mTracker; + }; + + std::unordered_set mUniforms; + std::unordered_set mModes; + std::set mAttributes; + }; ShaderVisitor::ShaderRequirements::ShaderRequirements() : mShaderRequired(false) @@ -100,14 +162,32 @@ namespace Shader return static_cast(stateSet.getUserDataContainer()->getUserObject("removedState")); } - void updateRemovedState(osg::UserDataContainer& userData, osg::StateSet* stateSet) + void updateRemovedState(osg::UserDataContainer& userData, osg::StateSet* removedState) { unsigned int index = userData.getUserObjectIndex("removedState"); if (index < userData.getNumUserObjects()) - userData.setUserObject(index, stateSet); + userData.setUserObject(index, removedState); else - userData.addUserObject(stateSet); - stateSet->setName("removedState"); + userData.addUserObject(removedState); + removedState->setName("removedState"); + } + + AddedState* getAddedState(osg::StateSet& stateSet) + { + if (!stateSet.getUserDataContainer()) + return nullptr; + + return static_cast(stateSet.getUserDataContainer()->getUserObject("addedState")); + } + + void updateAddedState(osg::UserDataContainer& userData, AddedState* addedState) + { + unsigned int index = userData.getUserObjectIndex("addedState"); + if (index < userData.getNumUserObjects()) + userData.setUserObject(index, addedState); + else + userData.addUserObject(addedState); + addedState->setName("addedState"); } const char* defaultTextures[] = { "diffuseMap", "normalMap", "emissiveMap", "darkMap", "detailMap", "envMap", "specularMap", "decalMap", "bumpMap" }; @@ -275,11 +355,13 @@ namespace Shader osg::StateSet::AttributeList removedAttributes; if (osg::ref_ptr removedState = getRemovedState(*stateset)) removedAttributes = removedState->getAttributeList(); + osg::ref_ptr addedState = getAddedState(*stateset); + for (const auto* attributeMap : std::initializer_list{ &attributes, &removedAttributes }) { for (osg::StateSet::AttributeList::const_iterator it = attributeMap->begin(); it != attributeMap->end(); ++it) { - if (attributeMap != &removedAttributes && removedAttributes.count(it->first)) + if (addedState && attributeMap != &removedAttributes && addedState->hasAttribute(it->first)) continue; if (it->first.first == osg::StateAttribute::MATERIAL) { @@ -291,9 +373,6 @@ namespace Shader const osg::Material* mat = static_cast(it->second.first.get()); - if (!writableStateSet) - writableStateSet = getWritableStateSet(node); - int colorMode; switch (mat->getColorMode()) { @@ -371,6 +450,10 @@ namespace Shader writableStateSet = node.getOrCreateStateSet(); else writableStateSet = getWritableStateSet(node); + osg::ref_ptr addedState = new AddedState; + osg::ref_ptr previousAddedState = getAddedState(*writableStateSet); + if (!previousAddedState) + previousAddedState = new AddedState; ShaderManager::DefineMap defineMap; for (unsigned int i=0; iaddUniform(new osg::Uniform("colorMode", reqs.mColorMode)); + addedState->addUniform("colorMode"); defineMap["alphaFunc"] = std::to_string(reqs.mAlphaFunc); @@ -401,20 +485,23 @@ namespace Shader if (reqs.mAlphaFunc != osg::AlphaFunc::ALWAYS) { writableStateSet->addUniform(new osg::Uniform("alphaRef", reqs.mAlphaRef)); + addedState->addUniform("alphaRef"); if (!removedState->getAttributePair(osg::StateAttribute::ALPHAFUNC)) { const auto* alphaFunc = writableStateSet->getAttributePair(osg::StateAttribute::ALPHAFUNC); - if (alphaFunc) + if (alphaFunc && !previousAddedState->hasAttribute(osg::StateAttribute::ALPHAFUNC, 0)) removedState->setAttribute(alphaFunc->first, alphaFunc->second); } // This prevents redundant glAlphaFunc calls while letting the shadows bin still see the test writableStateSet->setAttribute(RemovedAlphaFunc::getInstance(reqs.mAlphaFunc), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); + addedState->setAttribute(RemovedAlphaFunc::getInstance(reqs.mAlphaFunc)); // Blending won't work with A2C as we use the alpha channel for coverage. gl_SampleCoverage from ARB_sample_shading would save the day, but requires GLSL 130 if (mConvertAlphaTestToAlphaToCoverage && !reqs.mAlphaBlend) { writableStateSet->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, osg::StateAttribute::ON); + addedState->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); defineMap["alphaToCoverage"] = "1"; } @@ -425,10 +512,11 @@ namespace Shader // We could fall back to a texture size uniform if EXT_gpu_shader4 is missing } - if (writableStateSet->getMode(GL_ALPHA_TEST) != osg::StateAttribute::INHERIT) + if (writableStateSet->getMode(GL_ALPHA_TEST) != osg::StateAttribute::INHERIT && !previousAddedState->hasMode(GL_ALPHA_TEST)) removedState->setMode(GL_ALPHA_TEST, writableStateSet->getMode(GL_ALPHA_TEST)); // This disables the deprecated fixed-function alpha test writableStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); + addedState->setMode(GL_ALPHA_TEST); if (!removedState->getModeList().empty() || !removedState->getAttributeList().empty()) { @@ -442,6 +530,18 @@ namespace Shader updateRemovedState(*writableUserData, removedState); } + if (!addedState->empty()) + { + // user data is normally shallow copied so shared with the original stateset + osg::ref_ptr writableUserData; + if (mAllowedToModifyStateSets) + writableUserData = writableStateSet->getOrCreateUserDataContainer(); + else + writableUserData = getWritableUserDataContainer(*writableStateSet); + + updateAddedState(*writableUserData, addedState); + } + defineMap["translucentFramebuffer"] = mTranslucentFramebuffer ? "1" : "0"; std::string shaderPrefix; @@ -453,11 +553,14 @@ namespace Shader if (vertexShader && fragmentShader) { - writableStateSet->setAttributeAndModes(mShaderManager.getProgram(vertexShader, fragmentShader), osg::StateAttribute::ON); + auto program = mShaderManager.getProgram(vertexShader, fragmentShader); + writableStateSet->setAttributeAndModes(program, osg::StateAttribute::ON); + addedState->setAttributeAndModes(program); for (std::map::const_iterator texIt = reqs.mTextures.begin(); texIt != reqs.mTextures.end(); ++texIt) { writableStateSet->addUniform(new osg::Uniform(texIt->second.c_str(), texIt->first), osg::StateAttribute::ON); + addedState->addUniform(texIt->second); } } } @@ -472,24 +575,57 @@ namespace Shader else writableStateSet = getWritableStateSet(node); - writableStateSet->removeAttribute(osg::StateAttribute::PROGRAM); + // user data is normally shallow copied so shared with the original stateset - we'll need to copy before edits + osg::ref_ptr writableUserData; - if (osg::ref_ptr removedState = getRemovedState(*writableStateSet)) + if (osg::ref_ptr addedState = getAddedState(*writableStateSet)) { - // user data is normally shallow copied so shared with the original stateset - osg::ref_ptr writableUserData; if (mAllowedToModifyStateSets) writableUserData = writableStateSet->getUserDataContainer(); else writableUserData = getWritableUserDataContainer(*writableStateSet); + + unsigned int index = writableUserData->getUserObjectIndex("addedState"); + writableUserData->removeUserObject(index); + + // O(n log n) to use StateSet::removeX, but this is O(n) + for (auto itr = writableStateSet->getUniformList().begin(); itr != writableStateSet->getUniformList().end();) + { + if (addedState->hasUniform(itr->first)) + writableStateSet->getUniformList().erase(itr); + else + ++itr; + } + + for (auto itr = writableStateSet->getModeList().begin(); itr != writableStateSet->getModeList().end();) + { + if (addedState->hasMode(itr->first)) + writableStateSet->getModeList().erase(itr); + else + ++itr; + } + + // StateAttributes track the StateSets they're attached to + // We don't have access to the function to do that, and can't call removeAttribute with an iterator + for (const auto& [type, member] : addedState->getAttributes()) + writableStateSet->removeAttribute(type, member); + } + + + if (osg::ref_ptr removedState = getRemovedState(*writableStateSet)) + { + if (!writableUserData) + { + if (mAllowedToModifyStateSets) + writableUserData = writableStateSet->getUserDataContainer(); + else + writableUserData = getWritableUserDataContainer(*writableStateSet); + } + unsigned int index = writableUserData->getUserObjectIndex("removedState"); writableUserData->removeUserObject(index); - for (const auto& [mode, value] : removedState->getModeList()) - writableStateSet->setMode(mode, value); - - for (const auto& attribute : removedState->getAttributeList()) - writableStateSet->setAttribute(attribute.second.first, attribute.second.second); + writableStateSet->merge(*removedState); } } From b1fa0e9560c837292ffdb61caff6b577a55c7507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20St=C3=B6ckel?= Date: Sun, 4 Jul 2021 08:36:59 +0000 Subject: [PATCH 46/57] Fix Avatar Preview Coordinate Transformations in the Inventory (Issues #6129, #6131) --- AUTHORS.md | 1 + CHANGELOG.md | 2 ++ apps/openmw/mwbase/windowmanager.hpp | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 43 ++++++++++++++++---------- apps/openmw/mwgui/inventorywindow.hpp | 3 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- apps/openmw/mwgui/windowmanagerimp.hpp | 2 +- 7 files changed, 36 insertions(+), 19 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index 6a613b1c69..aa492f6c1e 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -29,6 +29,7 @@ Programmers Alex S (docwest) Alexey Yaryshev (skeevert) Allofich + Andreas Stöckel Andrei Kortunov (akortunov) AnyOldName3 Ardekantur diff --git a/CHANGELOG.md b/CHANGELOG.md index b508d518d7..76e0323071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ Bug #6066: addtopic "return" does not work from within script. No errors thrown Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime Bug #6115: Showmap overzealous matching + Bug #6129: Player avatar not displayed correctly for large window sizes when GUI scaling active + Bug #6131: Item selection in the avatar window not working correctly for large window sizes Bug #6133: Cannot reliably sneak or steal in the sight of the NPCs siding with player 0.47.0 diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 31d188879f..dde470b119 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -171,7 +171,7 @@ namespace MWBase virtual void setDragDrop(bool dragDrop) = 0; virtual bool getWorldMouseOver() = 0; - virtual float getScalingFactor() = 0; + virtual float getScalingFactor() const = 0; virtual bool toggleFogOfWar() = 0; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 402f7656cb..5f18fba91f 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -461,14 +461,10 @@ namespace MWGui void InventoryWindow::updatePreviewSize() { - MyGUI::IntSize size = mAvatarImage->getSize(); - int width = std::min(mPreview->getTextureWidth(), size.width); - int height = std::min(mPreview->getTextureHeight(), size.height); - float scalingFactor = MWBase::Environment::get().getWindowManager()->getScalingFactor(); - mPreview->setViewport(int(width*scalingFactor), int(height*scalingFactor)); - + const MyGUI::IntSize viewport = getPreviewViewportSize(); + mPreview->setViewport(viewport.width, viewport.height); mAvatarImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, - width*scalingFactor/float(mPreview->getTextureWidth()), height*scalingFactor/float(mPreview->getTextureHeight()))); + viewport.width / float(mPreview->getTextureWidth()), viewport.height / float(mPreview->getTextureHeight()))); } void InventoryWindow::onNameFilterChanged(MyGUI::EditBox* _sender) @@ -629,15 +625,8 @@ namespace MWGui MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y) { - // convert to OpenGL lower-left origin - y = (mAvatarImage->getHeight()-1) - y; - - // Scale coordinates - float scalingFactor = MWBase::Environment::get().getWindowManager()->getScalingFactor(); - x = static_cast(x*scalingFactor); - y = static_cast(y*scalingFactor); - - int slot = mPreview->getSlotSelected (x, y); + const osg::Vec2f viewport_coords = mapPreviewWindowToViewport(x, y); + int slot = mPreview->getSlotSelected(viewport_coords.x(), viewport_coords.y()); if (slot == -1) return MWWorld::Ptr(); @@ -832,4 +821,26 @@ namespace MWGui { mPreview->rebuild(); } + + MyGUI::IntSize InventoryWindow::getPreviewViewportSize() const + { + const MyGUI::IntSize previewWindowSize = mAvatarImage->getSize(); + const float scale = MWBase::Environment::get().getWindowManager()->getScalingFactor(); + + return MyGUI::IntSize(std::min(mPreview->getTextureWidth(), previewWindowSize.width * scale), + std::min(mPreview->getTextureHeight(), previewWindowSize.height * scale)); + } + + osg::Vec2f InventoryWindow::mapPreviewWindowToViewport(int x, int y) const + { + const MyGUI::IntSize previewWindowSize = mAvatarImage->getSize(); + const float normalisedX = x / std::max(1.0f, previewWindowSize.width); + const float normalisedY = y / std::max(1.0f, previewWindowSize.height); + + const MyGUI::IntSize viewport = getPreviewViewportSize(); + return osg::Vec2f( + normalisedX * float(viewport.width - 1), + (1.0 - normalisedY) * float(viewport.height - 1) + ); + } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 214245767b..a89e9a945f 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -130,6 +130,9 @@ namespace MWGui void updatePreviewSize(); void updateArmorRating(); + MyGUI::IntSize getPreviewViewportSize() const; + osg::Vec2f mapPreviewWindowToViewport(int x, int y) const; + void adjustPanes(); /// Unequips count items from mSelectedItem, if it is equipped, and then updates mSelectedItem in case the items were re-stacked diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index f45990f215..521d247cff 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1326,7 +1326,7 @@ namespace MWGui return mHud->getWorldMouseOver(); } - float WindowManager::getScalingFactor() + float WindowManager::getScalingFactor() const { return mScalingFactor; } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 5a0d89ce10..c5b2b93826 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -208,7 +208,7 @@ namespace MWGui void setDragDrop(bool dragDrop) override; bool getWorldMouseOver() override; - float getScalingFactor() override; + float getScalingFactor() const override; bool toggleFogOfWar() override; bool toggleFullHelp() override; ///< show extra info in item tooltips (owner, script) From 8d1eb7e2e6a72f04c2e15e4816009121366d885c Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 4 Jul 2021 03:15:40 +0200 Subject: [PATCH 47/57] Fix slow AiPackage::getTarget calls Assume there are no cell refs with empty ref id. --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aipackage.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b508d518d7..60de6d6d57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -143,6 +143,7 @@ Bug #6036: OpenMW-CS: Terrain selection at the border of cells omits certain corner vertices Bug #6043: Actor can have torch missing when torch animation is played Bug #6047: Mouse bindings can be triggered during save loading + Bug #6136: Game freezes when NPCs try to open doors that are about to be closed Feature #390: 3rd person look "over the shoulder" Feature #832: OpenMW-CS: Handle deleted references Feature #1536: Show more information about level on menu diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 5239491795..8ad9447514 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -55,6 +55,11 @@ MWWorld::Ptr MWMechanics::AiPackage::getTarget() const if (mTargetActorId == -1) { + if (mTargetActorRefId.empty()) + { + mTargetActorId = -2; + return MWWorld::Ptr(); + } MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mTargetActorRefId, false); if (target.isEmpty()) { From 3014963145f1c42ee86d784f7a26869bfbeae0a3 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 4 Jul 2021 15:20:27 +0000 Subject: [PATCH 48/57] Fail on bad download instead of downloading HTML 404 page --- CI/before_script.msvc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 2a4924a5f5..8d0b8647b4 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -258,10 +258,10 @@ download() { if [ -z $VERBOSE ]; then RET=0 - curl --silent --retry 10 -Ly 5 -o $FILE $URL || RET=$? + curl --silent --fail --retry 10 -Ly 5 -o $FILE $URL || RET=$? else RET=0 - curl --retry 10 -Ly 5 -o $FILE $URL || RET=$? + curl --fail --retry 10 -Ly 5 -o $FILE $URL || RET=$? fi if [ $RET -ne 0 ]; then From 91cece5cc4133a27dd90495f9a8b0cc6f0142509 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 1 Jul 2021 19:00:05 +0200 Subject: [PATCH 49/57] Define ESM::Land static constants as constexpr To avoid linking issues. --- components/esm/loadland.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 2a1140ad2e..9cba41b160 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -49,28 +49,28 @@ struct Land }; // default height to use in case there is no Land record - static const int DEFAULT_HEIGHT = -2048; + static constexpr int DEFAULT_HEIGHT = -2048; // number of vertices per side - static const int LAND_SIZE = 65; + static constexpr int LAND_SIZE = 65; // cell terrain size in world coords - static const int REAL_SIZE = Constants::CellSizeInUnits; + static constexpr int REAL_SIZE = Constants::CellSizeInUnits; // total number of vertices - static const int LAND_NUM_VERTS = LAND_SIZE * LAND_SIZE; + static constexpr int LAND_NUM_VERTS = LAND_SIZE * LAND_SIZE; - static const int HEIGHT_SCALE = 8; + static constexpr int HEIGHT_SCALE = 8; //number of textures per side of land - static const int LAND_TEXTURE_SIZE = 16; + static constexpr int LAND_TEXTURE_SIZE = 16; //total number of textures per land - static const int LAND_NUM_TEXTURES = LAND_TEXTURE_SIZE * LAND_TEXTURE_SIZE; + static constexpr int LAND_NUM_TEXTURES = LAND_TEXTURE_SIZE * LAND_TEXTURE_SIZE; - static const int LAND_GLOBAL_MAP_LOD_SIZE = 81; + static constexpr int LAND_GLOBAL_MAP_LOD_SIZE = 81; - static const int LAND_GLOBAL_MAP_LOD_SIZE_SQRT = 9; + static constexpr int LAND_GLOBAL_MAP_LOD_SIZE_SQRT = 9; #pragma pack(push,1) struct VHGT From 0193c95b269249711e6930b0536ecc6bbbbf056e Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 3 Jul 2021 17:39:34 +0200 Subject: [PATCH 50/57] Shrink to fit recast mesh data --- components/detournavigator/recastmesh.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/detournavigator/recastmesh.cpp b/components/detournavigator/recastmesh.cpp index 1a9982402b..00d6ae556a 100644 --- a/components/detournavigator/recastmesh.cpp +++ b/components/detournavigator/recastmesh.cpp @@ -19,5 +19,9 @@ namespace DetourNavigator + std::to_string(getTrianglesCount()) + ", areaTypes=" + std::to_string(mAreaTypes.size())); if (getVerticesCount()) rcCalcBounds(mVertices.data(), static_cast(getVerticesCount()), mBounds.mMin.ptr(), mBounds.mMax.ptr()); + mIndices.shrink_to_fit(); + mVertices.shrink_to_fit(); + mAreaTypes.shrink_to_fit(); + mWater.shrink_to_fit(); } } From 09f9075842da3b92afc00e7471996a4042368b10 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 3 Jul 2021 02:59:07 +0200 Subject: [PATCH 51/57] Use RecastMeshBuilder once to create RecastMesh This allows to move all data out of the object instead of copying. --- .../detournavigator/recastmeshbuilder.cpp | 32 +++++++++---------- .../detournavigator/recastmeshbuilder.cpp | 12 ++----- .../detournavigator/recastmeshbuilder.hpp | 4 +-- .../detournavigator/recastmeshmanager.cpp | 28 +++++++--------- .../detournavigator/recastmeshmanager.hpp | 9 +++--- 5 files changed, 36 insertions(+), 49 deletions(-) diff --git a/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp b/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp index b4b6645693..2624389b70 100644 --- a/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp +++ b/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp @@ -49,7 +49,7 @@ namespace TEST_F(DetourNavigatorRecastMeshBuilderTest, create_for_empty_should_return_empty) { RecastMeshBuilder builder(mSettings, mBounds); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector()); EXPECT_EQ(recastMesh->getIndices(), std::vector()); EXPECT_EQ(recastMesh->getAreaTypes(), std::vector()); @@ -63,7 +63,7 @@ namespace RecastMeshBuilder builder(mSettings, mBounds); builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 1, 0, -1, -1, 0, 1, @@ -84,7 +84,7 @@ namespace btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 2, 3, 0, 0, 3, 4, @@ -100,7 +100,7 @@ namespace btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false); RecastMeshBuilder builder(mSettings, mBounds); builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ -0.5, 0, -0.5, -0.5, 0, 0.5, @@ -116,7 +116,7 @@ namespace btBoxShape shape(btVector3(1, 1, 2)); RecastMeshBuilder builder(mSettings, mBounds); builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 1, 2, 1, -1, 2, 1, @@ -163,7 +163,7 @@ namespace btTransform::getIdentity(), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ -1, -2, -1, -1, -2, 1, @@ -210,7 +210,7 @@ namespace btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 2, 3, 0, 0, 3, 4, @@ -234,7 +234,7 @@ namespace btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 3, 12, 2, 1, 12, 10, @@ -256,7 +256,7 @@ namespace btTransform::getIdentity(), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 1, 0, -1, -1, 0, 1, @@ -284,7 +284,7 @@ namespace btTransform::getIdentity(), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ -0.2f, 0, -0.3f, -0.3f, 0, -0.2f, @@ -309,7 +309,7 @@ namespace static_cast(-osg::PI_4))), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_THAT(recastMesh->getVertices(), Pointwise(FloatNear(1e-5), std::vector({ 0, -0.70710659027099609375, -3.535533905029296875, 0, 0.707107067108154296875, -3.535533905029296875, @@ -334,7 +334,7 @@ namespace static_cast(osg::PI_4))), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_THAT(recastMesh->getVertices(), Pointwise(FloatNear(1e-5), std::vector({ -3.535533905029296875, -0.70710659027099609375, 0, -3.535533905029296875, 0.707107067108154296875, 0, @@ -359,7 +359,7 @@ namespace static_cast(osg::PI_4))), AreaType_ground ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_THAT(recastMesh->getVertices(), Pointwise(FloatNear(1e-5), std::vector({ 1.41421353816986083984375, 0, 1.1920928955078125e-07, -1.41421353816986083984375, 0, -1.1920928955078125e-07, @@ -388,7 +388,7 @@ namespace btTransform::getIdentity(), AreaType_null ); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 1, 0, -1, -1, 0, 1, @@ -405,7 +405,7 @@ namespace { RecastMeshBuilder builder(mSettings, mBounds); builder.addWater(1000, btTransform(btMatrix3x3::getIdentity(), btVector3(100, 200, 300))); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getWater(), std::vector({ RecastMesh::Water {1000, btTransform(btMatrix3x3::getIdentity(), btVector3(100, 200, 300))} })); @@ -420,7 +420,7 @@ namespace RecastMeshBuilder builder(mSettings, mBounds); builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground); - const auto recastMesh = builder.create(mGeneration, mRevision); + const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getVertices(), std::vector({ -1, 0, -1, -1, 0, 1, diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index 7e06c9229c..8ecbf1ec8e 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -152,19 +152,11 @@ namespace DetourNavigator mWater.push_back(RecastMesh::Water {cellSize, transform}); } - std::shared_ptr RecastMeshBuilder::create(std::size_t generation, std::size_t revision) + std::shared_ptr RecastMeshBuilder::create(std::size_t generation, std::size_t revision) && { optimizeRecastMesh(mIndices, mVertices); std::sort(mWater.begin(), mWater.end()); - return std::make_shared(generation, revision, mIndices, mVertices, mAreaTypes, mWater); - } - - void RecastMeshBuilder::reset() - { - mIndices.clear(); - mVertices.clear(); - mAreaTypes.clear(); - mWater.clear(); + return std::make_shared(generation, revision, std::move(mIndices), std::move(mVertices), std::move(mAreaTypes), std::move(mWater)); } void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform, diff --git a/components/detournavigator/recastmeshbuilder.hpp b/components/detournavigator/recastmeshbuilder.hpp index fc2bbbc02a..cb1b79377a 100644 --- a/components/detournavigator/recastmeshbuilder.hpp +++ b/components/detournavigator/recastmeshbuilder.hpp @@ -34,9 +34,7 @@ namespace DetourNavigator void addWater(const int mCellSize, const btTransform& transform); - std::shared_ptr create(std::size_t generation, std::size_t revision); - - void reset(); + std::shared_ptr create(std::size_t generation, std::size_t revision) &&; private: std::reference_wrapper mSettings; diff --git a/components/detournavigator/recastmeshmanager.cpp b/components/detournavigator/recastmeshmanager.cpp index e79d58de9d..e7afeb2848 100644 --- a/components/detournavigator/recastmeshmanager.cpp +++ b/components/detournavigator/recastmeshmanager.cpp @@ -1,10 +1,11 @@ #include "recastmeshmanager.hpp" +#include "recastmeshbuilder.hpp" namespace DetourNavigator { RecastMeshManager::RecastMeshManager(const Settings& settings, const TileBounds& bounds, std::size_t generation) - : mGeneration(generation) - , mMeshBuilder(settings, bounds) + : mSettings(settings) + , mGeneration(generation) , mTileBounds(bounds) { } @@ -74,8 +75,15 @@ namespace DetourNavigator std::shared_ptr RecastMeshManager::getMesh() { - rebuild(); - return mMeshBuilder.create(mGeneration, mRevision); + RecastMeshBuilder builder(mSettings, mTileBounds); + for (const auto& v : mWaterOrder) + builder.addWater(v.mCellSize, v.mTransform); + for (const auto& object : mObjectsOrder) + { + const RecastMeshObject& v = object.getImpl(); + builder.addObject(v.getShape(), v.getTransform(), v.getAreaType()); + } + return std::move(builder).create(mGeneration, mRevision); } bool RecastMeshManager::isEmpty() const @@ -99,16 +107,4 @@ namespace DetourNavigator { return Version {mGeneration, mRevision}; } - - void RecastMeshManager::rebuild() - { - mMeshBuilder.reset(); - for (const auto& v : mWaterOrder) - mMeshBuilder.addWater(v.mCellSize, v.mTransform); - for (const auto& object : mObjectsOrder) - { - const RecastMeshObject& v = object.getImpl(); - mMeshBuilder.addObject(v.getShape(), v.getTransform(), v.getAreaType()); - } - } } diff --git a/components/detournavigator/recastmeshmanager.hpp b/components/detournavigator/recastmeshmanager.hpp index 850865b95e..956170d3b4 100644 --- a/components/detournavigator/recastmeshmanager.hpp +++ b/components/detournavigator/recastmeshmanager.hpp @@ -1,7 +1,6 @@ #ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESHMANAGER_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESHMANAGER_H -#include "recastmeshbuilder.hpp" #include "oscillatingrecastmeshobject.hpp" #include "objectid.hpp" #include "version.hpp" @@ -13,11 +12,15 @@ #include #include #include +#include class btCollisionShape; namespace DetourNavigator { + struct Settings; + class RecastMesh; + struct RemovedRecastMeshObject { std::reference_wrapper mShape; @@ -61,9 +64,9 @@ namespace DetourNavigator Version mNavMeshVersion; }; + const Settings& mSettings; std::size_t mRevision = 0; std::size_t mGeneration; - RecastMeshBuilder mMeshBuilder; TileBounds mTileBounds; std::list mObjectsOrder; std::map::iterator> mObjects; @@ -71,8 +74,6 @@ namespace DetourNavigator std::map::iterator> mWater; std::optional mLastNavMeshReportedChange; std::optional mLastNavMeshReport; - - void rebuild(); }; } From e42b3bf960b4685ae29f220a7f7b5a1b8de188bd Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 4 Jul 2021 23:00:33 +0100 Subject: [PATCH 52/57] Adapt destination alpha factor for AMD As discussed in the comment, it's unclear to me whether this is a driver bug or mandatory behaviour only AMD implement. Some more context is here: https://gitlab.com/OpenMW/openmw/-/issues/6119#note_618245903 --- components/nifosg/nifloader.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index ab25fd744d..702ab33669 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -2011,6 +2011,11 @@ namespace NifOsg { osg::ref_ptr blendFunc (new osg::BlendFunc(getBlendMode((alphaprop->flags>>1)&0xf), getBlendMode((alphaprop->flags>>5)&0xf))); + // on AMD hardware, alpha still seems to be stored with an RGBA framebuffer with OpenGL. + // This might be mandated by the OpenGL 2.1 specification section 2.14.9, or might be a bug. + // Either way, D3D8.1 doesn't do that, so adapt the destination factor. + if (blendFunc->getDestination() == GL_DST_ALPHA) + blendFunc->setDestination(GL_ONE); blendFunc = shareAttribute(blendFunc); stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON); From c7c0d11cab9a27171659017bb3947442d31c9edc Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 5 Jul 2021 00:20:44 +0200 Subject: [PATCH 53/57] Trigger navmesh update when any navigator object has been updated Set World::mShouldUpdateNavigator to true when this happens. Previously assignment to true was missing for object rotation and moving. --- apps/openmw/mwworld/worldimp.cpp | 24 +++++++++++------------- apps/openmw/mwworld/worldimp.hpp | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 22520cecc0..14c7716f2e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1224,7 +1224,7 @@ namespace MWWorld if (movePhysics) { if (const auto object = mPhysics->getObject(ptr)) - updateNavigatorObject(object); + updateNavigatorObject(*object); } } @@ -1283,7 +1283,7 @@ namespace MWWorld if (mPhysics->getActor(ptr)) mNavigator->addAgent(getPathfindingHalfExtents(ptr)); else if (const auto object = mPhysics->getObject(ptr)) - mShouldUpdateNavigator = updateNavigatorObject(object) || mShouldUpdateNavigator; + updateNavigatorObject(*object); } void World::rotateObjectImp(const Ptr& ptr, const osg::Vec3f& rot, MWBase::RotationFlags flags) @@ -1332,7 +1332,7 @@ namespace MWWorld mWorldScene->updateObjectRotation(ptr, order); if (const auto object = mPhysics->getObject(ptr)) - updateNavigatorObject(object); + updateNavigatorObject(*object); } } @@ -1424,7 +1424,7 @@ namespace MWWorld mPhysics->updateRotation(ptr, rotate); if (const auto object = mPhysics->getObject(ptr)) - updateNavigatorObject(object); + updateNavigatorObject(*object); } } @@ -1544,14 +1544,11 @@ namespace MWWorld void World::updateNavigator() { - mPhysics->forEachAnimatedObject([&] (const MWPhysics::Object* object) - { - mShouldUpdateNavigator = updateNavigatorObject(object) || mShouldUpdateNavigator; - }); + mPhysics->forEachAnimatedObject([&] (const MWPhysics::Object* object) { updateNavigatorObject(*object); }); for (const auto& door : mDoorStates) if (const auto object = mPhysics->getObject(door.first)) - mShouldUpdateNavigator = updateNavigatorObject(object) || mShouldUpdateNavigator; + updateNavigatorObject(*object); if (mShouldUpdateNavigator) { @@ -1560,13 +1557,14 @@ namespace MWWorld } } - bool World::updateNavigatorObject(const MWPhysics::Object* object) + void World::updateNavigatorObject(const MWPhysics::Object& object) { const DetourNavigator::ObjectShapes shapes { - *object->getShapeInstance()->getCollisionShape(), - object->getShapeInstance()->getAvoidCollisionShape() + *object.getShapeInstance()->getCollisionShape(), + object.getShapeInstance()->getAvoidCollisionShape() }; - return mNavigator->updateObject(DetourNavigator::ObjectId(object), shapes, object->getTransform()); + mShouldUpdateNavigator = mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform()) + || mShouldUpdateNavigator; } const MWPhysics::RayCastingInterface* World::getRayCasting() const diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index c8f17109ec..2ed69aabdf 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -156,7 +156,7 @@ namespace MWWorld void updateNavigator(); - bool updateNavigatorObject(const MWPhysics::Object* object); + void updateNavigatorObject(const MWPhysics::Object& object); void ensureNeededRecords(); From 84a9facedf0bb6e49a78b85f73c89225bde4d994 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 4 Jul 2021 23:29:22 +0100 Subject: [PATCH 54/57] Disable coverage adjustment for blended objects --- components/sceneutil/mwshadowtechnique.cpp | 1 + components/shader/shadervisitor.cpp | 6 ++++++ files/shaders/alpha.glsl | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 9209532f7e..ad3fc5fd65 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -904,6 +904,7 @@ void SceneUtil::MWShadowTechnique::setupCastingShader(Shader::ShaderManager & sh program->addShader(castingVertexShader); program->addShader(shaderManager.getShader("shadowcasting_fragment.glsl", { {"alphaFunc", std::to_string(alphaFunc)}, {"alphaToCoverage", "0"}, + {"adjustCoverage", "1"}, {"useGPUShader4", useGPUShader4} }, osg::Shader::FRAGMENT)); } diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 9747d61acc..25dfa4af1e 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -482,6 +482,7 @@ namespace Shader removedState = new osg::StateSet(); defineMap["alphaToCoverage"] = "0"; + defineMap["adjustCoverage"] = "0"; if (reqs.mAlphaFunc != osg::AlphaFunc::ALWAYS) { writableStateSet->addUniform(new osg::Uniform("alphaRef", reqs.mAlphaRef)); @@ -505,6 +506,11 @@ namespace Shader defineMap["alphaToCoverage"] = "1"; } + // Adjusting coverage isn't safe with blending on as blending requires the alpha to be intact. + // Maybe we could also somehow (e.g. userdata) detect when the diffuse map has coverage-preserving mip maps in the future + if (!reqs.mAlphaBlend) + defineMap["adjustCoverage"] = "1"; + // Preventing alpha tested stuff shrinking as lower mip levels are used requires knowing the texture size osg::ref_ptr exts = osg::GLExtensions::Get(0, false); if (exts && exts->isGpuShader4Supported) diff --git a/files/shaders/alpha.glsl b/files/shaders/alpha.glsl index 05be801e93..46b748236c 100644 --- a/files/shaders/alpha.glsl +++ b/files/shaders/alpha.glsl @@ -22,7 +22,7 @@ float mipmapLevel(vec2 scaleduv) float coveragePreservingAlphaScale(sampler2D diffuseMap, vec2 uv) { - #if @alphaFunc != FUNC_ALWAYS && @alphaFunc != FUNC_NEVER + #if @adjustCoverage vec2 textureSize; #if @useGPUShader4 textureSize = textureSize2D(diffuseMap, 0); From e5e3f52e3eadac5e2189ea62530c8b1bd0c7c8d1 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Mon, 5 Jul 2021 10:23:01 +0200 Subject: [PATCH 55/57] Added changelog entry for #6067 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aef5a2be3b..268024e2ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Bug #5453: Magic effect VFX are offset for creatures Bug #5483: AutoCalc flag is not used to calculate spells cost Bug #6066: addtopic "return" does not work from within script. No errors thrown + Bug #6067: esp loader fails in for certain subrecord orders Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime Bug #6115: Showmap overzealous matching Bug #6129: Player avatar not displayed correctly for large window sizes when GUI scaling active From 7498a86abebf0eb9a039765833c06d424b93262a Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 5 Jul 2021 13:11:54 +0200 Subject: [PATCH 56/57] Remove redundant semicolons --- apps/benchmarks/detournavigator/navmeshtilescache.cpp | 2 +- apps/opencs/model/doc/runner.cpp | 2 +- apps/opencs/view/world/scriptsubview.cpp | 2 +- apps/openmw/mwstate/statemanagerimp.cpp | 2 +- extern/osg-ffmpeg-videoplayer/videostate.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/benchmarks/detournavigator/navmeshtilescache.cpp b/apps/benchmarks/detournavigator/navmeshtilescache.cpp index 2c7a981ad5..d39161fda2 100644 --- a/apps/benchmarks/detournavigator/navmeshtilescache.cpp +++ b/apps/benchmarks/detournavigator/navmeshtilescache.cpp @@ -69,7 +69,7 @@ namespace AreaType generateAreaType(Random& random) { std::uniform_int_distribution distribution(0, 4); - return toAreaType(distribution(random));; + return toAreaType(distribution(random)); } template diff --git a/apps/opencs/model/doc/runner.cpp b/apps/opencs/model/doc/runner.cpp index ccdff1444f..8dafbaf5ae 100644 --- a/apps/opencs/model/doc/runner.cpp +++ b/apps/opencs/model/doc/runner.cpp @@ -78,7 +78,7 @@ void CSMDoc::Runner::start (bool delayed) else arguments << "--new-game=1"; - arguments << ("--script-run="+mStartup->fileName());; + arguments << ("--script-run="+mStartup->fileName()); arguments << QString::fromUtf8 (("--data=\""+mProjectPath.parent_path().string()+"\"").c_str()); diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index 6eab7aaa53..6b07f2ea71 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -109,7 +109,7 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc: sizes << 1 << 0; mMain->setSizes (sizes); - QWidget *widget = new QWidget (this);; + QWidget *widget = new QWidget (this); widget->setLayout (&mLayout); setWidget (widget); diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index ffef9d74a9..b242862772 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -217,7 +217,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot profile.mTimePlayed = mTimePlayed; profile.mDescription = description; - Log(Debug::Info) << "Making a screenshot for saved game '" << description << "'";; + Log(Debug::Info) << "Making a screenshot for saved game '" << description << "'"; writeScreenshot(profile.mScreenshot); if (!slot) diff --git a/extern/osg-ffmpeg-videoplayer/videostate.cpp b/extern/osg-ffmpeg-videoplayer/videostate.cpp index 7b4060753e..7fcad33697 100644 --- a/extern/osg-ffmpeg-videoplayer/videostate.cpp +++ b/extern/osg-ffmpeg-videoplayer/videostate.cpp @@ -524,7 +524,7 @@ public: uint64_t seek_target = self->mSeekPos; int streamIndex = -1; - int videoStreamIndex = -1;; + int videoStreamIndex = -1; int audioStreamIndex = -1; if (self->video_st) videoStreamIndex = self->video_st - self->format_ctx->streams; From 625744298bafe02571b70b5f59729bb97f17914a Mon Sep 17 00:00:00 2001 From: Simon Meulenbeek Date: Mon, 5 Jul 2021 13:22:46 +0000 Subject: [PATCH 57/57] change setValue to replace value instead of insert --- CHANGELOG.md | 1 + components/config/settingsbase.hpp | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 268024e2ea..d671795004 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Bug #5379: Wandering NPCs falling through cantons Bug #5453: Magic effect VFX are offset for creatures Bug #5483: AutoCalc flag is not used to calculate spells cost + Bug #6037: Morrowind Content Language Cannot be Set to English in OpenMW Launcher Bug #6066: addtopic "return" does not work from within script. No errors thrown Bug #6067: esp loader fails in for certain subrecord orders Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime diff --git a/components/config/settingsbase.hpp b/components/config/settingsbase.hpp index 86fa962ae0..03ce9d3551 100644 --- a/components/config/settingsbase.hpp +++ b/components/config/settingsbase.hpp @@ -24,9 +24,7 @@ namespace Config inline void setValue(const QString &key, const QString &value) { - QStringList values = mSettings.values(key); - if (!values.contains(value)) - mSettings.insert(key, value); + mSettings.replace(key, value); } inline void setMultiValue(const QString &key, const QString &value)