mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 04:41:05 +08:00
Added support for interfacing with joysticks via DirectInput when it is available.
This commit is contained in:
parent
d972216c57
commit
22f1b85515
117
extlibs/headers/mingw/_mingw_dxhelper.h
vendored
Normal file
117
extlibs/headers/mingw/_mingw_dxhelper.h
vendored
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* This file has no copyright assigned and is placed in the Public Domain.
|
||||||
|
* This file is part of the mingw-w64 runtime package.
|
||||||
|
* No warranty is given; refer to the file DISCLAIMER within this package.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS)
|
||||||
|
#define NONAMELESSUNION 1
|
||||||
|
#endif
|
||||||
|
#if defined(NONAMELESSSTRUCT) && \
|
||||||
|
!defined(NONAMELESSUNION)
|
||||||
|
#define NONAMELESSUNION 1
|
||||||
|
#endif
|
||||||
|
#if defined(NONAMELESSUNION) && \
|
||||||
|
!defined(NONAMELESSSTRUCT)
|
||||||
|
#define NONAMELESSSTRUCT 1
|
||||||
|
#endif
|
||||||
|
#if !defined(__GNU_EXTENSION)
|
||||||
|
#if defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
#define __GNU_EXTENSION __extension__
|
||||||
|
#else
|
||||||
|
#define __GNU_EXTENSION
|
||||||
|
#endif
|
||||||
|
#endif /* __extension__ */
|
||||||
|
|
||||||
|
#ifndef __ANONYMOUS_DEFINED
|
||||||
|
#define __ANONYMOUS_DEFINED
|
||||||
|
#if defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
#define _ANONYMOUS_UNION __extension__
|
||||||
|
#define _ANONYMOUS_STRUCT __extension__
|
||||||
|
#else
|
||||||
|
#define _ANONYMOUS_UNION
|
||||||
|
#define _ANONYMOUS_STRUCT
|
||||||
|
#endif
|
||||||
|
#ifndef NONAMELESSUNION
|
||||||
|
#define _UNION_NAME(x)
|
||||||
|
#define _STRUCT_NAME(x)
|
||||||
|
#else /* NONAMELESSUNION */
|
||||||
|
#define _UNION_NAME(x) x
|
||||||
|
#define _STRUCT_NAME(x) x
|
||||||
|
#endif
|
||||||
|
#endif /* __ANONYMOUS_DEFINED */
|
||||||
|
|
||||||
|
#ifndef DUMMYUNIONNAME
|
||||||
|
# ifdef NONAMELESSUNION
|
||||||
|
# define DUMMYUNIONNAME u
|
||||||
|
# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */
|
||||||
|
# define DUMMYUNIONNAME2 u2
|
||||||
|
# define DUMMYUNIONNAME3 u3
|
||||||
|
# define DUMMYUNIONNAME4 u4
|
||||||
|
# define DUMMYUNIONNAME5 u5
|
||||||
|
# define DUMMYUNIONNAME6 u6
|
||||||
|
# define DUMMYUNIONNAME7 u7
|
||||||
|
# define DUMMYUNIONNAME8 u8
|
||||||
|
# define DUMMYUNIONNAME9 u9
|
||||||
|
# else /* NONAMELESSUNION */
|
||||||
|
# define DUMMYUNIONNAME
|
||||||
|
# define DUMMYUNIONNAME1 /* Wine uses this variant */
|
||||||
|
# define DUMMYUNIONNAME2
|
||||||
|
# define DUMMYUNIONNAME3
|
||||||
|
# define DUMMYUNIONNAME4
|
||||||
|
# define DUMMYUNIONNAME5
|
||||||
|
# define DUMMYUNIONNAME6
|
||||||
|
# define DUMMYUNIONNAME7
|
||||||
|
# define DUMMYUNIONNAME8
|
||||||
|
# define DUMMYUNIONNAME9
|
||||||
|
# endif
|
||||||
|
#endif /* DUMMYUNIONNAME */
|
||||||
|
|
||||||
|
#if !defined(DUMMYUNIONNAME1) /* MinGW does not define this one */
|
||||||
|
# ifdef NONAMELESSUNION
|
||||||
|
# define DUMMYUNIONNAME1 u1 /* Wine uses this variant */
|
||||||
|
# else
|
||||||
|
# define DUMMYUNIONNAME1 /* Wine uses this variant */
|
||||||
|
# endif
|
||||||
|
#endif /* DUMMYUNIONNAME1 */
|
||||||
|
|
||||||
|
#ifndef DUMMYSTRUCTNAME
|
||||||
|
# ifdef NONAMELESSUNION
|
||||||
|
# define DUMMYSTRUCTNAME s
|
||||||
|
# define DUMMYSTRUCTNAME1 s1 /* Wine uses this variant */
|
||||||
|
# define DUMMYSTRUCTNAME2 s2
|
||||||
|
# define DUMMYSTRUCTNAME3 s3
|
||||||
|
# define DUMMYSTRUCTNAME4 s4
|
||||||
|
# define DUMMYSTRUCTNAME5 s5
|
||||||
|
# else
|
||||||
|
# define DUMMYSTRUCTNAME
|
||||||
|
# define DUMMYSTRUCTNAME1 /* Wine uses this variant */
|
||||||
|
# define DUMMYSTRUCTNAME2
|
||||||
|
# define DUMMYSTRUCTNAME3
|
||||||
|
# define DUMMYSTRUCTNAME4
|
||||||
|
# define DUMMYSTRUCTNAME5
|
||||||
|
# endif
|
||||||
|
#endif /* DUMMYSTRUCTNAME */
|
||||||
|
|
||||||
|
/* These are for compatibility with the Wine source tree */
|
||||||
|
|
||||||
|
#ifndef WINELIB_NAME_AW
|
||||||
|
# ifdef __MINGW_NAME_AW
|
||||||
|
# define WINELIB_NAME_AW __MINGW_NAME_AW
|
||||||
|
# else
|
||||||
|
# ifdef UNICODE
|
||||||
|
# define WINELIB_NAME_AW(func) func##W
|
||||||
|
# else
|
||||||
|
# define WINELIB_NAME_AW(func) func##A
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif /* WINELIB_NAME_AW */
|
||||||
|
|
||||||
|
#ifndef DECL_WINELIB_TYPE_AW
|
||||||
|
# ifdef __MINGW_TYPEDEF_AW
|
||||||
|
# define DECL_WINELIB_TYPE_AW __MINGW_TYPEDEF_AW
|
||||||
|
# else
|
||||||
|
# define DECL_WINELIB_TYPE_AW(type) typedef WINELIB_NAME_AW(type) type;
|
||||||
|
# endif
|
||||||
|
#endif /* DECL_WINELIB_TYPE_AW */
|
||||||
|
|
2467
extlibs/headers/mingw/dinput.h
vendored
Normal file
2467
extlibs/headers/mingw/dinput.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -245,6 +245,13 @@ if(SFML_OS_LINUX)
|
|||||||
endif()
|
endif()
|
||||||
include_directories(${UDEV_INCLUDE_DIR})
|
include_directories(${UDEV_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
if(SFML_OS_WINDOWS AND NOT SFML_COMPILER_MSVC)
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
check_include_file(dinput.h DINPUT_H_FOUND)
|
||||||
|
if(NOT DINPUT_H_FOUND)
|
||||||
|
include_directories("${PROJECT_SOURCE_DIR}/extlibs/headers/mingw")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# build the list of external libraries to link
|
# build the list of external libraries to link
|
||||||
|
@ -33,9 +33,59 @@
|
|||||||
#include <regstr.h>
|
#include <regstr.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// DirectInput
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DIDFT_OPTIONAL
|
||||||
|
#define DIDFT_OPTIONAL 0x80000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
namespace guids
|
||||||
|
{
|
||||||
|
const GUID IID_IDirectInput8W = {0xbf798031, 0x483a, 0x4da2, {0xaa, 0x99, 0x5d, 0x64, 0xed, 0x36, 0x97, 0x00}};
|
||||||
|
|
||||||
|
const GUID GUID_XAxis = {0xa36d02e0, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||||
|
const GUID GUID_YAxis = {0xa36d02e1, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||||
|
const GUID GUID_ZAxis = {0xa36d02e2, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||||
|
const GUID GUID_RzAxis = {0xa36d02e3, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||||
|
const GUID GUID_Slider = {0xa36d02e4, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||||
|
|
||||||
|
const GUID GUID_POV = {0xa36d02f2, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||||
|
|
||||||
|
const GUID GUID_RxAxis = {0xa36d02f4, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||||
|
const GUID GUID_RyAxis = {0xa36d02f5, 0xc9f3, 0x11cf, {0xbf, 0xc7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE dinput8dll = NULL;
|
||||||
|
IDirectInput8W* directInput = NULL;
|
||||||
|
|
||||||
|
struct JoystickRecord
|
||||||
|
{
|
||||||
|
GUID guid;
|
||||||
|
unsigned int index;
|
||||||
|
bool plugged;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<JoystickRecord> JoystickList;
|
||||||
|
JoystickList joystickList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Legacy joystick API
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
struct ConnectionCache
|
struct ConnectionCache
|
||||||
@ -152,6 +202,12 @@ namespace priv
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void JoystickImpl::initialize()
|
void JoystickImpl::initialize()
|
||||||
{
|
{
|
||||||
|
// Try to initialize DirectInput
|
||||||
|
initializeDInput();
|
||||||
|
|
||||||
|
if (!directInput)
|
||||||
|
err() << "DirectInput not available, falling back to Windows joystick API" << std::endl;
|
||||||
|
|
||||||
// Perform the initial scan and populate the connection cache
|
// Perform the initial scan and populate the connection cache
|
||||||
updateConnections();
|
updateConnections();
|
||||||
}
|
}
|
||||||
@ -160,13 +216,17 @@ void JoystickImpl::initialize()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void JoystickImpl::cleanup()
|
void JoystickImpl::cleanup()
|
||||||
{
|
{
|
||||||
// Nothing to do
|
// Clean up DirectInput
|
||||||
|
cleanupDInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool JoystickImpl::isConnected(unsigned int index)
|
bool JoystickImpl::isConnected(unsigned int index)
|
||||||
{
|
{
|
||||||
|
if (directInput)
|
||||||
|
return isConnectedDInput(index);
|
||||||
|
|
||||||
ConnectionCache& cache = connectionCache[index];
|
ConnectionCache& cache = connectionCache[index];
|
||||||
if (!lazyUpdates && cache.timer.getElapsedTime() > connectionRefreshDelay)
|
if (!lazyUpdates && cache.timer.getElapsedTime() > connectionRefreshDelay)
|
||||||
{
|
{
|
||||||
@ -189,6 +249,9 @@ void JoystickImpl::setLazyUpdates(bool status)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void JoystickImpl::updateConnections()
|
void JoystickImpl::updateConnections()
|
||||||
{
|
{
|
||||||
|
if (directInput)
|
||||||
|
return updateConnectionsDInput();
|
||||||
|
|
||||||
for (unsigned int i = 0; i < Joystick::Count; ++i)
|
for (unsigned int i = 0; i < Joystick::Count; ++i)
|
||||||
{
|
{
|
||||||
JOYINFOEX joyInfo;
|
JOYINFOEX joyInfo;
|
||||||
@ -204,6 +267,9 @@ void JoystickImpl::updateConnections()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool JoystickImpl::open(unsigned int index)
|
bool JoystickImpl::open(unsigned int index)
|
||||||
{
|
{
|
||||||
|
if (directInput)
|
||||||
|
return openDInput(index);
|
||||||
|
|
||||||
// No explicit "open" action is required
|
// No explicit "open" action is required
|
||||||
m_index = JOYSTICKID1 + index;
|
m_index = JOYSTICKID1 + index;
|
||||||
|
|
||||||
@ -224,12 +290,16 @@ bool JoystickImpl::open(unsigned int index)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void JoystickImpl::close()
|
void JoystickImpl::close()
|
||||||
{
|
{
|
||||||
// Nothing to do
|
if (directInput)
|
||||||
|
closeDInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
JoystickCaps JoystickImpl::getCapabilities() const
|
JoystickCaps JoystickImpl::getCapabilities() const
|
||||||
{
|
{
|
||||||
|
if (directInput)
|
||||||
|
return getCapabilitiesDInput();
|
||||||
|
|
||||||
JoystickCaps caps;
|
JoystickCaps caps;
|
||||||
|
|
||||||
caps.buttonCount = m_caps.wNumButtons;
|
caps.buttonCount = m_caps.wNumButtons;
|
||||||
@ -259,6 +329,9 @@ Joystick::Identification JoystickImpl::getIdentification() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
JoystickState JoystickImpl::update()
|
JoystickState JoystickImpl::update()
|
||||||
{
|
{
|
||||||
|
if (directInput)
|
||||||
|
return updateDInput();
|
||||||
|
|
||||||
JoystickState state;
|
JoystickState state;
|
||||||
|
|
||||||
// Get the current joystick state
|
// Get the current joystick state
|
||||||
@ -300,6 +373,548 @@ JoystickState JoystickImpl::update()
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void JoystickImpl::initializeDInput()
|
||||||
|
{
|
||||||
|
// Try to load dinput8.dll
|
||||||
|
dinput8dll = LoadLibraryA("dinput8.dll");
|
||||||
|
|
||||||
|
if (dinput8dll)
|
||||||
|
{
|
||||||
|
// Try to get the address of the DirectInput8Create entry point
|
||||||
|
typedef HRESULT(WINAPI *DirectInput8CreateFunc)(HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN);
|
||||||
|
DirectInput8CreateFunc directInput8Create = reinterpret_cast<DirectInput8CreateFunc>(GetProcAddress(dinput8dll, "DirectInput8Create"));
|
||||||
|
|
||||||
|
if (directInput8Create)
|
||||||
|
{
|
||||||
|
// Try to acquire a DirectInput 8.x interface
|
||||||
|
HRESULT result = directInput8Create(GetModuleHandleW(NULL), 0x0800, guids::IID_IDirectInput8W, reinterpret_cast<void**>(&directInput), NULL);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
// De-initialize everything
|
||||||
|
directInput = NULL;
|
||||||
|
FreeLibrary(dinput8dll);
|
||||||
|
dinput8dll = NULL;
|
||||||
|
|
||||||
|
err() << "Failed to initialize DirectInput: " << result << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unload dinput8.dll
|
||||||
|
FreeLibrary(dinput8dll);
|
||||||
|
dinput8dll = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void JoystickImpl::cleanupDInput()
|
||||||
|
{
|
||||||
|
// Release the DirectInput interface
|
||||||
|
if (directInput)
|
||||||
|
{
|
||||||
|
directInput->Release();
|
||||||
|
directInput = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload dinput8.dll
|
||||||
|
if (dinput8dll)
|
||||||
|
FreeLibrary(dinput8dll);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool JoystickImpl::isConnectedDInput(unsigned int index)
|
||||||
|
{
|
||||||
|
// Check if a joystick with the given index is in the connected list
|
||||||
|
for (std::vector<JoystickRecord>::iterator i = joystickList.begin(); i != joystickList.end(); ++i)
|
||||||
|
{
|
||||||
|
if (i->index == index)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void JoystickImpl::updateConnectionsDInput()
|
||||||
|
{
|
||||||
|
// Clear plugged flags so we can determine which devices were added/removed
|
||||||
|
for (std::size_t i = 0; i < joystickList.size(); ++i)
|
||||||
|
joystickList[i].plugged = false;
|
||||||
|
|
||||||
|
// Enumerate devices
|
||||||
|
HRESULT result = directInput->EnumDevices(DI8DEVCLASS_GAMECTRL, &JoystickImpl::deviceEnumerationCallback, NULL, DIEDFL_ALLDEVICES);
|
||||||
|
|
||||||
|
// Remove devices that were not connected during the enumeration
|
||||||
|
for (std::vector<JoystickRecord>::iterator i = joystickList.begin(); i != joystickList.end();)
|
||||||
|
{
|
||||||
|
if (!i->plugged)
|
||||||
|
i = joystickList.erase(i);
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
err() << "Failed to enumerate DirectInput devices: " << result << std::endl;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign unused joystick indices to devices that were newly connected
|
||||||
|
for (unsigned int i = 0; i < Joystick::Count; ++i)
|
||||||
|
{
|
||||||
|
for (std::vector<JoystickRecord>::iterator j = joystickList.begin(); j != joystickList.end(); ++j)
|
||||||
|
{
|
||||||
|
if (j->index == i)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (j->index == Joystick::Count)
|
||||||
|
{
|
||||||
|
j->index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool JoystickImpl::openDInput(unsigned int index)
|
||||||
|
{
|
||||||
|
// Initialize DirectInput members
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < Joystick::AxisCount; ++i)
|
||||||
|
m_axes[i] = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < Joystick::ButtonCount; ++i)
|
||||||
|
m_buttons[i] = -1;
|
||||||
|
|
||||||
|
std::memset(&m_deviceCaps, 0, sizeof(DIDEVCAPS));
|
||||||
|
m_deviceCaps.dwSize = sizeof(DIDEVCAPS);
|
||||||
|
|
||||||
|
// Search for a joystick with the given index in the connected list
|
||||||
|
for (std::vector<JoystickRecord>::iterator i = joystickList.begin(); i != joystickList.end(); ++i)
|
||||||
|
{
|
||||||
|
if (i->index == index)
|
||||||
|
{
|
||||||
|
// Create device
|
||||||
|
HRESULT result = directInput->CreateDevice(i->guid, &m_device, NULL);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
err() << "Failed to create DirectInput device: " << result << std::endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool formatInitialized = false;
|
||||||
|
static DIDATAFORMAT format;
|
||||||
|
|
||||||
|
if (!formatInitialized)
|
||||||
|
{
|
||||||
|
const DWORD axisType = DIDFT_AXIS | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
|
||||||
|
const DWORD povType = DIDFT_POV | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
|
||||||
|
const DWORD buttonType = DIDFT_BUTTON | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
|
||||||
|
|
||||||
|
static DIOBJECTDATAFORMAT data[8 + 4 + sf::Joystick::ButtonCount];
|
||||||
|
|
||||||
|
data[0].pguid = &guids::GUID_XAxis;
|
||||||
|
data[0].dwOfs = DIJOFS_X;
|
||||||
|
|
||||||
|
data[1].pguid = &guids::GUID_YAxis;
|
||||||
|
data[1].dwOfs = DIJOFS_Y;
|
||||||
|
|
||||||
|
data[2].pguid = &guids::GUID_ZAxis;
|
||||||
|
data[2].dwOfs = DIJOFS_Z;
|
||||||
|
|
||||||
|
data[3].pguid = &guids::GUID_RxAxis;
|
||||||
|
data[3].dwOfs = DIJOFS_RX;
|
||||||
|
|
||||||
|
data[4].pguid = &guids::GUID_RyAxis;
|
||||||
|
data[4].dwOfs = DIJOFS_RY;
|
||||||
|
|
||||||
|
data[5].pguid = &guids::GUID_RzAxis;
|
||||||
|
data[5].dwOfs = DIJOFS_RZ;
|
||||||
|
|
||||||
|
data[6].pguid = &guids::GUID_Slider;
|
||||||
|
data[6].dwOfs = DIJOFS_SLIDER(0);
|
||||||
|
|
||||||
|
data[7].pguid = &guids::GUID_Slider;
|
||||||
|
data[7].dwOfs = DIJOFS_SLIDER(1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
data[i].dwType = axisType;
|
||||||
|
data[i].dwFlags = DIDOI_ASPECTPOSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
data[8 + i].pguid = &guids::GUID_POV;
|
||||||
|
data[8 + i].dwOfs = static_cast<DWORD>(DIJOFS_POV(i));
|
||||||
|
data[8 + i].dwType = povType;
|
||||||
|
data[8 + i].dwFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sf::Joystick::ButtonCount; ++i)
|
||||||
|
{
|
||||||
|
data[8 + 4 + i].pguid = NULL;
|
||||||
|
data[8 + 4 + i].dwOfs = static_cast<DWORD>(DIJOFS_BUTTON(i));
|
||||||
|
data[8 + 4 + i].dwType = buttonType;
|
||||||
|
data[8 + 4 + i].dwFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
format.dwSize = sizeof(DIDATAFORMAT);
|
||||||
|
format.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
|
||||||
|
format.dwFlags = DIDFT_ABSAXIS;
|
||||||
|
format.dwDataSize = sizeof(DIJOYSTATE);
|
||||||
|
format.dwNumObjs = 8 + 4 + sf::Joystick::ButtonCount;
|
||||||
|
format.rgodf = data;
|
||||||
|
|
||||||
|
formatInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set device data format
|
||||||
|
result = m_device->SetDataFormat(&format);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
err() << "Failed to set DirectInput device data format: " << result << std::endl;
|
||||||
|
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get device capabilities
|
||||||
|
result = m_device->GetCapabilities(&m_deviceCaps);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
err() << "Failed to get DirectInput device capabilities: " << result << std::endl;
|
||||||
|
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set axis mode to absolute
|
||||||
|
DIPROPDWORD property;
|
||||||
|
std::memset(&property, 0, sizeof(property));
|
||||||
|
property.diph.dwSize = sizeof(property);
|
||||||
|
property.diph.dwHeaderSize = sizeof(property.diph);
|
||||||
|
property.diph.dwHow = DIPH_DEVICE;
|
||||||
|
property.dwData = DIPROPAXISMODE_ABS;
|
||||||
|
|
||||||
|
result = m_device->SetProperty(DIPROP_AXISMODE, &property.diph);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
err() << "Failed to set DirectInput device axis mode: " << result << std::endl;
|
||||||
|
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enumerate device objects (axes/povs/buttons)
|
||||||
|
result = m_device->EnumObjects(&JoystickImpl::deviceObjectEnumerationCallback, this, DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
err() << "Failed to enumerate DirectInput device objects: " << result << std::endl;
|
||||||
|
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get friendly product name of the device
|
||||||
|
DIPROPSTRING stringProperty;
|
||||||
|
std::memset(&stringProperty, 0, sizeof(stringProperty));
|
||||||
|
stringProperty.diph.dwSize = sizeof(stringProperty);
|
||||||
|
stringProperty.diph.dwHeaderSize = sizeof(stringProperty.diph);
|
||||||
|
stringProperty.diph.dwHow = DIPH_DEVICE;
|
||||||
|
stringProperty.diph.dwObj = 0;
|
||||||
|
|
||||||
|
if (!m_device->GetProperty(DIPROP_PRODUCTNAME, &stringProperty.diph))
|
||||||
|
{
|
||||||
|
m_identification.name = stringProperty.wsz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get vendor and produce id of the device
|
||||||
|
std::memset(&property, 0, sizeof(property));
|
||||||
|
property.diph.dwSize = sizeof(property);
|
||||||
|
property.diph.dwHeaderSize = sizeof(property.diph);
|
||||||
|
property.diph.dwHow = DIPH_DEVICE;
|
||||||
|
|
||||||
|
if (!m_device->GetProperty(DIPROP_VIDPID, &property.diph))
|
||||||
|
{
|
||||||
|
m_identification.productId = HIWORD(property.dwData);
|
||||||
|
m_identification.vendorId = LOWORD(property.dwData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void JoystickImpl::closeDInput()
|
||||||
|
{
|
||||||
|
if (m_device)
|
||||||
|
{
|
||||||
|
// Release the device
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
JoystickCaps JoystickImpl::getCapabilitiesDInput() const
|
||||||
|
{
|
||||||
|
JoystickCaps caps;
|
||||||
|
|
||||||
|
// Count how many buttons have valid offsets
|
||||||
|
caps.buttonCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < Joystick::ButtonCount; ++i)
|
||||||
|
{
|
||||||
|
if (m_buttons[i] != -1)
|
||||||
|
++caps.buttonCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check which axes have valid offsets
|
||||||
|
for (int i = 0; i < Joystick::AxisCount; ++i)
|
||||||
|
caps.axes[i] = (m_axes[i] != -1);
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
JoystickState JoystickImpl::updateDInput()
|
||||||
|
{
|
||||||
|
JoystickState state;
|
||||||
|
|
||||||
|
if (m_device)
|
||||||
|
{
|
||||||
|
// Poll the device
|
||||||
|
m_device->Poll();
|
||||||
|
|
||||||
|
DIJOYSTATE joystate;
|
||||||
|
|
||||||
|
// Try to get the device state
|
||||||
|
HRESULT result = m_device->GetDeviceState(sizeof(joystate), &joystate);
|
||||||
|
|
||||||
|
// If we have not acquired or have lost the device, attempt to (re-)acquire it and get the device state again
|
||||||
|
if ((result == DIERR_NOTACQUIRED) || (result == DIERR_INPUTLOST))
|
||||||
|
{
|
||||||
|
m_device->Acquire();
|
||||||
|
m_device->Poll();
|
||||||
|
result = m_device->GetDeviceState(sizeof(joystate), &joystate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we still can't get the device state, assume it has been disconnected
|
||||||
|
if ((result == DIERR_NOTACQUIRED) || (result == DIERR_INPUTLOST))
|
||||||
|
{
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
err() << "Failed to get DirectInput device state: " << result << std::endl;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current state of each axis
|
||||||
|
for (int i = 0; i < Joystick::AxisCount; ++i)
|
||||||
|
{
|
||||||
|
if (m_axes[i] != -1)
|
||||||
|
{
|
||||||
|
if (i == Joystick::PovX)
|
||||||
|
{
|
||||||
|
unsigned short value = LOWORD(*reinterpret_cast<const DWORD*>(reinterpret_cast<const char*>(&joystate) + m_axes[i]));
|
||||||
|
|
||||||
|
if (value != 0xFFFF)
|
||||||
|
{
|
||||||
|
float angle = (static_cast<float>(value)) * 3.141592654f / DI_DEGREES / 180.f;
|
||||||
|
|
||||||
|
state.axes[i] = std::sin(angle) * 100.f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.axes[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (i == Joystick::PovY)
|
||||||
|
{
|
||||||
|
unsigned short value = LOWORD(*reinterpret_cast<const DWORD*>(reinterpret_cast<const char*>(&joystate) + m_axes[i]));
|
||||||
|
|
||||||
|
if (value != 0xFFFF)
|
||||||
|
{
|
||||||
|
float angle = (static_cast<float>(value)) * 3.141592654f / DI_DEGREES / 180.f;
|
||||||
|
|
||||||
|
state.axes[i] = std::cos(angle) * 100.f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.axes[i] = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.axes[i] = (static_cast<float>(*reinterpret_cast<const LONG*>(reinterpret_cast<const char*>(&joystate) + m_axes[i])) + 0.5f) * 100.f / 32767.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.axes[i] = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current state of each button
|
||||||
|
for (int i = 0; i < Joystick::ButtonCount; ++i)
|
||||||
|
{
|
||||||
|
if (m_buttons[i] != -1)
|
||||||
|
{
|
||||||
|
BYTE value = *reinterpret_cast<const BYTE*>(reinterpret_cast<const char*>(&joystate) + m_buttons[i]);
|
||||||
|
|
||||||
|
state.buttons[i] = ((value & 0x80) != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.buttons[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
BOOL CALLBACK JoystickImpl::deviceEnumerationCallback(const DIDEVICEINSTANCE* deviceInstance, void*)
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < joystickList.size(); ++i)
|
||||||
|
{
|
||||||
|
if (joystickList[i].guid == deviceInstance->guidInstance)
|
||||||
|
{
|
||||||
|
joystickList[i].plugged = true;
|
||||||
|
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JoystickRecord record = { deviceInstance->guidInstance, sf::Joystick::Count, true };
|
||||||
|
joystickList.push_back(record);
|
||||||
|
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
BOOL CALLBACK JoystickImpl::deviceObjectEnumerationCallback(const DIDEVICEOBJECTINSTANCE* deviceObjectInstance, void* userData)
|
||||||
|
{
|
||||||
|
sf::priv::JoystickImpl& joystick = *reinterpret_cast<sf::priv::JoystickImpl*>(userData);
|
||||||
|
|
||||||
|
if (DIDFT_GETTYPE(deviceObjectInstance->dwType) & DIDFT_AXIS)
|
||||||
|
{
|
||||||
|
// Axes
|
||||||
|
if (deviceObjectInstance->guidType == guids::GUID_XAxis)
|
||||||
|
joystick.m_axes[Joystick::X] = DIJOFS_X;
|
||||||
|
else if (deviceObjectInstance->guidType == guids::GUID_YAxis)
|
||||||
|
joystick.m_axes[Joystick::Y] = DIJOFS_Y;
|
||||||
|
else if (deviceObjectInstance->guidType == guids::GUID_ZAxis)
|
||||||
|
joystick.m_axes[Joystick::Z] = DIJOFS_Z;
|
||||||
|
else if (deviceObjectInstance->guidType == guids::GUID_RzAxis)
|
||||||
|
joystick.m_axes[Joystick::R] = DIJOFS_RZ;
|
||||||
|
else if (deviceObjectInstance->guidType == guids::GUID_RxAxis)
|
||||||
|
joystick.m_axes[Joystick::U] = DIJOFS_RX;
|
||||||
|
else if (deviceObjectInstance->guidType == guids::GUID_RyAxis)
|
||||||
|
joystick.m_axes[Joystick::V] = DIJOFS_RY;
|
||||||
|
else if (deviceObjectInstance->guidType == guids::GUID_Slider)
|
||||||
|
{
|
||||||
|
if(joystick.m_axes[Joystick::U] == -1)
|
||||||
|
joystick.m_axes[Joystick::U] = DIJOFS_SLIDER(0);
|
||||||
|
else
|
||||||
|
joystick.m_axes[Joystick::V] = DIJOFS_SLIDER(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
|
// Set the axis' value range to that of a signed short: [-32768, 32767]
|
||||||
|
DIPROPRANGE propertyRange;
|
||||||
|
|
||||||
|
std::memset(&propertyRange, 0, sizeof(propertyRange));
|
||||||
|
propertyRange.diph.dwSize = sizeof(propertyRange);
|
||||||
|
propertyRange.diph.dwHeaderSize = sizeof(propertyRange.diph);
|
||||||
|
propertyRange.diph.dwObj = deviceObjectInstance->dwType;
|
||||||
|
propertyRange.diph.dwHow = DIPH_BYID;
|
||||||
|
propertyRange.lMin = -32768;
|
||||||
|
propertyRange.lMax = 32767;
|
||||||
|
|
||||||
|
HRESULT result = joystick.m_device->SetProperty(DIPROP_RANGE, &propertyRange.diph);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
err() << "Failed to set DirectInput device axis property range: " << result << std::endl;
|
||||||
|
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
else if (DIDFT_GETTYPE(deviceObjectInstance->dwType) & DIDFT_POV)
|
||||||
|
{
|
||||||
|
// POVs
|
||||||
|
if (deviceObjectInstance->guidType == guids::GUID_POV)
|
||||||
|
{
|
||||||
|
if (joystick.m_axes[Joystick::PovX] == -1)
|
||||||
|
{
|
||||||
|
joystick.m_axes[Joystick::PovX] = DIJOFS_POV(0);
|
||||||
|
joystick.m_axes[Joystick::PovY] = DIJOFS_POV(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
else if (DIDFT_GETTYPE(deviceObjectInstance->dwType) & DIDFT_BUTTON)
|
||||||
|
{
|
||||||
|
// Buttons
|
||||||
|
for (int i = 0; i < Joystick::ButtonCount; ++i)
|
||||||
|
{
|
||||||
|
if (joystick.m_buttons[i] == -1)
|
||||||
|
{
|
||||||
|
joystick.m_buttons[i] = DIJOFS_BUTTON(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -34,13 +34,15 @@
|
|||||||
#ifdef _WIN32_WINNT
|
#ifdef _WIN32_WINNT
|
||||||
#undef _WIN32_WINNT
|
#undef _WIN32_WINNT
|
||||||
#endif
|
#endif
|
||||||
#define _WIN32_WINDOWS 0x0501
|
#define _WIN32_WINDOWS 0x0501
|
||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#define DIRECTINPUT_VERSION 0x0800
|
||||||
#include <SFML/Window/Joystick.hpp>
|
#include <SFML/Window/Joystick.hpp>
|
||||||
#include <SFML/Window/JoystickImpl.hpp>
|
#include <SFML/Window/JoystickImpl.hpp>
|
||||||
#include <SFML/System/String.hpp>
|
#include <SFML/System/String.hpp>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <mmsystem.h>
|
#include <mmsystem.h>
|
||||||
|
#include <dinput.h>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -131,14 +133,100 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
JoystickState update();
|
JoystickState update();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Perform the global initialization of the joystick module (DInput)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void initializeDInput();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Perform the global cleanup of the joystick module (DInput)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void cleanupDInput();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Check if a joystick is currently connected (DInput)
|
||||||
|
///
|
||||||
|
/// \param index Index of the joystick to check
|
||||||
|
///
|
||||||
|
/// \return True if the joystick is connected, false otherwise
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static bool isConnectedDInput(unsigned int index);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Update the connection status of all joysticks (DInput)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void updateConnectionsDInput();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Open the joystick (DInput)
|
||||||
|
///
|
||||||
|
/// \param index Index assigned to the joystick
|
||||||
|
///
|
||||||
|
/// \return True on success, false on failure
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool openDInput(unsigned int index);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Close the joystick (DInput)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void closeDInput();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the joystick capabilities (DInput)
|
||||||
|
///
|
||||||
|
/// \return Joystick capabilities
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
JoystickCaps getCapabilitiesDInput() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Update the joystick and get its new state (DInput)
|
||||||
|
///
|
||||||
|
/// \return Joystick state
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
JoystickState updateDInput();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Device enumeration callback function passed to EnumDevices in updateConnections
|
||||||
|
///
|
||||||
|
/// \param deviceInstance Device object instance
|
||||||
|
/// \param userData User data (unused)
|
||||||
|
///
|
||||||
|
/// \return DIENUM_CONTINUE to continue enumerating devices or DIENUM_STOP to stop
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static BOOL CALLBACK deviceEnumerationCallback(const DIDEVICEINSTANCE* deviceInstance, void* userData);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Device object enumeration callback function passed to EnumObjects in open
|
||||||
|
///
|
||||||
|
/// \param deviceObjectInstance Device object instance
|
||||||
|
/// \param userData User data (pointer to our JoystickImpl object)
|
||||||
|
///
|
||||||
|
/// \return DIENUM_CONTINUE to continue enumerating objects or DIENUM_STOP to stop
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static BOOL CALLBACK deviceObjectEnumerationCallback(const DIDEVICEOBJECTINSTANCE* deviceObjectInstance, void* userData);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int m_index; ///< Index of the joystick
|
unsigned int m_index; ///< Index of the joystick
|
||||||
JOYCAPS m_caps; ///< Joystick capabilities
|
JOYCAPS m_caps; ///< Joystick capabilities
|
||||||
Joystick::Identification m_identification; ///< Joystick identification
|
IDirectInputDevice8W* m_device; ///< DirectInput 8.x device
|
||||||
|
DIDEVCAPS m_deviceCaps; ///< DirectInput device capabilities
|
||||||
|
int m_axes[Joystick::AxisCount]; ///< Offsets to the bytes containing the axes states, -1 if not available
|
||||||
|
int m_buttons[Joystick::ButtonCount]; ///< Offsets to the bytes containing the button states, -1 if not available
|
||||||
|
Joystick::Identification m_identification; ///< Joystick identification
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Utf.hpp>
|
#include <SFML/System/Utf.hpp>
|
||||||
|
#include <Dbt.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@ -56,11 +57,6 @@
|
|||||||
#define MAPVK_VK_TO_VSC (0)
|
#define MAPVK_VK_TO_VSC (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Avoid including <Dbt.h> just for one define
|
|
||||||
#ifndef DBT_DEVNODES_CHANGED
|
|
||||||
#define DBT_DEVNODES_CHANGED 0x0007
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
unsigned int windowCount = 0; // Windows owned by SFML
|
unsigned int windowCount = 0; // Windows owned by SFML
|
||||||
@ -216,6 +212,10 @@ m_cursorGrabbed (m_fullscreen)
|
|||||||
// Create the window
|
// Create the window
|
||||||
m_handle = CreateWindowW(className, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
|
m_handle = CreateWindowW(className, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
|
||||||
|
|
||||||
|
// Register to receive device interface change notifications (used for joystick connection handling)
|
||||||
|
DEV_BROADCAST_HDR deviceBroadcastHeader = {sizeof(DEV_BROADCAST_HDR), DBT_DEVTYP_DEVICEINTERFACE, 0};
|
||||||
|
RegisterDeviceNotification(m_handle, &deviceBroadcastHeader, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
|
||||||
|
|
||||||
// If we're the first window handle, we only need to poll for joysticks when WM_DEVICECHANGE message is received
|
// If we're the first window handle, we only need to poll for joysticks when WM_DEVICECHANGE message is received
|
||||||
if (m_handle)
|
if (m_handle)
|
||||||
{
|
{
|
||||||
@ -983,8 +983,15 @@ void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
case WM_DEVICECHANGE:
|
case WM_DEVICECHANGE:
|
||||||
{
|
{
|
||||||
// Some sort of device change has happened, update joystick connections
|
// Some sort of device change has happened, update joystick connections
|
||||||
if (wParam == DBT_DEVNODES_CHANGED)
|
if ((wParam == DBT_DEVICEARRIVAL) || (wParam == DBT_DEVICEREMOVECOMPLETE))
|
||||||
JoystickImpl::updateConnections();
|
{
|
||||||
|
// Some sort of device change has happened, update joystick connections if it is a device interface
|
||||||
|
DEV_BROADCAST_HDR* deviceBroadcastHeader = reinterpret_cast<DEV_BROADCAST_HDR*>(lParam);
|
||||||
|
|
||||||
|
if (deviceBroadcastHeader && (deviceBroadcastHeader->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
|
||||||
|
JoystickImpl::updateConnections();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user