#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVMESHCACHEITEM_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_NAVMESHCACHEITEM_H #include "navmeshdata.hpp" #include "navmeshtilescache.hpp" #include "sharednavmesh.hpp" #include "tileposition.hpp" #include "version.hpp" #include #include #include struct dtMeshTile; namespace DetourNavigator { enum class UpdateNavMeshStatus : unsigned { ignored = 0, removed = 1 << 0, added = 1 << 1, replaced = removed | added, failed = 1 << 2, lost = removed | failed, cached = 1 << 3, unchanged = replaced | cached, restored = added | cached, }; inline bool isSuccess(UpdateNavMeshStatus value) { return (static_cast(value) & static_cast(UpdateNavMeshStatus::failed)) == 0; } std::ostream& operator<<(std::ostream& stream, UpdateNavMeshStatus value); class UpdateNavMeshStatusBuilder { public: UpdateNavMeshStatusBuilder() = default; explicit UpdateNavMeshStatusBuilder(UpdateNavMeshStatus value) : mResult(value) { } UpdateNavMeshStatusBuilder removed(bool value) { if (value) set(UpdateNavMeshStatus::removed); else unset(UpdateNavMeshStatus::removed); return *this; } UpdateNavMeshStatusBuilder added(bool value) { if (value) set(UpdateNavMeshStatus::added); else unset(UpdateNavMeshStatus::added); return *this; } UpdateNavMeshStatusBuilder failed(bool value) { if (value) set(UpdateNavMeshStatus::failed); else unset(UpdateNavMeshStatus::failed); return *this; } UpdateNavMeshStatusBuilder cached(bool value) { if (value) set(UpdateNavMeshStatus::cached); else unset(UpdateNavMeshStatus::cached); return *this; } UpdateNavMeshStatus getResult() const { return mResult; } private: UpdateNavMeshStatus mResult = UpdateNavMeshStatus::ignored; void set(UpdateNavMeshStatus value) { mResult = static_cast(static_cast(mResult) | static_cast(value)); } void unset(UpdateNavMeshStatus value) { mResult = static_cast(static_cast(mResult) & ~static_cast(value)); } }; const dtMeshTile* getTile(const dtNavMesh& navMesh, const TilePosition& position); class NavMeshCacheItem { public: NavMeshCacheItem(const NavMeshPtr& impl, std::size_t generation) : mImpl(impl) , mVersion{ generation, 0 } { } const dtNavMesh& getImpl() const { return *mImpl; } const Version& getVersion() const { return mVersion; } UpdateNavMeshStatus updateTile( const TilePosition& position, NavMeshTilesCache::Value&& cached, NavMeshData&& navMeshData); UpdateNavMeshStatus removeTile(const TilePosition& position); UpdateNavMeshStatus markAsEmpty(const TilePosition& position); bool isEmptyTile(const TilePosition& position) const; template void forEachUsedTile(Function&& function) const { for (const auto& [position, tile] : mUsedTiles) if (const dtMeshTile* meshTile = getTile(*mImpl, position)) function(position, tile.mVersion, *meshTile); } private: struct Tile { Version mVersion; NavMeshTilesCache::Value mCached; NavMeshData mData; }; NavMeshPtr mImpl; Version mVersion; std::map mUsedTiles; std::set mEmptyTiles; }; } #endif