"Forward synthetic test input" is a controller-debug aid, so it now lives in the Controllers panel (gated behind Debug details, disabled until the XInput hook is attached) instead of the Injection panel. ControllersPanel owns the flag and exposes test_input(); main feeds it into InjectionPanel::set_test_input each frame, so the existing synthetic-pad substitution in publish() is unchanged. Verified: x64 build green; review (default view no longer shows it in Injection; appears in Controllers under Debug details). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
70 lines
2.3 KiB
C++
70 lines
2.3 KiB
C++
// Controllers panel: the controller view of the pipeline. Shows what the host
|
|
// receives from Remote Play Together (the guest pads, via the input backend) and
|
|
// what the injected game actually reads back (per-slot XInput poll counts from the
|
|
// hook). This is how we verify RPT routes a guest's gamepad in and the game polls
|
|
// it out. The per-axis breakdown and per-slot poll table are debug-only.
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
#include "coop/protocol.hpp"
|
|
#include "input/input_source.hpp"
|
|
#include "ipc/ipc_server.hpp"
|
|
|
|
namespace coop
|
|
{
|
|
|
|
class ControllersPanel
|
|
{
|
|
public:
|
|
// `status` is the hook's back-channel (per-slot poll counters); `debug_details`
|
|
// reveals the raw axis values, the per-slot poll-rate table, and the synthetic
|
|
// test-input toggle.
|
|
void draw(const InputSource& input, const HookStatusView& status, bool debug_details);
|
|
|
|
// Whether the operator enabled "Forward synthetic test input" (a controller debug
|
|
// aid). The host feeds this to InjectionPanel, which substitutes a synthetic pad.
|
|
[[nodiscard]] bool test_input() const
|
|
{
|
|
return test_input_;
|
|
}
|
|
|
|
#ifdef COOP_WITH_STEAM
|
|
// Whether the operator has opted into Steam Input. It's off by default: simply
|
|
// initializing Steam Input activates Steam's in-process XInput interception,
|
|
// which hides controllers from XInput unless they're bound to our action set for
|
|
// this app -- so it can silently break the (working) XInput path. main reconciles
|
|
// this against the actual backend each frame.
|
|
[[nodiscard]] bool steam_input_requested() const
|
|
{
|
|
return steam_requested_;
|
|
}
|
|
void set_steam_active(bool active)
|
|
{
|
|
steam_active_ = active;
|
|
}
|
|
void on_steam_init_failed()
|
|
{
|
|
steam_requested_ = false;
|
|
steam_active_ = false;
|
|
steam_note_ = "Steam Input failed to start; using XInput.";
|
|
}
|
|
#endif
|
|
|
|
private:
|
|
bool test_input_ = false; // "Forward synthetic test input" (debug aid, default off)
|
|
|
|
// Sampled to turn the hook's cumulative per-slot counters into poll rates.
|
|
unsigned long long last_state_count_[kMaxPads] = {};
|
|
double state_rate_[kMaxPads] = {};
|
|
double last_sample_time_ = 0.0;
|
|
|
|
#ifdef COOP_WITH_STEAM
|
|
bool steam_requested_ = false; // operator opted into Steam Input (default off)
|
|
bool steam_active_ = false; // Steam Input actually initialized
|
|
const char* steam_note_ = "";
|
|
#endif
|
|
};
|
|
|
|
} // namespace coop
|