|
|
|
@ -31,9 +31,6 @@ |
|
|
|
|
|
|
|
|
|
#include <initguid.h> |
|
|
|
|
|
|
|
|
|
#define _GLFW_PRESENCE_ONLY 1 |
|
|
|
|
#define _GLFW_UPDATE_STATE 2 |
|
|
|
|
|
|
|
|
|
#define _GLFW_TYPE_AXIS 0 |
|
|
|
|
#define _GLFW_TYPE_SLIDER 1 |
|
|
|
|
#define _GLFW_TYPE_BUTTON 2 |
|
|
|
@ -238,21 +235,16 @@ static GLFWbool supportsXInput(const GUID* guid) |
|
|
|
|
|
|
|
|
|
// Frees all resources associated with the specified joystick
|
|
|
|
|
//
|
|
|
|
|
static void closeJoystick(_GLFWjoystickWin32* js) |
|
|
|
|
static void closeJoystick(_GLFWjoystick* js) |
|
|
|
|
{ |
|
|
|
|
if (js->device) |
|
|
|
|
if (js->win32.device) |
|
|
|
|
{ |
|
|
|
|
IDirectInputDevice8_Unacquire(js->device); |
|
|
|
|
IDirectInputDevice8_Release(js->device); |
|
|
|
|
IDirectInputDevice8_Unacquire(js->win32.device); |
|
|
|
|
IDirectInputDevice8_Release(js->win32.device); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
free(js->name); |
|
|
|
|
free(js->axes); |
|
|
|
|
free(js->buttons); |
|
|
|
|
free(js->objects); |
|
|
|
|
memset(js, 0, sizeof(_GLFWjoystickWin32)); |
|
|
|
|
|
|
|
|
|
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED); |
|
|
|
|
_glfwFreeJoystick(js); |
|
|
|
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_DISCONNECTED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DirectInput device object enumeration callback
|
|
|
|
@ -337,23 +329,17 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user) |
|
|
|
|
DIPROPDWORD dipd; |
|
|
|
|
IDirectInputDevice8* device; |
|
|
|
|
_GLFWobjenumWin32 data; |
|
|
|
|
_GLFWjoystickWin32* js; |
|
|
|
|
_GLFWjoystick* js; |
|
|
|
|
char name[256]; |
|
|
|
|
|
|
|
|
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
{ |
|
|
|
|
if (memcmp(&_glfw.win32_js[jid].guid, &di->guidInstance, sizeof(GUID)) == 0) |
|
|
|
|
if (!_glfw.joysticks[jid].present) |
|
|
|
|
continue; |
|
|
|
|
if (memcmp(&_glfw.joysticks[jid].win32.guid, &di->guidInstance, sizeof(GUID)) == 0) |
|
|
|
|
return DIENUM_CONTINUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
{ |
|
|
|
|
if (!_glfw.win32_js[jid].present) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (jid > GLFW_JOYSTICK_LAST) |
|
|
|
|
return DIENUM_STOP; |
|
|
|
|
|
|
|
|
|
if (supportsXInput(&di->guidProduct)) |
|
|
|
|
return DIENUM_CONTINUE; |
|
|
|
|
|
|
|
|
@ -426,89 +412,168 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user) |
|
|
|
|
sizeof(_GLFWjoyobjectWin32), |
|
|
|
|
compareJoystickObjects); |
|
|
|
|
|
|
|
|
|
js = _glfw.win32_js + jid; |
|
|
|
|
js->device = device; |
|
|
|
|
js->guid = di->guidInstance; |
|
|
|
|
js->axisCount = data.axisCount + data.sliderCount; |
|
|
|
|
js->axes = calloc(js->axisCount, sizeof(float)); |
|
|
|
|
js->buttonCount += data.buttonCount + data.povCount * 4; |
|
|
|
|
js->buttons = calloc(js->buttonCount, 1); |
|
|
|
|
js->objects = data.objects; |
|
|
|
|
js->objectCount = data.objectCount; |
|
|
|
|
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName); |
|
|
|
|
js->present = GLFW_TRUE; |
|
|
|
|
|
|
|
|
|
_glfwInputJoystickChange(jid, GLFW_CONNECTED); |
|
|
|
|
if (!WideCharToMultiByte(CP_UTF8, 0, |
|
|
|
|
di->tszInstanceName, -1, |
|
|
|
|
name, sizeof(name), |
|
|
|
|
NULL, NULL)) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Win32: Failed to convert joystick name to UTF-8"); |
|
|
|
|
|
|
|
|
|
IDirectInputDevice8_Release(device); |
|
|
|
|
free(data.objects); |
|
|
|
|
return DIENUM_STOP; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
js = _glfwAllocJoystick(name, |
|
|
|
|
data.axisCount + data.sliderCount, |
|
|
|
|
data.buttonCount + data.povCount * 4); |
|
|
|
|
if (!js) |
|
|
|
|
{ |
|
|
|
|
IDirectInputDevice8_Release(device); |
|
|
|
|
free(data.objects); |
|
|
|
|
return DIENUM_STOP; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
js->win32.device = device; |
|
|
|
|
js->win32.guid = di->guidInstance; |
|
|
|
|
js->win32.objects = data.objects; |
|
|
|
|
js->win32.objectCount = data.objectCount; |
|
|
|
|
|
|
|
|
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_CONNECTED); |
|
|
|
|
return DIENUM_CONTINUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Attempt to open the specified joystick device
|
|
|
|
|
// TODO: Pack state arrays for non-gamepad devices
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
////// GLFW internal API //////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Initialize joystick interface
|
|
|
|
|
//
|
|
|
|
|
static GLFWbool openXinputDevice(DWORD index) |
|
|
|
|
void _glfwInitJoysticksWin32(void) |
|
|
|
|
{ |
|
|
|
|
int jid; |
|
|
|
|
XINPUT_CAPABILITIES xic; |
|
|
|
|
_GLFWjoystickWin32* js; |
|
|
|
|
|
|
|
|
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
if (_glfw.win32.dinput8.instance) |
|
|
|
|
{ |
|
|
|
|
if (_glfw.win32_js[jid].present && |
|
|
|
|
_glfw.win32_js[jid].device == NULL && |
|
|
|
|
_glfw.win32_js[jid].index == index) |
|
|
|
|
if (FAILED(DirectInput8Create(GetModuleHandle(NULL), |
|
|
|
|
DIRECTINPUT_VERSION, |
|
|
|
|
&IID_IDirectInput8W, |
|
|
|
|
(void**) &_glfw.win32.dinput8.api, |
|
|
|
|
NULL))) |
|
|
|
|
{ |
|
|
|
|
return GLFW_FALSE; |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Win32: Failed to create interface"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
_glfwDetectJoystickConnectionWin32(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Close all opened joystick handles
|
|
|
|
|
//
|
|
|
|
|
void _glfwTerminateJoysticksWin32(void) |
|
|
|
|
{ |
|
|
|
|
int jid; |
|
|
|
|
|
|
|
|
|
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
closeJoystick(_glfw.joysticks + jid); |
|
|
|
|
|
|
|
|
|
if (_glfw.win32.dinput8.api) |
|
|
|
|
IDirectInput8_Release(_glfw.win32.dinput8.api); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Checks for new joysticks after DBT_DEVICEARRIVAL
|
|
|
|
|
//
|
|
|
|
|
void _glfwDetectJoystickConnectionWin32(void) |
|
|
|
|
{ |
|
|
|
|
if (_glfw.win32.xinput.instance) |
|
|
|
|
{ |
|
|
|
|
if (!_glfw.win32_js[jid].present) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
DWORD index; |
|
|
|
|
|
|
|
|
|
if (jid > GLFW_JOYSTICK_LAST) |
|
|
|
|
return GLFW_FALSE; |
|
|
|
|
for (index = 0; index < XUSER_MAX_COUNT; index++) |
|
|
|
|
{ |
|
|
|
|
int jid; |
|
|
|
|
XINPUT_CAPABILITIES xic; |
|
|
|
|
_GLFWjoystick* js; |
|
|
|
|
|
|
|
|
|
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS) |
|
|
|
|
return GLFW_FALSE; |
|
|
|
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
{ |
|
|
|
|
if (_glfw.joysticks[jid].present && |
|
|
|
|
_glfw.joysticks[jid].win32.device == NULL && |
|
|
|
|
_glfw.joysticks[jid].win32.index == index) |
|
|
|
|
{ |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
js = _glfw.win32_js + jid; |
|
|
|
|
js->axisCount = 6; |
|
|
|
|
js->axes = calloc(js->axisCount, sizeof(float)); |
|
|
|
|
js->buttonCount = 14; |
|
|
|
|
js->buttons = calloc(js->buttonCount, 1); |
|
|
|
|
js->present = GLFW_TRUE; |
|
|
|
|
js->name = strdup(getDeviceDescription(&xic)); |
|
|
|
|
js->index = index; |
|
|
|
|
if (jid <= GLFW_JOYSTICK_LAST) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
_glfwInputJoystickChange(jid, GLFW_CONNECTED); |
|
|
|
|
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
return GLFW_TRUE; |
|
|
|
|
js = _glfwAllocJoystick(getDeviceDescription(&xic), 6, 14); |
|
|
|
|
if (!js) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
js->win32.index = index; |
|
|
|
|
|
|
|
|
|
_glfwInputJoystick(_GLFW_JOYSTICK_ID(js), GLFW_CONNECTED); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfw.win32.dinput8.api) |
|
|
|
|
{ |
|
|
|
|
if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api, |
|
|
|
|
DI8DEVCLASS_GAMECTRL, |
|
|
|
|
deviceCallback, |
|
|
|
|
NULL, |
|
|
|
|
DIEDFL_ALLDEVICES))) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Failed to enumerate DirectInput8 devices"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Polls for and processes events the specified joystick
|
|
|
|
|
// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
|
|
|
|
|
//
|
|
|
|
|
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode) |
|
|
|
|
void _glfwDetectJoystickDisconnectionWin32(void) |
|
|
|
|
{ |
|
|
|
|
if (!js->present) |
|
|
|
|
return GLFW_FALSE; |
|
|
|
|
int jid; |
|
|
|
|
|
|
|
|
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
{ |
|
|
|
|
if (_glfw.joysticks[jid].present) |
|
|
|
|
_glfwPlatformPollJoystick(jid, _GLFW_POLL_PRESENCE); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
////// GLFW platform API //////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
int _glfwPlatformPollJoystick(int jid, int mode) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoystick* js = _glfw.joysticks + jid; |
|
|
|
|
|
|
|
|
|
if (js->device) |
|
|
|
|
if (js->win32.device) |
|
|
|
|
{ |
|
|
|
|
int i, j, ai = 0, bi = 0; |
|
|
|
|
HRESULT result; |
|
|
|
|
DIJOYSTATE state; |
|
|
|
|
|
|
|
|
|
IDirectInputDevice8_Poll(js->device); |
|
|
|
|
result = IDirectInputDevice8_GetDeviceState(js->device, |
|
|
|
|
IDirectInputDevice8_Poll(js->win32.device); |
|
|
|
|
result = IDirectInputDevice8_GetDeviceState(js->win32.device, |
|
|
|
|
sizeof(state), |
|
|
|
|
&state); |
|
|
|
|
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST) |
|
|
|
|
{ |
|
|
|
|
IDirectInputDevice8_Acquire(js->device); |
|
|
|
|
IDirectInputDevice8_Poll(js->device); |
|
|
|
|
result = IDirectInputDevice8_GetDeviceState(js->device, |
|
|
|
|
IDirectInputDevice8_Acquire(js->win32.device); |
|
|
|
|
IDirectInputDevice8_Poll(js->win32.device); |
|
|
|
|
result = IDirectInputDevice8_GetDeviceState(js->win32.device, |
|
|
|
|
sizeof(state), |
|
|
|
|
&state); |
|
|
|
|
} |
|
|
|
@ -519,29 +584,29 @@ static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode) |
|
|
|
|
return GLFW_FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (mode == _GLFW_PRESENCE_ONLY) |
|
|
|
|
if (mode == _GLFW_POLL_PRESENCE) |
|
|
|
|
return GLFW_TRUE; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < js->objectCount; i++) |
|
|
|
|
for (i = 0; i < js->win32.objectCount; i++) |
|
|
|
|
{ |
|
|
|
|
const void* data = (char*) &state + js->objects[i].offset; |
|
|
|
|
const void* data = (char*) &state + js->win32.objects[i].offset; |
|
|
|
|
|
|
|
|
|
switch (js->objects[i].type) |
|
|
|
|
switch (js->win32.objects[i].type) |
|
|
|
|
{ |
|
|
|
|
case _GLFW_TYPE_AXIS: |
|
|
|
|
case _GLFW_TYPE_SLIDER: |
|
|
|
|
{ |
|
|
|
|
js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f; |
|
|
|
|
const float value = (*((LONG*) data) + 0.5f) / 32767.5f; |
|
|
|
|
_glfwInputJoystickAxis(jid, ai, value); |
|
|
|
|
ai++; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case _GLFW_TYPE_BUTTON: |
|
|
|
|
{ |
|
|
|
|
if (*((BYTE*) data) & 0x80) |
|
|
|
|
js->buttons[bi++] = GLFW_PRESS; |
|
|
|
|
else |
|
|
|
|
js->buttons[bi++] = GLFW_RELEASE; |
|
|
|
|
|
|
|
|
|
const char value = (*((BYTE*) data) & 0x80) != 0; |
|
|
|
|
_glfwInputJoystickButton(jid, bi, value); |
|
|
|
|
bi++; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -549,30 +614,28 @@ static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode) |
|
|
|
|
{ |
|
|
|
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; |
|
|
|
|
// Screams of horror are appropriate at this point
|
|
|
|
|
int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES); |
|
|
|
|
if (value < 0 || value > 8) |
|
|
|
|
value = 8; |
|
|
|
|
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES); |
|
|
|
|
if (state < 0 || state > 8) |
|
|
|
|
state = 8; |
|
|
|
|
|
|
|
|
|
for (j = 0; j < 4; j++) |
|
|
|
|
{ |
|
|
|
|
if (directions[value] & (1 << j)) |
|
|
|
|
js->buttons[bi++] = GLFW_PRESS; |
|
|
|
|
else |
|
|
|
|
js->buttons[bi++] = GLFW_RELEASE; |
|
|
|
|
const char value = (directions[state] & (1 << j)) != 0; |
|
|
|
|
_glfwInputJoystickButton(jid, bi, value); |
|
|
|
|
bi++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return GLFW_TRUE; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
DWORD result; |
|
|
|
|
XINPUT_STATE xis; |
|
|
|
|
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f }; |
|
|
|
|
const WORD buttons[14] = |
|
|
|
|
{ |
|
|
|
|
XINPUT_GAMEPAD_A, |
|
|
|
@ -591,7 +654,7 @@ static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode) |
|
|
|
|
XINPUT_GAMEPAD_DPAD_LEFT |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
result = XInputGetState(js->index, &xis); |
|
|
|
|
result = XInputGetState(js->win32.index, &xis); |
|
|
|
|
if (result != ERROR_SUCCESS) |
|
|
|
|
{ |
|
|
|
|
if (result == ERROR_DEVICE_NOT_CONNECTED) |
|
|
|
@ -600,7 +663,7 @@ static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode) |
|
|
|
|
return GLFW_FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (mode == _GLFW_PRESENCE_ONLY) |
|
|
|
|
if (mode == _GLFW_POLL_PRESENCE) |
|
|
|
|
return GLFW_TRUE; |
|
|
|
|
|
|
|
|
|
if ((float) xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX + |
|
|
|
@ -608,13 +671,8 @@ static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode) |
|
|
|
|
(float) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE * |
|
|
|
|
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) |
|
|
|
|
{ |
|
|
|
|
js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f; |
|
|
|
|
js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
js->axes[0] = 0.f; |
|
|
|
|
js->axes[1] = 0.f; |
|
|
|
|
axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f; |
|
|
|
|
axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((float) xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX + |
|
|
|
@ -622,144 +680,26 @@ static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode) |
|
|
|
|
(float) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE * |
|
|
|
|
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) |
|
|
|
|
{ |
|
|
|
|
js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f; |
|
|
|
|
js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
js->axes[2] = 0.f; |
|
|
|
|
js->axes[3] = 0.f; |
|
|
|
|
axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f; |
|
|
|
|
axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) |
|
|
|
|
js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f; |
|
|
|
|
else |
|
|
|
|
js->axes[4] = -1.f; |
|
|
|
|
axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f; |
|
|
|
|
|
|
|
|
|
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) |
|
|
|
|
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f; |
|
|
|
|
else |
|
|
|
|
js->axes[5] = -1.f; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < 14; i++) |
|
|
|
|
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0; |
|
|
|
|
|
|
|
|
|
return GLFW_TRUE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
////// GLFW internal API //////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Initialize joystick interface
|
|
|
|
|
//
|
|
|
|
|
void _glfwInitJoysticksWin32(void) |
|
|
|
|
{ |
|
|
|
|
if (_glfw.win32.dinput8.instance) |
|
|
|
|
{ |
|
|
|
|
if (FAILED(DirectInput8Create(GetModuleHandle(NULL), |
|
|
|
|
DIRECTINPUT_VERSION, |
|
|
|
|
&IID_IDirectInput8W, |
|
|
|
|
(void**) &_glfw.win32.dinput8.api, |
|
|
|
|
NULL))) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Win32: Failed to create interface"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f; |
|
|
|
|
|
|
|
|
|
_glfwDetectJoystickConnectionWin32(); |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < 6; i++) |
|
|
|
|
_glfwInputJoystickAxis(jid, i, axes[i]); |
|
|
|
|
|
|
|
|
|
// Close all opened joystick handles
|
|
|
|
|
//
|
|
|
|
|
void _glfwTerminateJoysticksWin32(void) |
|
|
|
|
{ |
|
|
|
|
int jid; |
|
|
|
|
|
|
|
|
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
closeJoystick(_glfw.win32_js + jid); |
|
|
|
|
|
|
|
|
|
if (_glfw.win32.dinput8.api) |
|
|
|
|
IDirectInput8_Release(_glfw.win32.dinput8.api); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Checks for new joysticks after DBT_DEVICEARRIVAL
|
|
|
|
|
//
|
|
|
|
|
void _glfwDetectJoystickConnectionWin32(void) |
|
|
|
|
{ |
|
|
|
|
if (_glfw.win32.xinput.instance) |
|
|
|
|
{ |
|
|
|
|
DWORD i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < XUSER_MAX_COUNT; i++) |
|
|
|
|
openXinputDevice(i); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfw.win32.dinput8.api) |
|
|
|
|
{ |
|
|
|
|
if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api, |
|
|
|
|
DI8DEVCLASS_GAMECTRL, |
|
|
|
|
deviceCallback, |
|
|
|
|
NULL, |
|
|
|
|
DIEDFL_ALLDEVICES))) |
|
|
|
|
for (i = 0; i < 14; i++) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Failed to enumerate DirectInput8 devices"); |
|
|
|
|
return; |
|
|
|
|
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0; |
|
|
|
|
_glfwInputJoystickButton(jid, i, value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
|
|
|
|
|
//
|
|
|
|
|
void _glfwDetectJoystickDisconnectionWin32(void) |
|
|
|
|
{ |
|
|
|
|
int jid; |
|
|
|
|
|
|
|
|
|
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) |
|
|
|
|
pollJoystickState(_glfw.win32_js + jid, _GLFW_PRESENCE_ONLY); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
////// GLFW platform API //////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
int _glfwPlatformJoystickPresent(int jid) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoystickWin32* js = _glfw.win32_js + jid; |
|
|
|
|
return pollJoystickState(js, _GLFW_PRESENCE_ONLY); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const float* _glfwPlatformGetJoystickAxes(int jid, int* count) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoystickWin32* js = _glfw.win32_js + jid; |
|
|
|
|
if (!pollJoystickState(js, _GLFW_UPDATE_STATE)) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
*count = js->axisCount; |
|
|
|
|
return js->axes; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const unsigned char* _glfwPlatformGetJoystickButtons(int jid, int* count) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoystickWin32* js = _glfw.win32_js + jid; |
|
|
|
|
if (!pollJoystickState(js, _GLFW_UPDATE_STATE)) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
*count = js->buttonCount; |
|
|
|
|
return js->buttons; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char* _glfwPlatformGetJoystickName(int jid) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoystickWin32* js = _glfw.win32_js + jid; |
|
|
|
|
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY)) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
return js->name; |
|
|
|
|
return GLFW_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|