Persist the "Debug details" toggle in the layout .ini

The View-menu verbosity switch reset to off on every launch. Register a
custom ImGui settings handler (a [CoopUI][State] section in coop_layout.ini,
alongside the window layout) so the operator's choice survives restarts.
Toggling it marks settings dirty so ImGui's auto-save writes it back.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 23:59:03 +02:00
parent 7264cb2ef4
commit 699ca31d31
3 changed files with 68 additions and 1 deletions

View File

@@ -2,14 +2,51 @@
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "imgui.h"
#include "imgui_internal.h" // ImGuiSettingsHandler / AddSettingsHandler (custom .ini section)
namespace coop
{
namespace
{
// --- Custom .ini persistence for the UI switches ---------------------------
// We piggy-back on ImGui's .ini so the "Debug details" verbosity survives restarts
// without inventing a separate settings file. The section looks like:
// [CoopUI][State]
// DebugDetails=1
// ImGui calls ReadOpenFn once per "[CoopUI][<name>]" entry; we return the bound
// UiState* as the entry handle so ReadLineFn can write into it.
constexpr const char* kUiSettingsType = "CoopUI";
void* ui_settings_read_open(ImGuiContext*, ImGuiSettingsHandler* handler, const char* name)
{
// Only one entry ("State"); hand back the UiState* so ReadLineFn can fill it.
return std::strcmp(name, "State") == 0 ? handler->UserData : nullptr;
}
void ui_settings_read_line(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line)
{
auto* ui = static_cast<UiState*>(entry);
// Manual parse (avoids the sscanf CRT-secure deprecation for a single int key).
constexpr char kKey[] = "DebugDetails=";
if (std::strncmp(line, kKey, sizeof(kKey) - 1) == 0)
{
ui->debug_details = std::atoi(line + sizeof(kKey) - 1) != 0;
}
}
void ui_settings_write_all(ImGuiContext*, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
{
const auto* ui = static_cast<const UiState*>(handler->UserData);
buf->appendf("[%s][State]\n", kUiSettingsType);
buf->appendf("DebugDetails=%d\n", ui->debug_details ? 1 : 0);
buf->append("\n");
}
// Set by "View -> Reset layout"; true for the one frame in which panels re-apply
// their default position/size, then cleared by apply_layout_end_frame().
bool g_layout_reset = false;
@@ -22,6 +59,23 @@ int g_startup_force = 4;
bool g_had_persisted_layout = false;
} // namespace
void register_ui_settings(UiState& ui)
{
// Idempotent: don't stack a second handler if this is somehow called twice.
if (ImGui::FindSettingsHandler(kUiSettingsType) != nullptr)
{
return;
}
ImGuiSettingsHandler handler;
handler.TypeName = kUiSettingsType;
handler.TypeHash = ImHashStr(kUiSettingsType);
handler.ReadOpenFn = ui_settings_read_open;
handler.ReadLineFn = ui_settings_read_line;
handler.WriteAllFn = ui_settings_write_all;
handler.UserData = &ui;
ImGui::AddSettingsHandler(&handler); // copied into the context
}
void request_layout_reset()
{
g_layout_reset = true;
@@ -123,7 +177,10 @@ float draw_main_menu_bar(UiState& ui, const FrameStats& stats)
ImGui::MenuItem("Audio mirror", nullptr, &ui.show_audio);
ImGui::MenuItem("Log", nullptr, &ui.show_log);
ImGui::Separator();
ImGui::MenuItem("Debug details", nullptr, &ui.debug_details);
if (ImGui::MenuItem("Debug details", nullptr, &ui.debug_details))
{
ImGui::MarkIniSettingsDirty(); // persist the new verbosity to coop_layout.ini
}
if (ImGui::MenuItem("Reset layout"))
{
request_layout_reset();