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 3b389dd7d8..2022503dec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,21 @@ 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 #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 + Bug #6107: Fatigue is incorrectly recalculated when fortify effect is applied or removed + 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 Task #6017: Separate persistent and temporary cell references when saving + 0.47.0 ------ @@ -140,6 +150,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/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 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/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/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/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/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; 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); } } } 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/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 967504552d..d6e948d685 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. @@ -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/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/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..1407d6a0d5 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()) @@ -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/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/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); 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/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/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) 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/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 87f462d6ff..160cac0dc9 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); @@ -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()) @@ -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)) 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/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()) { 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/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); } } 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..e790f21413 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); @@ -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..ed28c0a463 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. @@ -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/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/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 987f2c6603..0ada08d3fb 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -167,7 +168,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(); } @@ -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); }; } 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/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..034a35f38e 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) @@ -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..1eb1fd419a 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); @@ -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/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/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/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/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()); } } }; 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/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/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/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/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/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..fec8ca77b0 100644 --- a/apps/openmw/mwworld/cellvisitors.hpp +++ b/apps/openmw/mwworld/cellvisitors.hpp @@ -13,17 +13,28 @@ namespace MWWorld { std::vector mObjects; - bool operator() (MWWorld::Ptr ptr) + bool operator() (const MWWorld::Ptr& ptr) { 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/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/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/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/store.cpp b/apps/openmw/mwworld/store.cpp index 944d311229..2ed051a141 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 //========================================================================= @@ -1072,7 +1084,7 @@ namespace MWWorld else { found->second.loadData(esm, isDeleted); - dialogue = found->second; + dialogue.mId = found->second.mId; } return RecordId(dialogue.mId, isDeleted); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 611e535c88..14c7716f2e 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)) { @@ -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); } } @@ -1421,10 +1421,10 @@ 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); + 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 @@ -2552,7 +2550,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 @@ -3836,7 +3841,7 @@ namespace MWWorld struct ResetActorsVisitor { - bool operator() (Ptr ptr) + bool operator() (const Ptr& ptr) { if (ptr.getClass().isActor() && ptr.getCellRef().hasContentFile()) { 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(); 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/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/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/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/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/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/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); 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) 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/findsmoothpath.cpp b/components/detournavigator/findsmoothpath.cpp index 8974be5321..6598263398 100644 --- a/components/detournavigator/findsmoothpath.cpp +++ b/components/detournavigator/findsmoothpath.cpp @@ -1,5 +1,7 @@ #include "findsmoothpath.hpp" +#include + #include #include @@ -103,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. @@ -113,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; @@ -125,7 +130,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..db2219b2cd 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -14,9 +14,8 @@ #include #include -#include - #include + #include #include @@ -26,10 +25,9 @@ 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 (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); @@ -143,15 +141,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, @@ -201,13 +190,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 +199,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; @@ -249,16 +233,18 @@ 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(); } } + if (dtStatusFailed(navMeshQuery.getPolyHeight(polygonPath.front(), result->mResultPos.ptr(), &iterPos.y()))) + return Status::GetPolyHeightFailed; + iterPos.x() = result->mResultPos.x(); + iterPos.z() = result->mResultPos.z(); + // Store results. *out++ = iterPos; ++smoothPathSize; 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; 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/detournavigator/offmeshconnectionsmanager.cpp b/components/detournavigator/offmeshconnectionsmanager.cpp new file mode 100644 index 0000000000..a673ae3e68 --- /dev/null +++ b/components/detournavigator/offmeshconnectionsmanager.cpp @@ -0,0 +1,95 @@ +#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); + }); + + 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; + } + + 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) + { + if (getTilePosition(mSettings, v.second.mStart) == tilePosition + || getTilePosition(mSettings, v.second.mEnd) == tilePosition) + 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 1ad96e3b97..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,73 +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 @@ -99,14 +35,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); - } }; } 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(); } } 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 bfc0409a51..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 @@ -83,7 +91,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; @@ -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 5922821f26..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; @@ -50,7 +53,7 @@ namespace DetourNavigator bool isEmpty() const; - void reportNavMeshChange(Version recastMeshVersion, Version navMeshVersion); + void reportNavMeshChange(const Version& recastMeshVersion, const Version& navMeshVersion); Version getVersion() const; @@ -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(); }; } 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) 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; diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 7d924d9c90..dbe5828289 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -72,10 +72,7 @@ void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted, int *tempRefCount) 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(); @@ -162,12 +159,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) diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index e3e6a4f335..a30ad2c069 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() @@ -315,7 +300,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; @@ -328,19 +313,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 ea18014b77..6129147d33 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); + [[noreturn]] 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; } 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 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 { 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/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/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index b4739110f7..487b7bd70b 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -75,64 +75,59 @@ 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 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; - 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 - 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)); } - 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/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/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/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/misc/stringops.hpp b/components/misc/stringops.hpp index 48deaa9991..2a865606fd 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; @@ -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); @@ -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) 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/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); 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); 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/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) { 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/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 88d44d2f69..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)); } @@ -1996,7 +1997,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..9b4fb9d3fb 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; @@ -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..f297c42d2e 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -58,9 +58,9 @@ 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); + 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/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; 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; 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) diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index e8ac7d9c36..25dfa4af1e 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) @@ -38,11 +100,6 @@ namespace Shader { } - ShaderVisitor::ShaderRequirements::~ShaderRequirements() - { - - } - ShaderVisitor::ShaderVisitor(ShaderManager& shaderManager, Resource::ImageManager& imageManager, const std::string &defaultShaderPrefix) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) , mForceShaders(false) @@ -105,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" }; @@ -280,10 +355,14 @@ namespace Shader osg::StateSet::AttributeList removedAttributes; if (osg::ref_ptr removedState = getRemovedState(*stateset)) removedAttributes = removedState->getAttributeList(); - for (const auto& attributeMap : { attributes, removedAttributes }) + 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) + for (osg::StateSet::AttributeList::const_iterator it = attributeMap->begin(); it != attributeMap->end(); ++it) { + if (addedState && attributeMap != &removedAttributes && addedState->hasAttribute(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 @@ -294,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()) { @@ -374,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,23 +482,35 @@ 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)); + addedState->addUniform("alphaRef"); - 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 && !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"; } + // 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) @@ -425,10 +518,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 +536,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 +559,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 +581,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); } } 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; 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; + } } } 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--; 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; 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);