Commit Graph

9 Commits

Author SHA1 Message Date
699ca31d31 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>
2026-06-21 23:59:03 +02:00
4121ad4373 Move input polling to its own thread; fixed-width fast-changing UI numbers
Input thread: controller polling, pad publishing, and rumble forwarding were
driven by the render loop, so a low/synced frame rate throttled how often guest
input reached the game. New InputWorker owns the InputSource and runs poll +
IPC publish + rumble on a dedicated ~1 kHz thread, independent of rendering. The
UI thread reads a copy-safe InputSnapshot for the Controllers panel and relays the
Steam-Input request/active/failed state to/from the worker (Steam init/shutdown now
happen on the worker thread). IpcServer gained a mutex so the worker's publish() /
hook_status() can't race the UI thread starting/stopping the shared-memory channel
(use-after-unmap); InjectionPanel::test_input_ is now atomic. ControllersPanel::draw
takes an InputSnapshot instead of the live InputSource.

Fixed-width numbers: fast-changing readouts (menu-bar FPS/ms, Video pipeline rates +
latency + graph legend, controller poll rates + round-trip sticks, audio buffered ms
+ frames/s) printed with %.0f etc., so they shifted/blurred as values crossed digit
thresholds (99 -> 100) each frame. Padded them to fixed field widths so they stay put.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 12:51:00 +02:00
22b0dff918 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>
2026-06-21 11:24:23 +02:00
86905a1f35 Tune center-column heights; note RawInput/DirectInput MKB + DX12 cost as future work
- Center stack heights set to Controllers 45% / Video 32% / Audio 23% (measured from
  the operator's preferred layout): Controllers has the most content, Audio the least.
- Future work: MKB forwarding for Raw Input / DirectInput games (the message +
  polling-state path doesn't reach them -- e.g. Trails through Daybreak uses Raw
  Input), and reducing the D3D11On12 (DX12) per-frame capture overhead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 11:05:52 +02:00
1493ce08e5 Rebalance overlay layout and fix the layout-on-launch overlap
Feedback from real use: the center column was far too wide and Injection/Log too
narrow; Audio was too tall while Controllers/Video were too short; and the layout
overlapped on launch until "Reset layout" was pressed.

- Columns are now proportional: Injection (left) and Log (right) take 36% each of the
  usable width, the center control column 28% -- so the wide panels are wide and the
  control panels narrow.
- The center stack heights are evened out (Controllers 30% / Video 38% / Audio 32% of
  the column), so Audio no longer hogs it.
- The default layout is now forced (ImGuiCond_Always) for the first few frames after
  launch, because the viewport WorkSize isn't trustworthy on frame 0 -- FirstUseEver
  was locking in those wrong (overlapping) positions until a manual Reset layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 10:41:58 +02:00
9f5b7c3272 Release the operator cursor for cursor-clipping games
Games that ClipCursor / re-center via SetCursorPos while focused trap the operator's
mouse (the focus spoof makes them think they're always focused), so the operator
can't reach the overlay. The Focus subsystem now inline-hooks ClipCursor and
SetCursorPos (stdcall trampolines): while "release" is requested it forces
ClipCursor(NULL) and swallows the re-centering SetCursorPos; otherwise it passes them
through. It frees any existing clip at install and re-frees each worker tick (covers
one-time clippers and a runtime clip->release toggle).

Host: protocol v10->v11 adds HookControl::allow_cursor_clip (0 = release, the
default). The Injection panel gets a "Release operator cursor" checkbox and an F2
hotkey (InjectionPanel::toggle_cursor_release); default released, since the guest
plays via the pad so the game's clip is operator-only.

Verified: full build x64 + x86 clean; ctest x64 9/9, x86 3/3. The cursor behavior
against a real clipping game (Trails through Daybreak) needs a live injected session
to confirm; logic reviewed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 05:20:17 +02:00
37d0f64e23 Lay out the overlay panels in a fixed 3-column scheme
Panels used to Begin at cascade positions, so they overlapped and clipped. A new
apply_panel_layout() in app_chrome positions/sizes each panel from the main
viewport work area (ImGuiCond_FirstUseEver, still movable): Injection left column
full height (room for hook diagnostics), Controllers/Video/Audio stacked in the
center column, Log right edge full height (max room for the log stream). Added a
"View -> Reset layout" menu item (request_layout_reset / apply_layout_end_frame
re-apply the defaults once via ImGuiCond_Always). Each panel now calls
apply_panel_layout(Panel::X) instead of its own ad-hoc SetNextWindowPos/Size.

Verified live: captured the host overlay -- Injection (left, full height),
Controllers/Video/Audio (center stack), Log (right, full height), no overlap among
the panels. x64 build + ctest green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 01:19:45 +02:00
9557b9ca69 Log window: stream the hook's logs over IPC into an in-app Log panel
Add a shared log ring (common/coop/log_ring.hpp): a lossy multi-producer /
single-consumer ring named coop_log_<pid>. The hook logs from several threads,
so producers claim a slot with fetch_add and publish each record with a
release store of its sequence; the consumer reads in order and tolerates
losing the oldest lines if it falls a whole ring behind.

The DLL's logf() now formats once and pushes every line to the ring (the file
trace stays as an opt-in mirror); the worker attaches the ring right after IPC
connect so bring-up is captured. The host (IpcServer) creates the ring at
injection time and exposes drain_logs(); a new LogPanel pulls new lines each
frame into a bounded rolling buffer and renders them with auto-scroll, a
filter, and clear. Added to the View menu (and UiState.show_log).

Verified against Phantom Brave via coop_audio_probe, which now also creates the
ring and drains it: the full hook bring-up trace streamed over IPC. All four
tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 20:25:04 +02:00
b48cdd6515 Generalize UI: main menu bar with panel toggles + frame stats
Add a top menu bar (host/src/ui/app_chrome) as the overlay shell:
- View menu toggles each panel (Controllers / Injection / Video / Audio)
  and a global "Debug details" switch (consumed by panels in a follow-up).
- A right-aligned performance readout: stable 1 s FPS plus the frame-time
  spread (avg, min-max) so stutter is visible; it turns amber on a >25 ms
  spike. FrameStats keeps the rolling window.

Consolidates the FPS that was duplicated in the controllers and video
panels into this one readout.

First structural step of the "generalize the UI" roadmap task; content
rework (debug-vs-general split, renaming the spike-era readouts) follows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:03:50 +02:00