From d0ea9c482a9a489ae9b0b4dd93a0c0d1d73db4f6 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 14 May 2021 19:57:11 +0200 Subject: [PATCH 1/2] Reorder async navmesh updater jobs when player tile changes When player tile changes distance to player that is part of jobs priority is invalidated. So jobs are no longer in the right order. This can lead to processing of farests tiles first. Sort queue each time player tile is changed. --- .../detournavigator/asyncnavmeshupdater.cpp | 38 ++++++++++++++----- .../detournavigator/asyncnavmeshupdater.hpp | 7 ++-- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index ff51e39aa..3f7114b85 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -88,13 +88,22 @@ namespace DetourNavigator const SharedNavMeshCacheItem& navMeshCacheItem, const TilePosition& playerTile, const std::map& changedTiles) { - *mPlayerTile.lock() = playerTile; + bool playerTileChanged = false; + { + auto locked = mPlayerTile.lock(); + playerTileChanged = *locked != playerTile; + *locked = playerTile; + } - if (changedTiles.empty()) + if (!playerTileChanged && changedTiles.empty()) return; const std::lock_guard lock(mMutex); + if (playerTileChanged) + for (auto& job : mJobs) + job.mDistanceToPlayer = getManhattanDistance(job.mChangedTile, playerTile); + for (const auto& changedTile : changedTiles) { if (mPushed[agentHalfExtents].insert(changedTile.first).second) @@ -112,10 +121,21 @@ namespace DetourNavigator ? mLastUpdates[job.mAgentHalfExtents][job.mChangedTile] + mSettings.get().mMinUpdateInterval : std::chrono::steady_clock::time_point(); - mJobs.push(std::move(job)); + if (playerTileChanged) + { + mJobs.push_back(std::move(job)); + } + else + { + const auto it = std::upper_bound(mJobs.begin(), mJobs.end(), job); + mJobs.insert(it, std::move(job)); + } } } + if (playerTileChanged) + std::sort(mJobs.begin(), mJobs.end()); + Log(Debug::Debug) << "Posted " << mJobs.size() << " navigator jobs"; if (!mJobs.empty()) @@ -283,7 +303,7 @@ namespace DetourNavigator while (true) { const auto hasJob = [&] { - return (!mJobs.empty() && mJobs.top().mProcessTime <= std::chrono::steady_clock::now()) + return (!mJobs.empty() && mJobs.front().mProcessTime <= std::chrono::steady_clock::now()) || !threadQueue.mJobs.empty(); }; @@ -318,11 +338,11 @@ namespace DetourNavigator { const auto now = std::chrono::steady_clock::now(); - if (jobs.top().mProcessTime > now) + if (jobs.front().mProcessTime > now) return {}; - Job job = jobs.top(); - jobs.pop(); + Job job = jobs.front(); + jobs.pop_front(); if (changeLastUpdate && job.mChangeType == ChangeType::update) mLastUpdates[job.mAgentHalfExtents][job.mChangedTile] = now; @@ -376,7 +396,7 @@ namespace DetourNavigator if (mPushed[job.mAgentHalfExtents].insert(job.mChangedTile).second) { ++job.mTryNumber; - mJobs.push(std::move(job)); + mJobs.push_back(std::move(job)); mHasJob.notify_all(); } } @@ -385,7 +405,7 @@ namespace DetourNavigator { if (queue.mPushed[job.mAgentHalfExtents].insert(job.mChangedTile).second) { - queue.mJobs.push(std::move(job)); + queue.mJobs.push_back(std::move(job)); mHasJob.notify_all(); } } diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index c28d8f21d..fb9532519 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -14,9 +14,10 @@ #include #include #include -#include +#include #include #include +#include class dtNavMesh; @@ -83,11 +84,11 @@ namespace DetourNavigator friend inline bool operator <(const Job& lhs, const Job& rhs) { - return lhs.getPriority() > rhs.getPriority(); + return lhs.getPriority() < rhs.getPriority(); } }; - using Jobs = std::priority_queue>; + using Jobs = std::deque; using Pushed = std::map>; struct Queue From 59f89d22f8e586c63be961b5606041e22c506ea7 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 14 May 2021 21:06:29 +0200 Subject: [PATCH 2/2] Apply min distance only for not present tiles To avoid waiting when navmesh update is triggered by transformed object for already present tiles. --- apps/openmw/mwworld/scene.cpp | 4 +- .../detournavigator/navigator.cpp | 44 ++++++++--------- .../detournavigator/asyncnavmeshupdater.cpp | 49 +++++++++++++++---- .../detournavigator/asyncnavmeshupdater.hpp | 8 ++- components/detournavigator/navigator.hpp | 6 ++- components/detournavigator/navigatorimpl.cpp | 4 +- components/detournavigator/navigatorimpl.hpp | 2 +- components/detournavigator/navigatorstub.hpp | 2 +- components/detournavigator/navmeshmanager.cpp | 5 +- components/detournavigator/navmeshmanager.hpp | 3 +- .../detournavigator/waitconditiontype.hpp | 13 +++++ 11 files changed, 95 insertions(+), 45 deletions(-) create mode 100644 components/detournavigator/waitconditiontype.hpp diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 23525dea8..83e9805f6 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -619,7 +619,7 @@ namespace MWWorld if (changeEvent) mCellChanged = true; - mNavigator.wait(*loadingListener); + mNavigator.wait(*loadingListener, DetourNavigator::WaitConditionType::requiredTilesPresent); } void Scene::testExteriorCells() @@ -848,7 +848,7 @@ namespace MWWorld MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); - mNavigator.wait(*loadingListener); + mNavigator.wait(*loadingListener, DetourNavigator::WaitConditionType::requiredTilesPresent); } void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index cb8ae4152..41671993d 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -127,7 +127,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::requiredTilesPresent); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); @@ -177,7 +177,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); @@ -209,7 +209,7 @@ namespace mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); mPath.clear(); mOut = std::back_inserter(mPath); @@ -262,7 +262,7 @@ namespace mNavigator->addObject(ObjectId(&heightfieldShape), heightfieldShape, btTransform::getIdentity()); mNavigator->addObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); @@ -296,7 +296,7 @@ namespace mNavigator->updateObject(ObjectId(&compoundShape), compoundShape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); mPath.clear(); mOut = std::back_inserter(mPath); @@ -355,7 +355,7 @@ namespace mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->addObject(ObjectId(&shape2), shape2, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); @@ -411,7 +411,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addObject(ObjectId(&shape), ObjectShapes {shape, &shapeAvoid}, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); @@ -459,7 +459,7 @@ namespace mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, 300, btTransform::getIdentity()); mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); mStart.x() = 0; mStart.z() = 300; @@ -507,7 +507,7 @@ namespace mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, -25, btTransform::getIdentity()); mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); mStart.x() = 0; mEnd.x() = 0; @@ -554,7 +554,7 @@ namespace mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->addWater(osg::Vec2i(0, 0), std::numeric_limits::max(), -25, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); mStart.x() = 0; mEnd.x() = 0; @@ -601,7 +601,7 @@ namespace mNavigator->addWater(osg::Vec2i(0, 0), 128 * 4, -25, btTransform::getIdentity()); mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); mStart.x() = 0; mEnd.x() = 0; @@ -645,15 +645,15 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); mNavigator->removeObject(ObjectId(&shape)); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); @@ -699,7 +699,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); Misc::Rng::init(42); @@ -748,7 +748,7 @@ namespace } mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mAreaCosts, mOut), Status::Success); @@ -791,7 +791,7 @@ namespace mNavigator->addObject(ObjectId(&shapes[i]), shapes[i], transform); } mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); const auto start = std::chrono::steady_clock::now(); for (std::size_t i = 0; i < shapes.size(); ++i) @@ -800,7 +800,7 @@ namespace mNavigator->updateObject(ObjectId(&shapes[i]), shapes[i], transform); } mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); for (std::size_t i = 0; i < shapes.size(); ++i) { @@ -808,7 +808,7 @@ namespace mNavigator->updateObject(ObjectId(&shapes[i]), shapes[i], transform); } mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); const auto duration = std::chrono::steady_clock::now() - start; @@ -831,7 +831,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addObject(ObjectId(&shape), shape, btTransform::getIdentity()); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); const auto result = mNavigator->raycast(mAgentHalfExtents, mStart, mEnd, Flag_walk); @@ -862,7 +862,7 @@ namespace mNavigator->addObject(ObjectId(&boderBoxShape), boderBoxShape, btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition + btVector3(0, 0, 200))); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); const auto navMeshes = mNavigator->getNavMeshes(); ASSERT_EQ(navMeshes.size(), 1); @@ -878,7 +878,7 @@ namespace oscillatingBoxShapePosition); mNavigator->updateObject(ObjectId(&oscillatingBoxShape), oscillatingBoxShape, transform); mNavigator->update(mPlayerPosition); - mNavigator->wait(mListener); + mNavigator->wait(mListener, WaitConditionType::allJobsDone); } ASSERT_EQ(navMeshes.size(), 1); diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 3f7114b85..bee4510b4 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -10,7 +10,9 @@ #include +#include #include +#include namespace { @@ -23,12 +25,14 @@ namespace } int getMinDistanceTo(const TilePosition& position, int maxDistance, - const std::map>& tilesPerHalfExtents) + const std::map>& tilesPerHalfExtents, + const std::set>& presentTiles) { int result = maxDistance; for (const auto& [halfExtents, tiles] : tilesPerHalfExtents) for (const TilePosition& tile : tiles) - result = std::min(result, getManhattanDistance(position, tile)); + if (presentTiles.find(std::make_tuple(halfExtents, tile)) == presentTiles.end()) + result = std::min(result, getManhattanDistance(position, tile)); return result; } } @@ -142,7 +146,7 @@ namespace DetourNavigator mHasJob.notify_all(); } - void AsyncNavMeshUpdater::wait(Loading::Listener& listener) + void AsyncNavMeshUpdater::wait(Loading::Listener& listener, WaitConditionType waitConditionType) { if (mSettings.get().mWaitUntilMinDistanceToPlayer == 0) return; @@ -150,15 +154,26 @@ namespace DetourNavigator const std::size_t initialJobsLeft = getTotalJobs(); std::size_t maxProgress = initialJobsLeft + mThreads.size(); listener.setProgressRange(maxProgress); - const int minDistanceToPlayer = waitUntilJobsDone(initialJobsLeft, maxProgress, listener); - if (minDistanceToPlayer < mSettings.get().mWaitUntilMinDistanceToPlayer) + switch (waitConditionType) { - mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); }); - listener.setProgress(maxProgress); + case WaitConditionType::requiredTilesPresent: + { + const int minDistanceToPlayer = waitUntilJobsDoneForNotPresentTiles(initialJobsLeft, maxProgress, listener); + if (minDistanceToPlayer < mSettings.get().mWaitUntilMinDistanceToPlayer) + { + mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); }); + listener.setProgress(maxProgress); + } + break; + } + case WaitConditionType::allJobsDone: + waitUntilAllJobsDone(); + listener.setProgress(maxProgress); + break; } } - int AsyncNavMeshUpdater::waitUntilJobsDone(const std::size_t initialJobsLeft, std::size_t& maxProgress, Loading::Listener& listener) + int AsyncNavMeshUpdater::waitUntilJobsDoneForNotPresentTiles(const std::size_t initialJobsLeft, std::size_t& maxProgress, Loading::Listener& listener) { std::size_t prevJobsLeft = initialJobsLeft; std::size_t jobsDone = 0; @@ -174,9 +189,9 @@ namespace DetourNavigator minDistanceToPlayer = 0; return true; } - minDistanceToPlayer = getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed); + minDistanceToPlayer = getMinDistanceTo(playerPosition, maxDistanceToPlayer, mPushed, mPresentTiles); for (const auto& [threadId, queue] : mThreadsQueues) - minDistanceToPlayer = getMinDistanceTo(playerPosition, minDistanceToPlayer, queue.mPushed); + minDistanceToPlayer = getMinDistanceTo(playerPosition, minDistanceToPlayer, queue.mPushed, mPresentTiles); return minDistanceToPlayer >= maxDistanceToPlayer; }; std::unique_lock lock(mMutex); @@ -199,6 +214,15 @@ namespace DetourNavigator return minDistanceToPlayer; } + void AsyncNavMeshUpdater::waitUntilAllJobsDone() + { + { + std::unique_lock lock(mMutex); + mDone.wait(lock, [this] { return mJobs.size() + getTotalThreadJobsUnsafe() == 0; }); + } + mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); }); + } + void AsyncNavMeshUpdater::reportStats(unsigned int frameNumber, osg::Stats& stats) const { std::size_t jobs = 0; @@ -273,6 +297,11 @@ namespace DetourNavigator navMeshVersion); } + if (status == UpdateNavMeshStatus::removed || status == UpdateNavMeshStatus::lost) + mPresentTiles.erase(std::make_tuple(job.mAgentHalfExtents, job.mChangedTile)); + else if (isSuccess(status) && status != UpdateNavMeshStatus::ignored) + mPresentTiles.insert(std::make_tuple(job.mAgentHalfExtents, job.mChangedTile)); + const auto finish = std::chrono::steady_clock::now(); writeDebugFiles(job, recastMesh.get()); diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index fb9532519..e8b2611e9 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -6,6 +6,7 @@ #include "tilecachedrecastmeshmanager.hpp" #include "tileposition.hpp" #include "navmeshtilescache.hpp" +#include "waitconditiontype.hpp" #include @@ -61,7 +62,7 @@ namespace DetourNavigator void post(const osg::Vec3f& agentHalfExtents, const SharedNavMeshCacheItem& mNavMeshCacheItem, const TilePosition& playerTile, const std::map& changedTiles); - void wait(Loading::Listener& listener); + void wait(Loading::Listener& listener, WaitConditionType waitConditionType); void reportStats(unsigned int frameNumber, osg::Stats& stats) const; @@ -114,6 +115,7 @@ namespace DetourNavigator NavMeshTilesCache mNavMeshTilesCache; Misc::ScopeGuarded>> mProcessingTiles; std::map> mLastUpdates; + std::set> mPresentTiles; std::map mThreadsQueues; std::vector mThreads; @@ -143,7 +145,9 @@ namespace DetourNavigator void cleanupLastUpdates(); - int waitUntilJobsDone(const std::size_t initialJobsLeft, std::size_t& maxJobsLeft, Loading::Listener& listener); + int waitUntilJobsDoneForNotPresentTiles(const std::size_t initialJobsLeft, std::size_t& maxJobsLeft, Loading::Listener& listener); + + void waitUntilAllJobsDone(); }; } diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 3ec5e5acc..8cf4cb80e 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -7,6 +7,7 @@ #include "objectid.hpp" #include "navmeshcacheitem.hpp" #include "recastmeshtiles.hpp" +#include "waitconditiontype.hpp" namespace ESM { @@ -165,9 +166,10 @@ namespace DetourNavigator virtual void setUpdatesEnabled(bool enabled) = 0; /** - * @brief wait locks thread until all tiles are updated from last update call. + * @brief wait locks thread until tiles are updated from last update call based on passed condition type. + * @param waitConditionType defines when waiting will stop */ - virtual void wait(Loading::Listener& listener) = 0; + virtual void wait(Loading::Listener& listener, WaitConditionType waitConditionType) = 0; /** * @brief findPath fills output iterator with points of scene surfaces to be used for actor to walk through. diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index d1e75b864..1d02ba266 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -153,9 +153,9 @@ namespace DetourNavigator mUpdatesEnabled = enabled; } - void NavigatorImpl::wait(Loading::Listener& listener) + void NavigatorImpl::wait(Loading::Listener& listener, WaitConditionType waitConditionType) { - mNavMeshManager.wait(listener); + mNavMeshManager.wait(listener, waitConditionType); } SharedNavMeshCacheItem NavigatorImpl::getNavMesh(const osg::Vec3f& agentHalfExtents) const diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp index a53c9608d..324946261 100644 --- a/components/detournavigator/navigatorimpl.hpp +++ b/components/detournavigator/navigatorimpl.hpp @@ -48,7 +48,7 @@ namespace DetourNavigator void setUpdatesEnabled(bool enabled) override; - void wait(Loading::Listener& listener) override; + void wait(Loading::Listener& listener, WaitConditionType waitConditionType) override; SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const override; diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp index c21db2bf8..2c12c45eb 100644 --- a/components/detournavigator/navigatorstub.hpp +++ b/components/detournavigator/navigatorstub.hpp @@ -73,7 +73,7 @@ namespace DetourNavigator void setUpdatesEnabled(bool /*enabled*/) override {} - void wait(Loading::Listener& /*listener*/) override {} + void wait(Loading::Listener& /*listener*/, WaitConditionType /*waitConditionType*/) override {} SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& /*agentHalfExtents*/) const override { diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index 71a4def4f..8f1aa86d4 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -5,6 +5,7 @@ #include "makenavmesh.hpp" #include "navmeshcacheitem.hpp" #include "settings.hpp" +#include "waitconditiontype.hpp" #include @@ -190,9 +191,9 @@ namespace DetourNavigator " recastMeshManagerRevision=" << lastRevision; } - void NavMeshManager::wait(Loading::Listener& listener) + void NavMeshManager::wait(Loading::Listener& listener, WaitConditionType waitConditionType) { - mAsyncNavMeshUpdater.wait(listener); + mAsyncNavMeshUpdater.wait(listener, waitConditionType); } SharedNavMeshCacheItem NavMeshManager::getNavMesh(const osg::Vec3f& agentHalfExtents) const diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index ce90aafc5..a38e221a7 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -6,6 +6,7 @@ #include "offmeshconnectionsmanager.hpp" #include "sharednavmesh.hpp" #include "recastmeshtiles.hpp" +#include "waitconditiontype.hpp" #include @@ -45,7 +46,7 @@ namespace DetourNavigator void update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents); - void wait(Loading::Listener& listener); + void wait(Loading::Listener& listener, WaitConditionType waitConditionType); SharedNavMeshCacheItem getNavMesh(const osg::Vec3f& agentHalfExtents) const; diff --git a/components/detournavigator/waitconditiontype.hpp b/components/detournavigator/waitconditiontype.hpp new file mode 100644 index 000000000..06a590128 --- /dev/null +++ b/components/detournavigator/waitconditiontype.hpp @@ -0,0 +1,13 @@ +#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_WAITCONDITIONTYPE_H +#define OPENMW_COMPONENTS_DETOURNAVIGATOR_WAITCONDITIONTYPE_H + +namespace DetourNavigator +{ + enum class WaitConditionType + { + requiredTilesPresent, + allJobsDone, + }; +} + +#endif