From e3d63c65c1bdcf2056d94f934d07c1afa9211130 Mon Sep 17 00:00:00 2001 From: bicarus <202771338+bicarus-dev@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:52:13 -0800 Subject: [PATCH] overlay: fps window clean up (#506) ## Link to GitHub Issue, if one exists n/a ## Description of change Use fmt library for formatting time Round down sub-second units so that the FPS counter only updates once per second (instead of Time and Uptime ticking independently) clean up usage of `localtime` in `logging.cpp` --- src/spice2x/overlay/windows/fps.cpp | 24 +++++++++++++----------- src/spice2x/util/logging.cpp | 5 +++-- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/spice2x/overlay/windows/fps.cpp b/src/spice2x/overlay/windows/fps.cpp index 761f3b7..42e05cf 100644 --- a/src/spice2x/overlay/windows/fps.cpp +++ b/src/spice2x/overlay/windows/fps.cpp @@ -1,5 +1,6 @@ #include #include +#include "external/fmt/include/fmt/chrono.h" #include "fps.h" namespace overlay::windows { @@ -15,7 +16,8 @@ namespace overlay::windows { | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoDocking; this->bg_alpha = 0.5f; - this->start_time = std::chrono::system_clock::now(); + this->start_time = + std::chrono::floor(std::chrono::system_clock::now()); } void FPS::calculate_initial_window() { @@ -34,23 +36,23 @@ namespace overlay::windows { ImGui::Text("FPS: %.1f", io.Framerate); // ImGui::Text("FT: %.2fms", 1000 / io.Framerate); - auto now = std::chrono::system_clock::now(); + const auto now = std::chrono::system_clock::now(); + const auto now_s = std::chrono::floor(now); // current time { - auto now_t = std::chrono::system_clock::to_time_t(now); - static CHAR buf[48]; - std::strftime(buf, sizeof(buf), "Time: %H:%M:%S", std::localtime(&now_t)); - ImGui::Text(buf); + const std::time_t tt = std::chrono::system_clock::to_time_t(now_s); + std::tm local_tm{}; + localtime_s(&local_tm, &tt); + ImGui::TextUnformatted(fmt::format("Time: {:%H:%M:%S}", local_tm).c_str()); } // elapsed time { - auto d = now - this->start_time; - const auto h = std::chrono::duration_cast(d); - const auto m = std::chrono::duration_cast(d - h); - const auto s = std::chrono::duration_cast(d - h - m); - ImGui::Text("Up: %02d:%02d:%02d", (int)h.count(), (int)m.count(), (int)s.count()); + const auto uptime = now_s - this->start_time; + ImGui::TextUnformatted( + fmt::format("Up: {:%H:%M:%S}", + std::chrono::floor(uptime)).c_str()); } } } diff --git a/src/spice2x/util/logging.cpp b/src/spice2x/util/logging.cpp index 6d7e8ac..13a8f23 100644 --- a/src/spice2x/util/logging.cpp +++ b/src/spice2x/util/logging.cpp @@ -13,8 +13,9 @@ std::string_view log_get_datetime() { std::string_view log_get_datetime(std::time_t now) { static thread_local char buf[64]; - // `localtime` on Windows is thread-safe - strftime(buf, sizeof(buf), "[%Y/%m/%d %X]", localtime(&now)); + std::tm local_tm{}; + localtime_s(&local_tm, &now); + strftime(buf, sizeof(buf), "[%Y/%m/%d %X]", &local_tm); return buf; }