#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_DEBUG_H #include "tilebounds.hpp" #include #include #include #include #include #include #include #include #include class dtNavMesh; namespace DetourNavigator { inline std::ostream& operator <<(std::ostream& stream, const TileBounds& value) { return stream << "TileBounds {" << value.mMin << ", " << value.mMax << "}"; } class RecastMesh; class Log { public: Log() : mEnabled() { mFile.exceptions(std::ios::failbit | std::ios::badbit); } void setEnabled(bool value) { mEnabled = value; } bool isEnabled() const { return mEnabled; } void write(const std::string& text) { if (mEnabled) { const std::lock_guard lock(mMutex); if (!mFile.is_open()) { mFile.open("detournavigator.log"); } mFile << text << std::flush; } } static Log& instance() { static Log value; return value; } private: std::mutex mMutex; std::ofstream mFile; std::atomic_bool mEnabled; }; inline void write(std::ostream& stream) { stream << '\n'; } template void write(std::ostream& stream, const Head& head, const Tail& ... tail) { stream << head; write(stream, tail ...); } template void log(Ts&& ... values) { auto& log = Log::instance(); if (!log.isEnabled()) return; std::ostringstream stream; write(stream, std::forward(values) ...); log.write(stream.str()); } void writeToFile(const RecastMesh& recastMesh, const std::string& pathPrefix, const std::string& revision); void writeToFile(const dtNavMesh& navMesh, const std::string& pathPrefix, const std::string& revision); } #endif