Commit d9b8990a authored by Phillip Castaneda's avatar Phillip Castaneda
Browse files

Adding XInput support for win32. Not currently an option to compile out - todo.

parent 6a6c0c87
......@@ -4,7 +4,7 @@
The zlib/libpng License
Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
Copyright (c) 2005-2010 Phillip Castaneda (pjcast -- www.wreckedgames.com)
This software is provided 'as-is', without any express or implied warranty. In no
event will the authors be held liable for any damages arising from the use of this
......@@ -45,21 +45,16 @@ compatiable with many systems and operating systems
Win32/
Contains Visual Studio .Net Solution Files
Contains CodeBlocks + MinGW + StlPort project files for OIS
Contains CodeBlocks project files for OIS
---- Dependencies ------------------------------------------------------
DirectInput 8
Ogre & CEGUI 0.4.0 If building CEGUIOgre OIS Demo
SDL/
A test bed for an OIS InputManager with SDL as the backend. Not recommended;
however, useful for platforms with non-native OIS ports for temporary use.
Linux/
---- Dependencies ------------------------------------------------------
X11
Ogre (GLX Platform) & CEGUI 0.4.0 If building CEGUIOgre OIS Demo
Newer Linux Kernel (2.6+ ?) for Event API - else, use --disable-joyevents
Newer Linux Kernel (2.6+ ?) for Event API
Steps to build on Linux:
./bootstrap
......@@ -68,9 +63,7 @@ Linux/
---- Configure build options --------------------------------------------
./configure --help --- List all configure options
./configure --disable-ogre --- Disables CEGUIOgre ActionMapping Demo
./configure --disable-joyevents --- Uses /dev/input/jsX instead of
/dev/input/eventX
LinuxCB/
Contains CodeBlock files for building OIS and Demos with codeblocks
......@@ -79,9 +72,5 @@ LinuxCB/
settings. It also installs libOIS to ~/libs
Mac/
XCode-1.5/
Non-complete native OIS port.
XCode-2.2/
Working, complete, OIS port to OSX using SDL as a backend.
\ No newline at end of file
Working, mostly complete OSX vackend.
\ No newline at end of file
......@@ -64,7 +64,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ois_static_d.lib"
AdditionalDependencies="ois_static_d.lib xinput.lib"
OutputFile="$(OutDir)/CommandLine.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\lib;..\..\src\win32\extras\WiiMote"
......@@ -99,9 +99,9 @@
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2"
>
......@@ -119,16 +119,17 @@
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="true"
AdditionalIncludeDirectories="..\..\includes;..\CommandLine\"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_STLP_DEBUG"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
......@@ -145,16 +146,17 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ois_d.lib"
AdditionalDependencies="ois_static.lib xinput.lib"
OutputFile="$(OutDir)/CommandLine.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\lib64"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\lib;..\..\src\win32\extras\WiiMote"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/CommandLine.pdb"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
......@@ -180,9 +182,9 @@
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
......@@ -200,17 +202,16 @@
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="true"
Optimization="0"
AdditionalIncludeDirectories="..\..\includes;..\CommandLine\"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_STLP_DEBUG"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
......@@ -227,17 +228,16 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ois_static.lib"
AdditionalDependencies="ois_d.lib"
OutputFile="$(OutDir)/CommandLine.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\lib;..\..\src\win32\extras\WiiMote"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\lib64"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/CommandLine.pdb"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
......
......@@ -64,7 +64,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ois_static_d.lib"
AdditionalDependencies="ois_static_d.lib xinput.lib"
OutputFile="$(OutDir)/DemoFFTest.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="..\..\lib;..\..\src\win32\extras\WiiMote"
......@@ -146,7 +146,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ois_static.lib"
AdditionalDependencies="ois_static.lib xinput.lib"
OutputFile="$(OutDir)/DemoFFTest.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="..\..\lib;..\..\src\win32\extras\WiiMote"
......
......@@ -68,7 +68,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_static_d.lib"
AdditionalLibraryDirectories="..\src\win32\extras\WiiMote"
/>
......@@ -140,7 +140,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_d.lib"
/>
<Tool
......@@ -212,7 +212,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_static.lib"
AdditionalLibraryDirectories="..\src\win32\extras\WiiMote"
/>
......@@ -289,7 +289,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS.lib"
/>
<Tool
......@@ -361,7 +361,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
AdditionalLibraryDirectories="..\src\win32\extras\WiiMote\"
GenerateDebugInformation="false"
OptimizeReferences="2"
......@@ -451,7 +451,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
GenerateDebugInformation="true"
TargetMachine="17"
/>
......@@ -531,7 +531,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_d.dll"
AdditionalLibraryDirectories="..\src\win32\extras\WiiMote\"
GenerateDebugInformation="true"
......@@ -613,7 +613,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_d.dll"
TargetMachine="17"
/>
......
......@@ -69,7 +69,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_static_d.lib"
AdditionalLibraryDirectories="..\src\win32\extras\WiiMote"
/>
......@@ -142,7 +142,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_static.lib"
AdditionalLibraryDirectories="..\src\win32\extras\WiiMote"
/>
......@@ -215,7 +215,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
AdditionalLibraryDirectories="..\src\win32\extras\WiiMote\"
GenerateDebugInformation="false"
OptimizeReferences="2"
......@@ -298,7 +298,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_d.dll"
AdditionalLibraryDirectories="..\src\win32\extras\WiiMote\"
GenerateDebugInformation="true"
......@@ -379,7 +379,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_d.lib"
/>
<Tool
......@@ -455,7 +455,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS.lib"
/>
<Tool
......@@ -531,7 +531,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
GenerateDebugInformation="true"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
......@@ -611,7 +611,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxguid.lib dinput8.lib"
AdditionalDependencies="dxguid.lib dinput8.lib xinput.lib"
OutputFile="$(OutDir)/OIS_d.dll"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
......@@ -897,13 +897,6 @@
Name="VCResourceCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="OIS_ReleaseDll|Win32"
>
<Tool
Name="VCResourceCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="OIS_DebugDll|Win32"
ExcludedFromBuild="true"
......
......@@ -46,6 +46,14 @@ namespace OIS
/** @copydoc Object::_initialize */
virtual void _initialize();
/**
@remarks
Enum each PNP device using WMI and check each device ID to see if it contains
"IG_" (ex. "VID_045E&PID_028E&IG_00"). If it does, then it's an XInput device
Unfortunately this information can not be found by just using DirectInput
*/
static void CheckXInputDevices(JoyStickInfoList &joys);
protected:
//! Enumerates all things
void _enumerate();
......@@ -60,12 +68,12 @@ namespace OIS
IDirectInput8* mDirectInput;
IDirectInputDevice8* mJoyStick;
DIDEVCAPS mDIJoyCaps;
DWORD coopSetting;
GUID deviceGuid;
JoyStickInfo mJoyInfo;
//! A force feedback device
Win32ForceFeedback* ff_device;
Win32ForceFeedback* mFfDevice;
//! Mapping
int _AxisNumber;
......
......@@ -27,6 +27,7 @@ restrictions:
#define DIRECTINPUT_VERSION 0x0800
#include <windows.h>
#include <dinput.h>
#include <XInput.h>
//Max number of elements to collect from buffered DirectInput
#define KEYBOARD_DX_BUFFERSIZE 17
......@@ -54,10 +55,13 @@ namespace OIS
public:
int devId;
GUID deviceID;
GUID productGuid;
std::string vendor;
bool isXInput;
int xInputDev;
};
typedef std::vector< JoyStickInfo > JoyStickInfoList;
typedef std::vector<JoyStickInfo> JoyStickInfoList;
}
#endif //_WIN32_INPUTSYSTEM_PREREQS_H
......@@ -74,7 +74,7 @@ void Win32InputManager::_initialize( ParamList &paramList )
hInst = GetModuleHandle(0);
//Create the input system
//Create the device
hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&mDirectInput, NULL );
if (FAILED(hr))
OIS_EXCEPT( E_General, "Win32InputManager::Win32InputManager >> Not able to init DirectX8 Input!");
......@@ -117,7 +117,19 @@ void Win32InputManager::_parseConfigSettings( ParamList &paramList )
void Win32InputManager::_enumerateDevices()
{
//Enumerate all attached devices
mDirectInput->EnumDevices(NULL , _DIEnumDevCallback, this, DIEDFL_ATTACHEDONLY);
mDirectInput->EnumDevices(NULL, _DIEnumDevCallback, this, DIEDFL_ATTACHEDONLY);
int xinputControllers = 0;
//let's check how many possible XInput devices we may have (max 4)...
for(int i = 0; i < 3; ++i)
{
XINPUT_STATE state;
if(XInputGetState(i, &state) != ERROR_DEVICE_NOT_CONNECTED)
{ //Once we found 1, just check our whole list against devices
Win32JoyStick::CheckXInputDevices(unusedJoyStickList);
break;
}
}
}
//--------------------------------------------------------------------------------//
......@@ -133,6 +145,8 @@ BOOL CALLBACK Win32InputManager::_DIEnumDevCallback(LPCDIDEVICEINSTANCE lpddi, L
GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_FLIGHT)
{
JoyStickInfo jsInfo;
jsInfo.isXInput = false;
jsInfo.productGuid = lpddi->guidProduct;
jsInfo.deviceID = lpddi->guidInstance;
jsInfo.vendor = lpddi->tszInstanceName;
jsInfo.devId = _this_->joySticks;
......
......@@ -27,6 +27,18 @@ restrictions:
#include "OISException.h"
#include <cassert>
#include <wbemidl.h>
#include <oleauto.h>
//#include <wmsstd.h>
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(x) \
if(x != NULL) \
{ \
x->Release(); \
x = NULL; \
}
#endif
//DX Only defines macros for the JOYSTICK not JOYSTICK2, so fix it
#undef DIJOFS_BUTTON
......@@ -39,26 +51,26 @@ restrictions:
#define DIJOFS_SLIDER2(n) (FIELD_OFFSET(DIJOYSTATE2, rglASlider)+(n) * sizeof(LONG))
#define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG))
#define XINPUT_TRANSLATED_BUTTON_COUNT 12
#define XINPUT_TRANSLATED_AXIS_COUNT 6
using namespace OIS;
//--------------------------------------------------------------------------------------------------//
Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI,
bool buffered, DWORD coopSettings, const JoyStickInfo &info )
: JoyStick(info.vendor, buffered, info.devId, creator)
Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings, const JoyStickInfo &info ) :
JoyStick(info.vendor, buffered, info.devId, creator),
mDirectInput(pDI),
coopSetting(coopSettings),
mJoyStick(0),
mJoyInfo(info),
mFfDevice(0)
{
mDirectInput = pDI;
coopSetting = coopSettings;
mJoyStick = 0;
deviceGuid = info.deviceID;
ff_device = 0;
}
//--------------------------------------------------------------------------------------------------//
Win32JoyStick::~Win32JoyStick()
{
delete ff_device;
delete mFfDevice;
if(mJoyStick)
{
......@@ -68,80 +80,86 @@ Win32JoyStick::~Win32JoyStick()
}
//Return joystick to pool
JoyStickInfo js;
js.deviceID = deviceGuid;
js.devId = mDevID;
js.vendor = mVendor;
static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(js);
static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(mJoyInfo);
}
//--------------------------------------------------------------------------------------------------//
void Win32JoyStick::_initialize()
{
if (mJoyInfo.isXInput)
{
_enumerate();
}
else
{
//Clear old state
mState.mAxes.clear();
if (ff_device)
{
delete ff_device;
ff_device = 0;
}
delete mFfDevice;
mFfDevice = 0;
// Create direct input joystick device.
if(FAILED(mDirectInput->CreateDevice(deviceGuid, &mJoyStick, NULL)))
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = JOYSTICK_DX_BUFFERSIZE;
if(FAILED(mDirectInput->CreateDevice(mJoyInfo.deviceID, &mJoyStick, NULL)))
OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
// Set DIJoystick2 data format.
if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
// Set cooperative level as specified when creating input manager.
HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
// Set buffer size.
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = JOYSTICK_DX_BUFFERSIZE;
if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
OIS_EXCEPT( E_General, "Win32JoyStick::_initialize >> Failed to set buffer size property" );
OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" );
// Enumerate all axes/buttons/sliders/force feedback/etc before aquiring
//Enumerate all axes/buttons/sliders/etc before aquiring
_enumerate();
mState.clear();
capture();
}
}
//--------------------------------------------------------------------------------------------------//
void Win32JoyStick::_enumerate()
{
if (mJoyInfo.isXInput)
{
mPOVs = 1;
mState.mButtons.resize(XINPUT_TRANSLATED_BUTTON_COUNT);
mState.mAxes.resize(XINPUT_TRANSLATED_AXIS_COUNT);
}
else
{
// Get joystick capabilities.
mDIJoyCaps.dwSize = sizeof(DIDEVCAPS);
if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) )
OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" );
// => Number of POVs
mPOVs = (short)mDIJoyCaps.dwPOVs;
// => Number of buttons and axes.
mState.mButtons.resize(mDIJoyCaps.dwButtons);
mState.mAxes.resize(mDIJoyCaps.dwAxes);
// Enumerate all Force Feedback effects (if any)
mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
//Reset the axis mapping enumeration value
_AxisNumber = 0;
// Enumerate and set axis constraints (and check FF Axes)
//Enumerate Force Feedback (if any)
mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
//Enumerate and set axis constraints (and check FF Axes)
mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
}
}
//--------------------------------------------------------------------------------------------------//
......@@ -190,19 +208,19 @@ BOOL CALLBACK Win32JoyStick::DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTAN
//Check if FF Axes, and if so, increment counter
if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
{
if( _this->ff_device )
if( _this->mFfDevice )
{
_this->ff_device->_addFFAxis();
_this->mFfDevice->_addFFAxis();
}
}
//Force the flags for gain and auto-center support to true,
//as DInput has no API to query the device for these capabilities
//(the only way to know is to try them ...)
if( _this->ff_device )
if( _this->mFfDevice )
{
_this->ff_device->_setGainSupport(true);
_this->ff_device->_setAutoCenterSupport(true);
_this->mFfDevice->_setGainSupport(true);
_this->mFfDevice->_setAutoCenterSupport(true);
}
return DIENUM_CONTINUE;
......@@ -214,10 +232,10 @@ BOOL CALLBACK Win32JoyStick::DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID
Win32JoyStick* _this = (Win32JoyStick*)pvRef;
//Create the FF instance only after we know there is at least one effect type
if( _this->ff_device == 0 )
_this->ff_device = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
if( _this->mFfDevice == 0 )
_this->mFfDevice = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
_this->ff_device->_addEffectSupport( pdei );
_this->mFfDevice->_addEffectSupport(pdei);
return DIENUM_CONTINUE;
}
......@@ -225,6 +243,147 @@ BOOL CALLBACK Win32JoyStick::DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID
//--------------------------------------------------------------------------------------------------//
void Win32JoyStick::capture()
{
if (mJoyInfo.isXInput)
{
XINPUT_STATE inputState;
if (XInputGetState((DWORD)mJoyInfo.xInputDev, &inputState) != ERROR_SUCCESS)
memset(&inputState, 0, sizeof(inputState));
//Sticks and triggers
bool axisMoved[XINPUT_TRANSLATED_AXIS_COUNT] = {false,false,false,false,false,false};
if (std::abs(inputState.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
int value = -(int)inputState.Gamepad.sThumbLY;
mState.mAxes[0].rel = value - mState.mAxes[0].abs;
mState.mAxes[0].abs = value;
axisMoved[0] = mState.mAxes[0].rel != 0;
}
else
{
mState.mAxes[0].rel = 0;
mState.mAxes[0].abs = 0;
}
if (std::abs(inputState.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
{
mState.mAxes[1].rel = inputState.Gamepad.sThumbLX - mState.mAxes[1].abs;
mState.mAxes[1].abs = inputState.Gamepad.sThumbLX;
axisMoved[1] = mState.mAxes[1].rel != 0;
}
else
{
mState.mAxes[1].rel = 0;
mState.mAxes[1].abs = 0;
}
if (std::abs(inputState.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
int value = -(int)inputState.Gamepad.sThumbRY;
mState.mAxes[2].rel = value - mState.mAxes[2].abs;
mState.mAxes[2].abs = value;
axisMoved[2] = mState.mAxes[2].rel != 0;
}
else
{
mState.mAxes[2].rel = 0;
mState.mAxes[2].abs = 0;
}
if (std::abs(inputState.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
{
mState.mAxes[3].rel = inputState.Gamepad.sThumbRX - mState.mAxes[3].abs;
mState.mAxes[3].abs = inputState.Gamepad.sThumbRX;
axisMoved[3] = mState.mAxes[3].rel != 0;
}
else
{
mState.mAxes[3].rel = 0;
mState.mAxes[3].abs = 0;
}
if (inputState.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
{
int value = (int)inputState.Gamepad.bLeftTrigger * 128;
if (value > 0)
value = min(value + 128, 32767);
mState.mAxes[4].rel = value - mState.mAxes[4].abs;
mState.mAxes[4].abs = value;
axisMoved[4] = mState.mAxes[4].rel != 0;
}
else
{
mState.mAxes[4].rel = 0;
mState.mAxes[4].abs = 0;
}
if (inputState.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
{
int value = (int)inputState.Gamepad.bRightTrigger * 128;
if (value > 0)
value = min(value + 128, 32767);
mState.mAxes[5].rel = value - mState.mAxes[5].abs;
mState.mAxes[5].abs = value;
axisMoved[5] = mState.mAxes[5].rel != 0;
}
else
{
mState.mAxes[5].rel = 0;
mState.mAxes[5].abs = 0;
}
//POV
int previousPov = mState.mPOV[0].direction;
int& pov = mState.mPOV[0].direction;
pov = Pov::Centered;
if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
pov |= Pov::North;
else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
pov |= Pov::South;
if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
pov |= Pov::West;
else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
pov |= Pov::East;
//Buttons - The first 4 buttons don't need to be checked since they represent the dpad
bool previousButtons[XINPUT_TRANSLATED_BUTTON_COUNT];
std::copy(mState.mButtons.begin(), mState.mButtons.end(), previousButtons);
for (size_t i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
mState.mButtons[i] = (inputState.Gamepad.wButtons & (1 << (i + 4))) != 0;
//Send events
if (mBuffered && mListener)
{
JoyStickEvent joystickEvent(this, mState);
//Axes
for (int i = 0; i < XINPUT_TRANSLATED_AXIS_COUNT; i++)
{
if (axisMoved[i] && !mListener->axisMoved(joystickEvent, i))
return;
}
//POV
if (previousPov != pov && !mListener->povMoved(joystickEvent, 0))
return;
//Buttons
for (int i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
{
if (!previousButtons[i] && mState.mButtons[i])
{
if (!mListener->buttonPressed(joystickEvent, i))
return;
}
else if (previousButtons[i] && !mState.mButtons[i])
{
if (!mListener->buttonReleased(joystickEvent, i))
return;
}
}
}
}
else
{
DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE];
DWORD entries = JOYSTICK_DX_BUFFERSIZE;
......@@ -349,6 +508,7 @@ void Win32JoyStick::capture()
if( mListener->sliderMoved( temp, i ) == false )
return;
}
}
}
//--------------------------------------------------------------------------------------------------//
......@@ -409,11 +569,132 @@ void Win32JoyStick::setBuffered(bool buffered)
//--------------------------------------------------------------------------------------------------//
Interface* Win32JoyStick::queryInterface(Interface::IType type)
{
//Thought about using covariant return type here.. however,
//some devices may allow LED light changing, or other interface stuff
if( ff_device && type == Interface::ForceFeedback )
return ff_device;
if( mFfDevice && type == Interface::ForceFeedback )
return mFfDevice;
else
return 0;
}
//--------------------------------------------------------------------------------------------------//
void Win32JoyStick::CheckXInputDevices(JoyStickInfoList &joys)
{
IWbemLocator* pIWbemLocator = NULL;
IEnumWbemClassObject* pEnumDevices = NULL;
IWbemClassObject* pDevices[20] = {0};
IWbemServices* pIWbemServices = NULL;
BSTR bstrNamespace = NULL;
BSTR bstrDeviceID = NULL;
BSTR bstrClassName = NULL;
DWORD uReturned = 0;
bool bIsXinputDevice= false;
DWORD iDevice = 0;
int xDevice = 0;
VARIANT var;
HRESULT hr;
if(joys.size() == 0)
return;
// CoInit if needed
hr = CoInitialize(NULL);
bool bCleanupCOM = SUCCEEDED(hr);
// Create WMI
hr = CoCreateInstance(__uuidof(WbemLocator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator);
if( FAILED(hr) || pIWbemLocator == NULL )
goto LCleanup;
bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );
if( bstrNamespace == NULL )
goto LCleanup;
bstrClassName = SysAllocString( L"Win32_PNPEntity" );
if( bstrClassName == NULL )
goto LCleanup;
bstrDeviceID = SysAllocString( L"DeviceID" );
if( bstrDeviceID == NULL )
goto LCleanup;
// Connect to WMI
hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices );
if( FAILED(hr) || pIWbemServices == NULL )
goto LCleanup;
// Switch security level to IMPERSONATE.
CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices );
if( FAILED(hr) || pEnumDevices == NULL )
goto LCleanup;
// Loop over all devices
for( ;; )
{
// Get 20 at a time
hr = pEnumDevices->Next(5000, 20, pDevices, &uReturned);
if( FAILED(hr) )
goto LCleanup;
if( uReturned == 0 )
break;
for(iDevice = 0; iDevice < uReturned; iDevice++)
{
// For each device, get its device ID
hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL);
if(SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL)
{
// Check if the device ID contains "IG_". If it does, then it's an XInput device - This information can not be found from DirectInput
if(wcsstr(var.bstrVal, L"IG_"))
{
// If it does, then get the VID/PID from var.bstrVal
DWORD dwPid = 0, dwVid = 0;
WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
if(strVid && swscanf_s( strVid, L"VID_%4X", &dwVid ) != 1)
dwVid = 0;
WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
if(strPid && swscanf_s( strPid, L"PID_%4X", &dwPid ) != 1)
dwPid = 0;
// Compare the VID/PID to the DInput device
DWORD dwVidPid = MAKELONG(dwVid, dwPid);
for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
{
if(dwVidPid == i->productGuid.Data1)
{
i->isXInput = true;
i->xInputDev = xDevice;
}
}
if(joys.size() == 0)
goto LCleanup;
}
}
SAFE_RELEASE(pDevices[iDevice]);
}
}
LCleanup:
if(bstrNamespace)
SysFreeString(bstrNamespace);
if(bstrDeviceID)
SysFreeString(bstrDeviceID);
if(bstrClassName)
SysFreeString(bstrClassName);
for(iDevice=0; iDevice < 20; iDevice++)
SAFE_RELEASE(pDevices[iDevice]);
SAFE_RELEASE(pEnumDevices);
SAFE_RELEASE(pIWbemLocator);
SAFE_RELEASE(pIWbemServices);
if(bCleanupCOM)
CoUninitialize();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment