Persist ImGui panel layout to disk; quiet audio set_audio_ring log spam
Layout persistence: re-enable io.IniFilename (was nullptr "for the spike"), anchored to a coop_layout.ini next to the exe so window positions/sizes survive restarts even when Steam launches us under the donor appid (CWD is unreliable). Path is UTF-8 for ImGui's file IO. When a saved layout is restored at startup, suppress the computed-default force so it does not clobber the user's positions; Reset layout (and a fresh install with no .ini) still applies the default. Log spam: the worker thread re-attaches every audio ring every tick (idempotent), and set_audio_ring logged unconditionally, flooding the log. Only log when the ring pointer actually changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -600,9 +600,14 @@ void set_audio_ring(unsigned index, AudioRingHeader* ring)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_rings[index].store(ring, std::memory_order_release);
|
// The worker thread re-attaches every tick (idempotent); only log when the ring
|
||||||
logf("set_audio_ring: index=%u ring=%p capture_enabled=%u", index, ring,
|
// pointer actually changes so the log isn't flooded with identical lines.
|
||||||
ring ? ring->capture_enabled.load(std::memory_order_relaxed) : 0u);
|
AudioRingHeader* const prev = g_rings[index].exchange(ring, std::memory_order_acq_rel);
|
||||||
|
if (prev != ring)
|
||||||
|
{
|
||||||
|
logf("set_audio_ring: index=%u ring=%p capture_enabled=%u", index, ring,
|
||||||
|
ring ? ring->capture_enabled.load(std::memory_order_relaxed) : 0u);
|
||||||
|
}
|
||||||
// The stream may already be registered (game was playing before we injected and
|
// The stream may already be registered (game was playing before we injected and
|
||||||
// before the host created the ring); publish its format so the host stops waiting
|
// before the host created the ring); publish its format so the host stops waiting
|
||||||
// and consumes the ring instead of falling back to loopback.
|
// and consumes the ring instead of falling back to loopback.
|
||||||
|
|||||||
@@ -1,12 +1,34 @@
|
|||||||
#include "imgui_layer.hpp"
|
#include "imgui_layer.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_impl_dx11.h>
|
#include <imgui_impl_dx11.h>
|
||||||
#include <imgui_impl_win32.h>
|
#include <imgui_impl_win32.h>
|
||||||
|
|
||||||
|
#include "coop/tool_paths.hpp"
|
||||||
|
#include "ui/app_chrome.hpp"
|
||||||
|
|
||||||
namespace coop
|
namespace coop
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// ImGui's file IO treats IniFilename as UTF-8 (it converts to wide for _wfopen), so
|
||||||
|
// the path must be UTF-8 rather than the system ANSI code page.
|
||||||
|
std::string to_utf8(const std::wstring& w)
|
||||||
|
{
|
||||||
|
if (w.empty())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const int n = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), static_cast<int>(w.size()), nullptr, 0, nullptr, nullptr);
|
||||||
|
std::string s(static_cast<std::size_t>(n), '\0');
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, w.c_str(), static_cast<int>(w.size()), s.data(), n, nullptr, nullptr);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
ImGuiLayer::~ImGuiLayer()
|
ImGuiLayer::~ImGuiLayer()
|
||||||
{
|
{
|
||||||
if (initialized_)
|
if (initialized_)
|
||||||
@@ -23,7 +45,15 @@ bool ImGuiLayer::init(HWND hwnd, ID3D11Device* device, ID3D11DeviceContext* cont
|
|||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.IniFilename = nullptr; // don't litter the cwd with imgui.ini during the spike
|
// Persist the panel layout next to the executable so window positions/sizes survive
|
||||||
|
// restarts. CWD is unreliable when Steam launches us under the donor appid, so anchor
|
||||||
|
// to the exe directory. If a layout already exists, tell the chrome not to force the
|
||||||
|
// computed default on startup (which would clobber the restored positions).
|
||||||
|
const std::wstring ini_w = exe_directory() + L"coop_layout.ini";
|
||||||
|
const bool had_layout = GetFileAttributesW(ini_w.c_str()) != INVALID_FILE_ATTRIBUTES;
|
||||||
|
ini_path_ = to_utf8(ini_w);
|
||||||
|
io.IniFilename = ini_path_.c_str();
|
||||||
|
set_layout_persisted(had_layout);
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
if (!ImGui_ImplWin32_Init(hwnd))
|
if (!ImGui_ImplWin32_Init(hwnd))
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// Owns ImGui setup/teardown for the Win32 + DX11 backends.
|
// Owns ImGui setup/teardown for the Win32 + DX11 backends.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
@@ -22,6 +24,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
|
// Backing storage for io.IniFilename (ImGui keeps the pointer, not a copy), so the
|
||||||
|
// layout .ini path must outlive the context. Empty until init() sets it.
|
||||||
|
std::string ini_path_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace coop
|
} // namespace coop
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ bool g_layout_reset = false;
|
|||||||
// WorkSize isn't trustworthy on frame 0, and FirstUseEver would otherwise lock in
|
// WorkSize isn't trustworthy on frame 0, and FirstUseEver would otherwise lock in
|
||||||
// those wrong positions (overlapping) until the user pressed Reset layout.
|
// those wrong positions (overlapping) until the user pressed Reset layout.
|
||||||
int g_startup_force = 4;
|
int g_startup_force = 4;
|
||||||
|
// True when ImGui loaded a saved layout (.ini) at startup; then the startup force is
|
||||||
|
// suppressed so the restored window positions survive (Reset layout still re-applies).
|
||||||
|
bool g_had_persisted_layout = false;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void request_layout_reset()
|
void request_layout_reset()
|
||||||
@@ -24,6 +27,11 @@ void request_layout_reset()
|
|||||||
g_layout_reset = true;
|
g_layout_reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_layout_persisted(bool had_persisted_layout)
|
||||||
|
{
|
||||||
|
g_had_persisted_layout = had_persisted_layout;
|
||||||
|
}
|
||||||
|
|
||||||
void apply_layout_end_frame()
|
void apply_layout_end_frame()
|
||||||
{
|
{
|
||||||
g_layout_reset = false;
|
g_layout_reset = false;
|
||||||
@@ -87,7 +95,11 @@ void apply_panel_layout(Panel panel)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImGuiCond cond = (g_layout_reset || g_startup_force > 0) ? ImGuiCond_Always : ImGuiCond_FirstUseEver;
|
// Force the computed layout only when the user asks (Reset layout) or on a fresh
|
||||||
|
// install with no saved layout to restore. Otherwise FirstUseEver lets ImGui's
|
||||||
|
// restored .ini positions stand (and still seeds any brand-new panel).
|
||||||
|
const bool force = g_layout_reset || (!g_had_persisted_layout && g_startup_force > 0);
|
||||||
|
const ImGuiCond cond = force ? ImGuiCond_Always : ImGuiCond_FirstUseEver;
|
||||||
ImGui::SetNextWindowPos(pos, cond);
|
ImGui::SetNextWindowPos(pos, cond);
|
||||||
ImGui::SetNextWindowSize(size, cond);
|
ImGui::SetNextWindowSize(size, cond);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ void apply_panel_layout(Panel panel);
|
|||||||
void request_layout_reset();
|
void request_layout_reset();
|
||||||
void apply_layout_end_frame();
|
void apply_layout_end_frame();
|
||||||
|
|
||||||
|
// Tell the layout whether ImGui restored a saved layout (.ini) at startup. When it
|
||||||
|
// did, the computed default layout must NOT be force-applied on launch (that would
|
||||||
|
// clobber the user's saved window positions); only an explicit Reset layout re-applies.
|
||||||
|
void set_layout_persisted(bool had_persisted_layout);
|
||||||
|
|
||||||
// Rolling frame-timing over a ~1 s window, recomputed each window so the status
|
// Rolling frame-timing over a ~1 s window, recomputed each window so the status
|
||||||
// bar can show a stable FPS plus the min/max frame time (jitter) underneath it.
|
// bar can show a stable FPS plus the min/max frame time (jitter) underneath it.
|
||||||
class FrameStats
|
class FrameStats
|
||||||
|
|||||||
Reference in New Issue
Block a user