Steam Input as the primary guest-input path (optional, SDK-gated)
Add SteamInputSource: initializes SteamAPI + Steam Input, loads a bundled action manifest via SetInputActionManifestFilePath (no partner-backend config needed), and reads the GameControls action set into CoopPadState -- falling back to XInput per slot, and to pure XInput if Steam isn't available, so the host always runs. Enabled automatically when the Steamworks SDK is vendored at third_party/steamworks_sdk/ (auto-detected by CMake; gitignored and never committed -- the build is XInput-only without it). Stages steam_api64.dll + the manifest next to the host and builds coop_steam_input_probe (a console smoke test). Verified: the probe initializes against the live Steam client and enumerates controllers; the host degrades gracefully when launched standalone. All 5 tests pass. Reading actual controller state needs a pad bound through Steam Input for the running (donor) appid, which XInput otherwise covers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
59
tools/steam_input_probe/main.cpp
Normal file
59
tools/steam_input_probe/main.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
// coop_steam_input_probe -- console smoke test for SteamInputSource. Brings up
|
||||
// Steam Input via the shipping host code (no GUI), prints whether it initialized,
|
||||
// how many Steam controllers are connected, and a few polled snapshots, then
|
||||
// exits. Needs Steam running and an appid context: either launch it under Steam,
|
||||
// or drop a steam_appid.txt (e.g. "480") next to the exe. Built only when the
|
||||
// Steamworks SDK is vendored.
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "input/steam_input_source.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string manifest_path()
|
||||
{
|
||||
char buffer[MAX_PATH] = {};
|
||||
const DWORD len = GetModuleFileNameA(nullptr, buffer, MAX_PATH);
|
||||
std::string path(buffer, len);
|
||||
const std::size_t slash = path.find_last_of("\\/");
|
||||
if (slash != std::string::npos)
|
||||
{
|
||||
path.resize(slash + 1);
|
||||
}
|
||||
return path + "steam_input_actions.vdf";
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
coop::SteamInputSource src;
|
||||
const bool ok = src.init(manifest_path());
|
||||
std::printf("init=%d steam_active=%d backend=\"%s\"\n", ok ? 1 : 0, src.steam_active() ? 1 : 0,
|
||||
src.name());
|
||||
|
||||
for (int frame = 0; frame < 20; ++frame)
|
||||
{
|
||||
src.poll();
|
||||
Sleep(50);
|
||||
}
|
||||
|
||||
std::printf("steam_controllers=%d\n", src.steam_controllers());
|
||||
const auto& pads = src.pads();
|
||||
for (std::uint32_t i = 0; i < coop::kMaxPads; ++i)
|
||||
{
|
||||
const coop::PadInfo& p = pads[i];
|
||||
if (p.connected)
|
||||
{
|
||||
std::printf(" slot %u: source=\"%s\" buttons=0x%04X LX=%d LY=%d LT=%u RT=%u\n", i,
|
||||
p.source.c_str(), p.state.buttons, p.state.thumb_lx, p.state.thumb_ly,
|
||||
p.state.left_trigger, p.state.right_trigger);
|
||||
}
|
||||
}
|
||||
|
||||
src.shutdown();
|
||||
std::printf("done.\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user