From 349040ffb20b6511f22f1388d33c0b42e572683d Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 28 Jan 2020 22:24:51 +0100 Subject: [PATCH] Use status codes to handle navigator errors instead of exceptions For find path use case. --- apps/openmw/mwmechanics/pathfinding.cpp | 58 +++++++------ .../detournavigator/navigator.cpp | 37 +++++---- components/detournavigator/debug.hpp | 20 +++++ .../findrandompointaroundcircle.cpp | 3 +- components/detournavigator/findsmoothpath.hpp | 81 +++++++++---------- components/detournavigator/navigator.hpp | 8 +- components/detournavigator/status.hpp | 43 ++++++++++ 7 files changed, 163 insertions(+), 87 deletions(-) create mode 100644 components/detournavigator/status.hpp diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index f8736c0629..a7bba5b63f 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -341,21 +341,23 @@ namespace MWMechanics const osg::Vec3f& endPoint, const osg::Vec3f& halfExtents, const DetourNavigator::Flags flags, std::back_insert_iterator> out) { - try + const auto world = MWBase::Environment::get().getWorld(); + const auto stepSize = getPathStepSize(actor); + const auto navigator = world->getNavigator(); + const auto status = navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out); + + if (status == DetourNavigator::Status::NavMeshNotFound) + return false; + + if (status != DetourNavigator::Status::Success) { - const auto world = MWBase::Environment::get().getWorld(); - const auto stepSize = getPathStepSize(actor); - const auto navigator = world->getNavigator(); - return navigator->findPath(halfExtents, stepSize, startPoint, endPoint, flags, out).is_initialized(); - } - catch (const DetourNavigator::NavigatorException& exception) - { - Log(Debug::Debug) << "Build path by navigator exception: \"" << exception.what() + Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status) << "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase() << ") from " << startPoint << " to " << endPoint << " with flags (" << DetourNavigator::WriteFlags {flags} << ")"; - return true; } + + return true; } void PathFinder::buildPathByNavMeshToNextPoint(const MWWorld::ConstPtr& actor, const osg::Vec3f& halfExtents, @@ -370,26 +372,30 @@ namespace MWMechanics if (sqrDistanceIgnoreZ(mPath.front(), startPoint) <= 4 * stepSize * stepSize) return; - try + const auto navigator = MWBase::Environment::get().getWorld()->getNavigator(); + std::deque prePath; + auto prePathInserter = std::back_inserter(prePath); + const auto status = navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags, + prePathInserter); + + if (status == DetourNavigator::Status::NavMeshNotFound) + return; + + if (status != DetourNavigator::Status::Success) { - const auto navigator = MWBase::Environment::get().getWorld()->getNavigator(); - std::deque prePath; - navigator->findPath(halfExtents, stepSize, startPoint, mPath.front(), flags, std::back_inserter(prePath)); - - while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.front(), startPoint) < stepSize * stepSize) - prePath.pop_front(); - - while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.back(), mPath.front()) < stepSize * stepSize) - prePath.pop_back(); - - std::copy(prePath.rbegin(), prePath.rend(), std::front_inserter(mPath)); - } - catch (const DetourNavigator::NavigatorException& exception) - { - Log(Debug::Debug) << "Build path by navigator exception: \"" << exception.what() + Log(Debug::Debug) << "Build path by navigator error: \"" << DetourNavigator::getMessage(status) << "\" for \"" << actor.getClass().getName(actor) << "\" (" << actor.getBase() << ") from " << startPoint << " to " << mPath.front() << " with flags (" << DetourNavigator::WriteFlags {flags} << ")"; + return; } + + while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.front(), startPoint) < stepSize * stepSize) + prePath.pop_front(); + + while (!prePath.empty() && sqrDistanceIgnoreZ(prePath.back(), mPath.front()) < stepSize * stepSize) + prePath.pop_back(); + + std::copy(prePath.rbegin(), prePath.rend(), std::front_inserter(mPath)); } } diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index f8aa8f535f..df8be37811 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -73,14 +73,16 @@ namespace TEST_F(DetourNavigatorNavigatorTest, find_path_for_empty_should_return_empty) { - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), + Status::NavMeshNotFound); EXPECT_EQ(mPath, std::deque()); } TEST_F(DetourNavigatorNavigatorTest, find_path_for_existing_agent_with_no_navmesh_should_throw_exception) { mNavigator->addAgent(mAgentHalfExtents); - EXPECT_THROW(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), NavigatorException); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), + Status::StartPolygonNotFound); } TEST_F(DetourNavigatorNavigatorTest, add_agent_should_count_each_agent) @@ -88,7 +90,8 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addAgent(mAgentHalfExtents); mNavigator->removeAgent(mAgentHalfExtents); - EXPECT_THROW(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), NavigatorException); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), + Status::StartPolygonNotFound); } TEST_F(DetourNavigatorNavigatorTest, update_then_find_path_should_return_path) @@ -108,7 +111,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(); - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(-215, 215, 1.85963428020477294921875), @@ -158,7 +161,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(); - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, std::back_inserter(mPath)); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(-215, 215, 1.85963428020477294921875), @@ -191,7 +194,8 @@ namespace mNavigator->wait(); mPath.clear(); - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, std::back_inserter(mPath)); + mOut = std::back_inserter(mPath); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(-215, 215, 1.87826788425445556640625), @@ -242,7 +246,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(); - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, std::back_inserter(mPath)); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(-215, 215, 1.87826788425445556640625), @@ -277,7 +281,8 @@ namespace mNavigator->wait(); mPath.clear(); - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut); + mOut = std::back_inserter(mPath); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(-215, 215, 1.85963428020477294921875), @@ -334,7 +339,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(); - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(-215, 215, 1.96328866481781005859375), @@ -390,7 +395,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(); - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(-215, 215, 1.9393787384033203125), @@ -443,7 +448,7 @@ namespace mEnd.x() = 0; mEnd.z() = 300; - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(0, 215, 185.33331298828125), @@ -489,7 +494,8 @@ namespace mStart.x() = 0; mEnd.x() = 0; - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut), + Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(0, 215, -94.75363922119140625), @@ -535,7 +541,8 @@ namespace mStart.x() = 0; mEnd.x() = 0; - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_swim | Flag_walk, mOut), + Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(0, 215, -94.75363922119140625), @@ -581,7 +588,7 @@ namespace mStart.x() = 0; mEnd.x() = 0; - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(0, 215, -94.75363922119140625), @@ -630,7 +637,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(); - mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut); + EXPECT_EQ(mNavigator->findPath(mAgentHalfExtents, mStepSize, mStart, mEnd, Flag_walk, mOut), Status::Success); EXPECT_EQ(mPath, std::deque({ osg::Vec3f(-215, 215, 1.85963428020477294921875), diff --git a/components/detournavigator/debug.hpp b/components/detournavigator/debug.hpp index 541680997f..a17eec16a7 100644 --- a/components/detournavigator/debug.hpp +++ b/components/detournavigator/debug.hpp @@ -2,6 +2,7 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_H #include "tilebounds.hpp" +#include "status.hpp" #include @@ -26,6 +27,25 @@ namespace DetourNavigator return stream << "TileBounds {" << value.mMin << ", " << value.mMax << "}"; } + inline std::ostream& operator <<(std::ostream& stream, Status value) + { +#define OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(name) \ + case Status::name: return stream << "DetourNavigator::Status::"#name; + switch (value) + { + OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(Success) + OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(NavMeshNotFound) + OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(StartPolygonNotFound) + OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(EndPolygonNotFound) + OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(MoveAlongSurfaceFailed) + OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(FindPathOverPolygonsFailed) + OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(GetPolyHeightFailed) + OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE(InitNavMeshQueryFailed) + } +#undef OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_STATUS_MESSAGE + return stream << "DetourNavigator::Error::" << static_cast(value); + } + class RecastMesh; void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix, const std::string& revision); diff --git a/components/detournavigator/findrandompointaroundcircle.cpp b/components/detournavigator/findrandompointaroundcircle.cpp index c894e6681c..3888c59feb 100644 --- a/components/detournavigator/findrandompointaroundcircle.cpp +++ b/components/detournavigator/findrandompointaroundcircle.cpp @@ -14,7 +14,8 @@ namespace DetourNavigator const osg::Vec3f& start, const float maxRadius, const Flags includeFlags, const Settings& settings) { dtNavMeshQuery navMeshQuery; - initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes); + if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes)) + return boost::optional(); dtQueryFilter queryFilter; queryFilter.setIncludeFlags(includeFlags); diff --git a/components/detournavigator/findsmoothpath.hpp b/components/detournavigator/findsmoothpath.hpp index e988dedb73..0f8f2c09a7 100644 --- a/components/detournavigator/findsmoothpath.hpp +++ b/components/detournavigator/findsmoothpath.hpp @@ -7,6 +7,7 @@ #include "settings.hpp" #include "settingsutils.hpp" #include "debug.hpp" +#include "status.hpp" #include #include @@ -97,11 +98,10 @@ namespace DetourNavigator std::reference_wrapper mSettings; }; - inline void initNavMeshQuery(dtNavMeshQuery& value, const dtNavMesh& navMesh, const int maxNodes) + inline bool initNavMeshQuery(dtNavMeshQuery& value, const dtNavMesh& navMesh, const int maxNodes) { const auto status = value.init(&navMesh, maxNodes); - if (!dtStatusSucceed(status)) - throw NavigatorException("Failed to init navmesh query"); + return dtStatusSucceed(status); } struct MoveAlongSurfaceResult @@ -110,8 +110,8 @@ namespace DetourNavigator std::vector mVisited; }; - inline MoveAlongSurfaceResult moveAlongSurface(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef, - const osg::Vec3f& startPos, const osg::Vec3f& endPos, const dtQueryFilter& filter, + inline boost::optional moveAlongSurface(const dtNavMeshQuery& navMeshQuery, + const dtPolyRef startRef, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const dtQueryFilter& filter, const std::size_t maxVisitedSize) { MoveAlongSurfaceResult result; @@ -120,18 +120,14 @@ namespace DetourNavigator const auto status = navMeshQuery.moveAlongSurface(startRef, startPos.ptr(), endPos.ptr(), &filter, result.mResultPos.ptr(), result.mVisited.data(), &visitedNumber, static_cast(maxVisitedSize)); if (!dtStatusSucceed(status)) - { - std::ostringstream message; - message << "Failed to move along surface from " << startPos << " to " << endPos; - throw NavigatorException(message.str()); - } + return {}; assert(visitedNumber >= 0); assert(visitedNumber <= static_cast(maxVisitedSize)); result.mVisited.resize(static_cast(visitedNumber)); - return result; + return {std::move(result)}; } - inline std::vector findPath(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef, + inline boost::optional> findPath(const dtNavMeshQuery& navMeshQuery, const dtPolyRef startRef, const dtPolyRef endRef, const osg::Vec3f& startPos, const osg::Vec3f& endPos, const dtQueryFilter& queryFilter, const std::size_t maxSize) { @@ -140,34 +136,26 @@ namespace DetourNavigator const auto status = navMeshQuery.findPath(startRef, endRef, startPos.ptr(), endPos.ptr(), &queryFilter, result.data(), &pathLen, static_cast(maxSize)); if (!dtStatusSucceed(status)) - { - std::ostringstream message; - message << "Failed to find path over polygons from " << startRef << " to " << endRef; - throw NavigatorException(message.str()); - } + return {}; assert(pathLen >= 0); assert(static_cast(pathLen) <= maxSize); result.resize(static_cast(pathLen)); - return result; + return {std::move(result)}; } - inline float getPolyHeight(const dtNavMeshQuery& navMeshQuery, const dtPolyRef ref, const osg::Vec3f& pos) + inline boost::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)) - { - std::ostringstream message; - message << "Failed to get polygon height ref=" << ref << " pos=" << pos; - throw NavigatorException(message.str()); - } + return {}; return result; } template - OutputIterator makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery, + Status makeSmoothPath(const dtNavMesh& navMesh, const dtNavMeshQuery& navMeshQuery, const dtQueryFilter& filter, const osg::Vec3f& start, const osg::Vec3f& end, const float stepSize, - std::vector polygonPath, std::size_t maxSmoothPathSize, OutputIterator out) + std::vector polygonPath, std::size_t maxSmoothPathSize, OutputIterator& out) { // Iterate over the path to find smooth path on the detail mesh surface. osg::Vec3f iterPos; @@ -207,12 +195,15 @@ namespace DetourNavigator const osg::Vec3f moveTgt = iterPos + delta * len; const auto result = moveAlongSurface(navMeshQuery, polygonPath.front(), iterPos, moveTgt, filter, 16); - polygonPath = fixupCorridor(polygonPath, result.mVisited); + if (!result) + return Status::MoveAlongSurfaceFailed; + + polygonPath = fixupCorridor(polygonPath, result->mVisited); polygonPath = fixupShortcuts(polygonPath, navMeshQuery); float h = 0; - navMeshQuery.getPolyHeight(polygonPath.front(), result.mResultPos.ptr(), &h); - iterPos = result.mResultPos; + 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. @@ -259,7 +250,12 @@ namespace DetourNavigator // Move position at the other side of the off-mesh link. iterPos = endPos; - iterPos.y() = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos); + const auto height = getPolyHeight(navMeshQuery, polygonPath.front(), iterPos); + + if (!height) + return Status::GetPolyHeightFailed; + + iterPos.y() = *height; } } @@ -268,16 +264,17 @@ namespace DetourNavigator ++smoothPathSize; } - return out; + return Status::Success; } template - OutputIterator findSmoothPath(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const float stepSize, + Status findSmoothPath(const dtNavMesh& navMesh, const osg::Vec3f& halfExtents, const float stepSize, const osg::Vec3f& start, const osg::Vec3f& end, const Flags includeFlags, - const Settings& settings, OutputIterator out) + const Settings& settings, OutputIterator& out) { dtNavMeshQuery navMeshQuery; - initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes); + if (!initNavMeshQuery(navMeshQuery, navMesh, settings.mMaxNavMeshQueryNodes)) + return Status::InitNavMeshQueryFailed; dtQueryFilter queryFilter; queryFilter.setIncludeFlags(includeFlags); @@ -293,7 +290,7 @@ namespace DetourNavigator } if (startRef == 0) - throw NavigatorException("Navmesh polygon for start point is not found"); + return Status::StartPolygonNotFound; dtPolyRef endRef = 0; osg::Vec3f endPolygonPosition; @@ -306,18 +303,20 @@ namespace DetourNavigator } if (endRef == 0) - throw NavigatorException("Navmesh polygon for end polygon is not found"); + return Status::EndPolygonNotFound; const auto polygonPath = findPath(navMeshQuery, startRef, endRef, start, end, queryFilter, settings.mMaxPolygonPathSize); - if (polygonPath.empty() || polygonPath.back() != endRef) - return out; + if (!polygonPath) + return Status::FindPathOverPolygonsFailed; - makeSmoothPath(navMesh, navMeshQuery, queryFilter, start, end, stepSize, std::move(polygonPath), - settings.mMaxSmoothPathSize, OutputTransformIterator(out, settings)); + if (polygonPath->empty() || polygonPath->back() != endRef) + return Status::Success; - return out; + auto outTransform = OutputTransformIterator(out, settings); + return makeSmoothPath(navMesh, navMeshQuery, queryFilter, start, end, stepSize, std::move(*polygonPath), + settings.mMaxSmoothPathSize, outTransform); } } diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 1b7af7e8b9..2265b1d39b 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -1,4 +1,4 @@ -#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H +#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVIGATOR_H #include "findsmoothpath.hpp" @@ -159,8 +159,8 @@ namespace DetourNavigator * Equal to out if no path is found. */ template - boost::optional findPath(const osg::Vec3f& agentHalfExtents, const float stepSize, const osg::Vec3f& start, - const osg::Vec3f& end, const Flags includeFlags, OutputIterator out) const + Status findPath(const osg::Vec3f& agentHalfExtents, const float stepSize, const osg::Vec3f& start, + const osg::Vec3f& end, const Flags includeFlags, OutputIterator& out) const { static_assert( std::is_same< @@ -171,7 +171,7 @@ namespace DetourNavigator ); const auto navMesh = getNavMesh(agentHalfExtents); if (!navMesh) - return {}; + return Status::NavMeshNotFound; const auto settings = getSettings(); return findSmoothPath(navMesh->lockConst()->getImpl(), toNavMeshCoordinates(settings, agentHalfExtents), toNavMeshCoordinates(settings, stepSize), toNavMeshCoordinates(settings, start), diff --git a/components/detournavigator/status.hpp b/components/detournavigator/status.hpp new file mode 100644 index 0000000000..3715489acc --- /dev/null +++ b/components/detournavigator/status.hpp @@ -0,0 +1,43 @@ +#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_STATUS_H +#define OPENMW_COMPONENTS_DETOURNAVIGATOR_STATUS_H + +namespace DetourNavigator +{ + enum class Status + { + Success, + NavMeshNotFound, + StartPolygonNotFound, + EndPolygonNotFound, + MoveAlongSurfaceFailed, + FindPathOverPolygonsFailed, + GetPolyHeightFailed, + InitNavMeshQueryFailed, + }; + + constexpr const char* getMessage(Status value) + { + switch (value) + { + case Status::Success: + return "success"; + case Status::NavMeshNotFound: + return "navmesh is not found"; + case Status::StartPolygonNotFound: + return "polygon for start position is not found on navmesh"; + case Status::EndPolygonNotFound: + return "polygon for end position is not found on navmesh"; + case Status::MoveAlongSurfaceFailed: + return "move along surface on navmesh is failed"; + case Status::FindPathOverPolygonsFailed: + return "path over navmesh polygons is not found"; + case Status::GetPolyHeightFailed: + return "failed to get polygon height"; + case Status::InitNavMeshQueryFailed: + return "failed to init navmesh query"; + } + return "unknown error"; + } +} + +#endif