// SPDX-FileCopyrightText: 2021 Jorrit Rouwe // SPDX-License-Identifier: MIT #include #include #include #include #include namespace JPH { #ifdef JPH_STAT_COLLECTOR StatCollector StatCollector::sInstance; string StatCollector::Variant::ToString() const { switch (mType) { case EType::Float: return ConvertToString(mFloat); case EType::Int: return ConvertToString(mInt); case EType::Bool: return ConvertToString(mBool); case EType::Undefined: default: JPH_ASSERT(false); return ""; } } void StatCollector::SetNextFrame() { lock_guard lock(mMutex); if (mIsCapturing) mCurrentFrame = &mFrames[mCurrentFrameNumber++]; } void StatCollector::ResetInternal() { mCurrentFrameNumber = 0; mCurrentFrame = nullptr; mFrames.clear(); mKeys.clear(); mNextKey = 0; } void StatCollector::Reset() { lock_guard lock(mMutex); ResetInternal(); } void StatCollector::StartCapture() { lock_guard lock(mMutex); ResetInternal(); mIsCapturing = true; } void StatCollector::AddItem(const string &inName, const Variant &inValue) { lock_guard lock(mMutex); JPH_ASSERT(mCurrentFrame != nullptr, "Don't forget to call SetFrame(...)"); // Determine key for inName pair p = mKeys.insert(KeyIDMap::value_type(inName, mNextKey)); // Increment key inName was new if (p.second) ++mNextKey; // Take key from map int key = p.first->second; // Store value (*mCurrentFrame)[key] = inValue; } void StatCollector::AddItem(const string &inName, Vec3Arg inValue) { AddItem(inName + ".X", inValue.GetX()); AddItem(inName + ".Y", inValue.GetY()); AddItem(inName + ".Z", inValue.GetZ()); } void StatCollector::AddItem(const string &inName, QuatArg inValue) { Vec3 axis; float angle; inValue.GetAxisAngle(axis, angle); AddItem(inName + ".Axis", axis); AddItem(inName + ".Angle", RadiansToDegrees(angle)); } struct StatTreeNode { using Children = map; int mIndex = -1; Children mChildren; }; static void sWriteStatTree(ofstream &ioStream, const StatTreeNode &inNode) { bool first = true; for (const StatTreeNode::Children::value_type &c : inNode.mChildren) { // Write comma if this is not the first line if (!first) ioStream << ","; first = false; // Write title ioStream << "{title:\"" + c.first + "\""; // Write key ioStream << ",key:\"" + ConvertToString(c.second.mIndex) + "\""; // Write children if (!c.second.mChildren.empty()) { ioStream << ",children:["; sWriteStatTree(ioStream, c.second); ioStream << "]"; } ioStream << "}"; } } void StatCollector::StopCapture(const char *inFileName) { lock_guard lock(mMutex); // Stop capturing mIsCapturing = false; // Open file ofstream f; f.open(inFileName, ofstream::out | ofstream::trunc); if (!f.is_open()) return; // Start html file f << R"( Stats

   

)-"; // Remove all collected data ResetInternal(); } #endif // JPH_STAT_COLLECTOR } // JPH