VisualPinball.NativeInput 0.0.2

dotnet add package VisualPinball.NativeInput --version 0.0.2
                    
NuGet\Install-Package VisualPinball.NativeInput -Version 0.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="VisualPinball.NativeInput" Version="0.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="VisualPinball.NativeInput" Version="0.0.2" />
                    
Directory.Packages.props
<PackageReference Include="VisualPinball.NativeInput" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add VisualPinball.NativeInput --version 0.0.2
                    
#r "nuget: VisualPinball.NativeInput, 0.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package VisualPinball.NativeInput@0.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=VisualPinball.NativeInput&version=0.0.2
                    
Install as a Cake Addin
#tool nuget:?package=VisualPinball.NativeInput&version=0.0.2
                    
Install as a Cake Tool

VPE Native Input Polling

High-performance native input polling library for Visual Pinball Engine.

Purpose

Provides OS-level input polling to achieve sub-millisecond input latency by bypassing Unity's Input System buffer. The input polling runs on a dedicated thread at 500-2000 Hz and forwards events to the simulation thread via a callback.

Architecture

┌─────────────────────────────────────┐
│   OS Input Events (Keyboard/HID)    │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  Native Input Polling Thread        │
│  (500-2000 Hz)                      │
├─────────────────────────────────────┤
│  • GetAsyncKeyState (Windows)       │
│  • X11 key polling (Linux)          │
│  • CoreGraphics/AppKit (macOS)      │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  Lock-Free SPSC Ring Buffer         │
└─────────────────────────────────────┘
              ↓
┌─────────────────────────────────────┐
│  Simulation Thread (1000 Hz)        │
└─────────────────────────────────────┘

Building

Windows (Visual Studio 2022)

cd VisualPinball.NativeInput
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release

Output: ../VisualPinball.Engine/VisualPinball.Unity/VisualPinball.Unity/Plugins/win-x64/VisualPinball.NativeInput.dll

Windows (MinGW)

cd VisualPinball.NativeInput
mkdir build
cd build
cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build .

Linux

cd VisualPinball.NativeInput
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make

Requires: libx11-dev

macOS

cd VisualPinball.NativeInput
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make

Requires: AppKit and ApplicationServices frameworks (provided by macOS)

CI / NuGet

GitHub Actions builds win-x64, win-x86, linux-x64, osx-x64, and osx-arm64 binaries and packs them into a single NuGet package.

Publishing happens automatically for tags matching v*.

Usage from C#

using VisualPinball.Unity.Simulation;

// Initialize
NativeInputApi.VpeInputInit();

// Set bindings
var bindings = new[] {
    new NativeInputApi.InputBinding {
        Action = (int)NativeInputApi.InputAction.LeftFlipper,
        BindingType = (int)NativeInputApi.BindingType.Keyboard,
        KeyCode = (int)NativeInputApi.KeyCode.LShift
    }
};
NativeInputApi.VpeInputSetBindings(bindings, bindings.Length);

// Start polling
NativeInputApi.VpeInputStartPolling(OnInputEvent, IntPtr.Zero, 500);

// Callback
[MonoPInvokeCallback(typeof(NativeInputApi.InputEventCallback))]
static void OnInputEvent(ref NativeInputApi.InputEvent evt, IntPtr userData) {
    Console.WriteLine($"Input: {evt.Action} = {evt.Value} @ {evt.TimestampUsec}μs");
}

// Stop polling
NativeInputApi.VpeInputStopPolling();

// Shutdown
NativeInputApi.VpeInputShutdown();

Platform Status

Platform Status API Used
Windows ✅ Implemented GetAsyncKeyState, QueryPerformanceCounter
Linux ✅ Implemented X11 keyboard state polling
macOS ✅ Implemented CoreGraphics keyboard state polling

Performance

  • Latency: <0.1ms from physical input to event callback
  • CPU Usage: 5-10% of one core (mostly sleeping)
  • Overhead: ~10-20ns per P/Invoke call
  • Precision: Monotonic microsecond timestamps across platforms

Future Enhancements

  1. Gamepad support: XInput (Windows), SDL/libinput (Linux), GCController (macOS)
  2. Analog inputs: Plunger, steering, analog triggers
  3. Force feedback: Haptics for nudge, tilt, button feedback
  4. Hot-plugging: Detect device connect/disconnect
  5. Configuration: JSON-based key mapping files
  6. Profiles: Per-table input profiles

License

GPLv3+ (same as VPE)

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.2 85 3/20/2026
0.0.1 75 3/20/2026