XInput.Wrapper
- It is a short and monolithic C# class that can be embedded as source code in any project (1 source file).
- No external libraries, except XInput1_4.DLL but it ships today as a system component in Windows 8/8.1/10. It is available "inbox" and does not require redistribution with an application.
- To implement this class into your own project, just add the "X.cs" class file and start using it without any restriction. Anyway you can download latest release and add a reference to XInput.Wrapper.dll.
How to...
Initialization
using XInput.Wrapper;
// for ease of later using
X.Gamepad gamepad = null;
Test of availability of XInput 1.4 (xinput1_4.dll). Should not call often! This method not cached.
if (X.IsAvailable)
{
...
Got Gamepad of the first user
if (X.IsAvailable)
{
gamepad = X.Gamepad_1;
...
Check gamepad's capabilites and test ForceFeedBack support
if (X.IsAvailable)
{
gamepad = X.Gamepad_1;
X.Gamepad.Capability caps = gamepad.Capabilities;
if ((caps.Flags & X.Gamepad.CapabilityFlags.FFB_Supported) == X.Gamepad.CapabilityFlags.FFB_Supported)
{
// can play with ~~vibration~~ FFB
}
...
You can subscribe on events then start polling thread. X.StartPolling() supports up to four controllers.
if (X.IsAvailable)
{
gamepad = X.Gamepad_1;
...
gamepad.KeyDown += Gamepad_KeyDown;
gamepad.StateChanged += Gamepad_StateChanged;
gamepad.ConnectionChanged += Gamepad_ConnectionChanged;
X.StartPolling(gamepad);
}
Do not forget to stop polling
private void GameForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (gamepad != null)
X.StopPolling();
...
Events
ConnectionChanged
Occurs when state of connection is changed: controller connects or disconnects. Use X.GamePad.IsConnected() to retrieve state of connection.
StateChanged
Occurs when controller sends new data packet for application. Something changed and you should do something with new data. You can spot that some of buttons were pressed (up or down), thumb was rotated or trigger was pressed.
KeyDown
When button pressed for a long time your app can regularly receive messages about this.
StateChanged event called once when button pressed. Use KeyDown event handler if you want to receive regularly messages about this.
Update gamepad state
If you are playing with an event driven application (such as WinForms, WPF, etc) you can use X.Start|StopPolling. Apps with custom main loop should call X.Gamepad.Update() method.
while (true)
{
ProcessInput();
Update();
Render();
}
...
void ProcessInput()
{
if (gamepad == null)
return;
if (gamepad.Update())
{
// something happened: button pressed, stick turned or trigger was triggered
}
...
If Update() returns TRUE you should check connection state, state of buttons, sticks, triggers, bumpers,...
if (gamepad.Update())
{
// Check connection status and if connected then check battery state
if (gamepad.IsConnected)
gamepad.UpdateBattery();
// KeyUp is an event that happens once
// Try to stop vibrations
if (gamepad.X_up)
gamepad.FFB_Stop();
// You can process here but this will called once
if (gamepad.A_down)
gamepad.FFB_Vibrate(1, .5f, 100);
// Processing of analog inputs
...
}
// Will called again and again and again while button is pressed
if (gamepad.Buttons != 0)
{
if (gamepad.X_down)
gamepad.FFB_Vibrate(.2f, .5f, 100);
...
}
Processing of analog inputs
There are two kinds of analog methods: absolute and normalized. Normalized are with the _N postfix. Absolute methods returns X.Point {int X, int Y} objects, normalized returns X.PointF {float X, float Y}.
0 <= LTrigger.X <= 255 // absolute
0.0f <= LTrigger_N.X <= 1.0f // normalized
-32767 <= LStick.X <= 32767 // absolute
-1.0f <= LStick_N.X <= 1.0f // normalized
Dead zones
To adjust dead zones sensitivity
int LStick_DeadZone = 7849;
int RStick_DeadZone = 8689;
int LTrigger_Threshold = 30;
int RTrigger_Threshold = 30;
_N methods return 0.0f when axis in a dead zone.
Force feedback
Check presence of FFB
X.Gamepad.Capability caps = gamepad.Capabilities;
if ((caps.Flags & X.Gamepad.CapabilityFlags.FFB_Supported) == X.Gamepad.CapabilityFlags.FFB_Supported)
{
// Already here
}
Stop vabrations
gamepad.FFB_Stop();
And starts again at left and right with strength lying beetwen 0.0f and 1.0f up to 100ms
gamepad.FFB_Vibrate(0.5f, 1.0f, 100);
Left motor only (low-frequency motor)
gamepad.FFB_LeftMotor(0.5f, 100);
Right side only (hi-frequency motor)
gamepad.FFB_RightMotor(0.5f, 100);