Skip to main content

ADR-019: Steam Input for Gamepad Support

Status

Accepted

Context

The catnet VR overlay system requires gamepad input support for navigation and interaction. We initially used the gilrs library for cross-platform gamepad support, which worked well but had limitations:

  1. Platform Inconsistencies: Different behavior across Windows, Linux, and Steam Deck
  2. Limited Controller Support: Some controllers weren't properly detected or mapped
  3. No Action System: Raw button/axis mapping required manual configuration
  4. Steam Integration: No native integration with Steam's controller configuration UI

Steam Input offers several advantages:

  • Unified input across all Steam-supported controllers
  • User-customizable bindings through Steam's UI
  • Action-based system instead of raw button mapping
  • Built-in support for haptics and advanced features
  • Automatic controller type detection and appropriate glyphs

However, Steam Input has one major limitation: it requires a valid Steam App ID to function properly. During development with Spacewar's test App ID (480), the action system doesn't work.

Decision

We will implement Steam Input as the primary gamepad backend using the steamworks crate, with gilrs as an automatic fallback option.

Implementation Details

  1. Dual Backend Support

    • Steam Input via steamworks = "0.11" crate (feature-gated)
    • Gilrs via gilrs = "0.10" as default/fallback
    • Both implement the same InputSource trait
  2. Automatic Fallback

    • InputManager::add_gamepad_auto() attempts Steam Input first
    • Falls back to gilrs if Steam is unavailable or not initialized
    • Manual selection possible via add_steam_input() or add_gamepad()
  3. Action Configuration

    • Steam Input actions defined in steam_input_actions.vdf
    • Two action sets: ship_controls and menu_controls
    • Maps to existing ButtonId/AxisId enums for compatibility
  4. Development Workflow

    • Use gilrs during development (works immediately)
    • Test Steam Input with detection examples
    • Full Steam Input activated once real App ID is available

Consequences

Positive

  • Better User Experience: Players can configure controls through familiar Steam UI
  • Broader Controller Support: Any controller Steam supports works automatically
  • Future-Proof: Ready for Steam release without code changes
  • Maintains Compatibility: Gilrs fallback ensures non-Steam users aren't affected

Negative

  • Development Complexity: Can't fully test Steam Input during development
  • Additional Dependency: Requires steamworks crate and Steam client
  • Configuration Files: Must maintain steam_input_actions.vdf manifest

Neutral

  • Feature Flag: Steam Input is optional via steam-input feature
  • No Breaking Changes: Existing InputSource trait unchanged
  • Testing Strategy: Multiple test binaries for different scenarios

Implementation Notes

The implementation is complete and merged. Key files:

  • crates/vr-input/src/steam_input/ - Full implementation
  • steam_input_actions.vdf - Action manifest (IGA format)
  • steam_appid.txt - Contains development App ID
  • Multiple test examples in crates/examples/src/bin/input/

Once the project has a real Steam App ID, update steam_appid.txt and Steam Input will become fully functional. Until then, gilrs provides reliable gamepad support for development and testing.