From a630f36d0061adbdb5eb46621cc9a257a8d394a6 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 12 Apr 2020 11:26:14 -0400 Subject: [PATCH] add windows gamepad rumble implementation --- include/GLFW/glfw3.h | 31 +++++++++++++++++++++++++++++++ src/input.c | 28 ++++++++++++++++++++++++++++ src/internal.h | 1 + src/win32_init.c | 2 ++ src/win32_joystick.c | 13 +++++++++++++ src/win32_platform.h | 3 +++ 6 files changed, 78 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index e5b9b6c64..cd6b53b5a 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -5348,6 +5348,37 @@ GLFWAPI const char* glfwGetGamepadName(int jid); */ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state); +/*! @brief Sets the specified gamepad's vibration effect intensity. + * + * This function sends vibration data to the specified Xbox-like gamepad. + * + * Vibration intensity is a value between 0.0 and 1.0 inclusive, where 0.0 is no + * vibration, and 1.0 is maximum vibration. It is set separately for the + * gamepad's low frequency and high frequency rumble motors. + * + * If the specified gamepad is not present or does not support the rumble + * effect, this function will return `GLFW_FALSE` but will not generate an + * error. + * + * @param[in] jid The [joystick](@ref joysticks) to vibrate. + * @param[in] slowMotorSpeed The low frequency rumble intensity. + * @param[in] fastMotorSpeed The high frequency rumble intensity. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is + * connected, or the joystick does not support the rumble effect. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwUpdateGamepadMappings + * @sa @ref glfwJoystickIsGamepad + * + * @ingroup input + */ +GLFWAPI int glfwSetGamepadRumble(int jid, float slowMotorSpeed, float fastMotorSpeed); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded diff --git a/src/input.c b/src/input.c index f6163093c..35fbb072c 100644 --- a/src/input.c +++ b/src/input.c @@ -1312,6 +1312,34 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state) return GLFW_TRUE; } +GLFWAPI int glfwSetGamepadRumble(int jid, float slowMotorSpeed, float fastMotorSpeed) +{ + _GLFWjoystick* js; + + assert(jid >= GLFW_JOYSTICK_1); + assert(jid <= GLFW_JOYSTICK_LAST); + + _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); + + if (jid < 0 || jid > GLFW_JOYSTICK_LAST) + { + _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); + return GLFW_FALSE; + } + + js = _glfw.joysticks + jid; + if (!js->present) + return GLFW_FALSE; + + slowMotorSpeed = slowMotorSpeed < 0.0f ? 0.0f : slowMotorSpeed; + slowMotorSpeed = slowMotorSpeed > 1.0f ? 1.0f : slowMotorSpeed; + + fastMotorSpeed = fastMotorSpeed < 0.0f ? 0.0f : fastMotorSpeed; + fastMotorSpeed = fastMotorSpeed > 1.0f ? 1.0f : fastMotorSpeed; + + return _glfwPlatformSetGamepadRumble(js, slowMotorSpeed, fastMotorSpeed); +} + GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) { assert(string != NULL); diff --git a/src/internal.h b/src/internal.h index 6d7587c8c..99f7f3f76 100644 --- a/src/internal.h +++ b/src/internal.h @@ -628,6 +628,7 @@ const char* _glfwPlatformGetClipboardString(void); int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode); void _glfwPlatformUpdateGamepadGUID(char* guid); +int _glfwPlatformSetGamepadRumble(_GLFWjoystick* js, float slowMotorSpeed, float fastMotorSpeed); uint64_t _glfwPlatformGetTimerValue(void); uint64_t _glfwPlatformGetTimerFrequency(void); diff --git a/src/win32_init.c b/src/win32_init.c index 260e888e9..4ea6ef3ef 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -128,6 +128,8 @@ static GLFWbool loadLibraries(void) GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities"); _glfw.win32.xinput.GetState = (PFN_XInputGetState) GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState"); + _glfw.win32.xinput.SetState = (PFN_XInputSetState) + GetProcAddress(_glfw.win32.xinput.instance, "XInputSetState"); break; } diff --git a/src/win32_joystick.c b/src/win32_joystick.c index c19f77c5d..e707d7b08 100644 --- a/src/win32_joystick.c +++ b/src/win32_joystick.c @@ -753,3 +753,16 @@ void _glfwPlatformUpdateGamepadGUID(char* guid) } } +int _glfwPlatformSetGamepadRumble(_GLFWjoystick* js, float slowMotorSpeed, float fastMotorSpeed) +{ + if (js->win32.device) + return GLFW_FALSE; + + XINPUT_VIBRATION effect; + ZeroMemory(&effect, sizeof(XINPUT_VIBRATION)); + + effect.wLeftMotorSpeed = (WORD)(65535.0f * slowMotorSpeed); + effect.wRightMotorSpeed = (WORD)(65535.0f * fastMotorSpeed); + + return (int) (XInputSetState(js->win32.index, &effect) == ERROR_SUCCESS); +} \ No newline at end of file diff --git a/src/win32_platform.h b/src/win32_platform.h index 2b00b0018..ac84313a7 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -222,8 +222,10 @@ typedef DWORD (WINAPI * PFN_timeGetTime)(void); // xinput.dll function pointer typedefs typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*); typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); +typedef DWORD (WINAPI * PFN_XInputSetState)(DWORD,XINPUT_VIBRATION*); #define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities #define XInputGetState _glfw.win32.xinput.GetState +#define XInputSetState _glfw.win32.xinput.SetState // dinput8.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN); @@ -357,6 +359,7 @@ typedef struct _GLFWlibraryWin32 HINSTANCE instance; PFN_XInputGetCapabilities GetCapabilities; PFN_XInputGetState GetState; + PFN_XInputSetState SetState; } xinput; struct {