Input handler for Xbox controllers
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
#include "global.h"
|
||||
#include "InputHandler_Xbox.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageDisplay.h"
|
||||
|
||||
|
||||
#include <xtl.h>
|
||||
|
||||
struct DEVICE_STATE {
|
||||
XPP_DEVICE_TYPE *pxdt;
|
||||
DWORD dwState;
|
||||
};
|
||||
|
||||
byte buttonMasks[] = { XINPUT_GAMEPAD_DPAD_LEFT,
|
||||
XINPUT_GAMEPAD_DPAD_RIGHT,
|
||||
XINPUT_GAMEPAD_DPAD_UP,
|
||||
XINPUT_GAMEPAD_DPAD_DOWN,
|
||||
XINPUT_GAMEPAD_START,
|
||||
XINPUT_GAMEPAD_BACK,
|
||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB};
|
||||
|
||||
|
||||
/**
|
||||
* XBOX controller maps to the following RageInputDevice constants:
|
||||
* DPAD -> JOY_HAT_...
|
||||
* START -> JOY_AUX_1
|
||||
* BACK -> JOY_AUX_2
|
||||
* Left thumb button -> JOY_AUX_3
|
||||
* Right thumb button -> JOY_AUX_4
|
||||
* Following buttons are JOY_(index):
|
||||
* A, B, X, Y, BLACK, WHITE, Left trigger, right trigger
|
||||
*/
|
||||
|
||||
/* XXX: For some reason, with this input handler the input isn't handled on the gameplay screen!
|
||||
* All other menus work, and the screen itself sees the input and bounces the arrow, but no step
|
||||
* is actually registered. */
|
||||
|
||||
InputHandler_Xbox::InputHandler_Xbox()
|
||||
{
|
||||
//
|
||||
// Init joysticks
|
||||
//
|
||||
XDEVICE_PREALLOC_TYPE xdpt[] = {{XDEVICE_TYPE_GAMEPAD, 4}};
|
||||
XInitDevices( sizeof(xdpt) / sizeof(XDEVICE_PREALLOC_TYPE), xdpt );
|
||||
|
||||
getHandles();
|
||||
}
|
||||
|
||||
InputHandler_Xbox::~InputHandler_Xbox()
|
||||
{
|
||||
for(unsigned i = 0; i < NUM_PLAYERS; i++)
|
||||
{
|
||||
if(joysticks[i] != 0)
|
||||
XInputClose(joysticks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler_Xbox::Update(float fDeltaTime)
|
||||
{
|
||||
// check insertions and removals
|
||||
DWORD dwInsert, dwRemove;
|
||||
DEVICE_STATE devices = {XDEVICE_TYPE_GAMEPAD, 0};
|
||||
|
||||
bool changes = false;
|
||||
// Check each device type to see if any changes have occurred.
|
||||
if( XGetDeviceChanges( devices.pxdt, &dwInsert, &dwRemove ) )
|
||||
{
|
||||
for(int j = 0; j < 4; j++)
|
||||
{
|
||||
if(1 << j & dwRemove)
|
||||
{
|
||||
changes = true;
|
||||
LOG->Trace("A joystick was removed");
|
||||
}
|
||||
if(1 << j & dwInsert)
|
||||
{
|
||||
changes = true;
|
||||
LOG->Trace("A joystick was inserted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(changes)
|
||||
{
|
||||
getHandles();
|
||||
return;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < NUM_PLAYERS; i++)
|
||||
{
|
||||
if(joysticks[i] == 0)
|
||||
{
|
||||
LOG->Trace("Ignoring absent joystick");
|
||||
continue;
|
||||
}
|
||||
|
||||
InputDevice inputDevice = InputDevice(DEVICE_JOY1 + i);
|
||||
XINPUT_STATE xis;
|
||||
// Query latest state.
|
||||
XInputGetState( joysticks[i], &xis );
|
||||
|
||||
// check buttons
|
||||
for(int j = 0; j < NUM_BUTTONS; j++)
|
||||
{
|
||||
DWORD nowPressed = xis.Gamepad.wButtons & buttonMasks[j];
|
||||
DWORD wasPressed = lastState[i].wButtons & buttonMasks[j];
|
||||
|
||||
if(nowPressed != wasPressed)
|
||||
{
|
||||
JoystickButton Button = JoystickButton(JOY_HAT_LEFT + j);
|
||||
if(Button >= NUM_JOYSTICK_BUTTONS)
|
||||
{
|
||||
LOG->Warn("Ignored joystick event (button too high)");
|
||||
continue;
|
||||
}
|
||||
DeviceInput di(inputDevice, Button);
|
||||
ButtonPressed(di, nowPressed != 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check analog buttons
|
||||
for(int j = 0; j < NUM_ANALOG_BUTTONS; j++)
|
||||
{
|
||||
bool nowPressed = xis.Gamepad.bAnalogButtons[j] > XINPUT_GAMEPAD_MAX_CROSSTALK;
|
||||
bool wasPressed = lastState[i].bAnalogButtons[j] > XINPUT_GAMEPAD_MAX_CROSSTALK;
|
||||
|
||||
if(nowPressed != wasPressed)
|
||||
{
|
||||
JoystickButton Button = JoystickButton(JOY_1 + j);
|
||||
if(Button >= NUM_JOYSTICK_BUTTONS)
|
||||
{
|
||||
LOG->Warn("Ignored joystick event (button too high)");
|
||||
continue;
|
||||
}
|
||||
DeviceInput di(inputDevice, Button);
|
||||
ButtonPressed(di, nowPressed);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check thumbsticks
|
||||
SHORT axes[] = { xis.Gamepad.sThumbLX, xis.Gamepad.sThumbLY, xis.Gamepad.sThumbRX, xis.Gamepad.sThumbRY};
|
||||
|
||||
for(int j = 0; j < NUM_AXES; j++)
|
||||
{
|
||||
if(axes[j] != 0)
|
||||
{
|
||||
JoystickButton neg = (JoystickButton)(JOY_LEFT + (2 * j));
|
||||
JoystickButton pos = (JoystickButton)(JOY_RIGHT + (2 * j));
|
||||
float l = SCALE( axes[j], 0.0f, 32768.0f, 0.0f, 1.0f );
|
||||
ButtonPressed(DeviceInput(inputDevice, neg,max(-l,0),RageZeroTimer), axes[j] < -16000);
|
||||
ButtonPressed(DeviceInput(inputDevice, pos,max(+l,0),RageZeroTimer), axes[j] > +16000);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&lastState[i], &xis.Gamepad, sizeof(XINPUT_GAMEPAD));
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler_Xbox::GetDevicesAndDescriptions(vector<InputDevice>& vDevicesOut, vector<CString>& vDescriptionsOut)
|
||||
{
|
||||
for( int i=0; i<NUM_PLAYERS; i++ )
|
||||
{
|
||||
if( joysticks[i] != 0 )
|
||||
{
|
||||
vDevicesOut.push_back( InputDevice(DEVICE_JOY1+i) );
|
||||
vDescriptionsOut.push_back( "" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler_Xbox::getHandles()
|
||||
{
|
||||
ZeroMemory( joysticks, sizeof(joysticks) );
|
||||
ZeroMemory( lastState, sizeof(lastState) );
|
||||
|
||||
// Work out joystick handles
|
||||
DEVICE_STATE devices = {XDEVICE_TYPE_GAMEPAD, 0};
|
||||
devices.dwState = XGetDevices( devices.pxdt );
|
||||
|
||||
// Check the global gamepad state for a connected device.
|
||||
unsigned playersAllocated = 0;
|
||||
unsigned joysFound = 0;
|
||||
|
||||
for( unsigned i = 0; i < NUM_PORTS; i++ )
|
||||
{
|
||||
if( devices.dwState & 1 << i)
|
||||
{
|
||||
if(playersAllocated < NUM_PLAYERS)
|
||||
{
|
||||
XINPUT_POLLING_PARAMETERS pollingParameters = {TRUE, TRUE, 0, 8, 8, 0,};
|
||||
joysticks[playersAllocated] = XInputOpen(XDEVICE_TYPE_GAMEPAD, (DWORD)i, XDEVICE_NO_SLOT, &pollingParameters);
|
||||
playersAllocated++;
|
||||
}
|
||||
joysFound++;
|
||||
}
|
||||
}
|
||||
|
||||
LOG->Info( "Found %d connected joysticks for %d players", joysFound, playersAllocated );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Ryan Dortmans
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
Reference in New Issue
Block a user