Generalize UI: general status by default, diagnostics behind Debug details

Rework the spike-era debug readouts into general-purpose status, with the
verbose diagnostics gated behind the menu bar's "Debug details" switch:

- Controllers (was "Phase 0 spike"): always shows slot/source + live
  buttons; the raw stick/trigger numbers are debug-only.
- Injection hook status: general view is attached + focus spoof + a single
  "Game reading controller: N polls/s" summary; the per-slot poll table,
  focus-API counts, and input-path detection are debug-only.
- Audio: general view adds a "Buffered: N ms" health/latency proxy
  (AudioMirror now tracks buffered audio in both render paths) and keeps the
  render-stream count; the per-stream table is debug-only.

Default overlay is now clean general status; flip Debug details for the full
diagnostics. Completes the "generalize the UI" roadmap task. All tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-19 15:07:42 +02:00
parent b48cdd6515
commit d19974b17c
9 changed files with 79 additions and 31 deletions

View File

@@ -139,7 +139,7 @@ void InjectionPanel::publish(const std::array<PadInfo, kMaxPads>& pads)
server_.publish(synthetic);
}
void InjectionPanel::draw_hook_status()
void InjectionPanel::draw_hook_status(bool debug_details)
{
if (!server_.running())
{
@@ -170,13 +170,31 @@ void InjectionPanel::draw_hook_status()
return;
}
ImGui::TextColored(kGreen, "Attached (game pid %u, hwnd 0x%llX)", status.game_pid,
static_cast<unsigned long long>(status.game_hwnd));
ImGui::TextColored(kGreen, "Attached (game pid %u)", status.game_pid);
ImGui::TextColored(status.focus_spoof ? kGreen : kGrey, "Focus spoof: %s",
status.focus_spoof ? "active" : "inactive");
// Per-slot XInput polling: shows exactly which slots the game reads and how
// fast -- the requested visualization.
// General summary: is the game actually polling our pad, and how fast.
double total_rate = 0.0;
for (int i = 0; i < static_cast<int>(kMaxPads); ++i)
{
total_rate += state_rate_[i];
}
if (total_rate > 0.0)
{
ImGui::TextColored(kGreen, "Game reading controller: %.0f polls/s", total_rate);
}
else
{
ImGui::TextColored(kGrey, "Game reading controller: idle");
}
if (!debug_details)
{
return; // everything below is diagnostic detail
}
// Per-slot XInput polling: shows exactly which slots the game reads and how fast.
if (ImGui::BeginTable("slots", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchProp))
{
ImGui::TableSetupColumn("Slot");
@@ -233,7 +251,7 @@ void InjectionPanel::draw_hook_status()
status.dinput_loaded ? "yes (could be foreground-gated)" : "no");
}
void InjectionPanel::draw()
void InjectionPanel::draw(bool debug_details)
{
ImGui::SetNextWindowPos(ImVec2(24, 360), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(420, 380), ImGuiCond_FirstUseEver);
@@ -300,7 +318,7 @@ void InjectionPanel::draw()
ImGui::TextDisabled("(ignores your controller)");
}
draw_hook_status();
draw_hook_status(debug_details);
ImGui::End();
}