From 44f9b2232361b75640d77195bed7342a1a9fb4a8 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 19 Dec 2015 21:04:49 +0100 Subject: [PATCH] Gamepad vibration on Windows --- dtool/src/parser-inc/XInput.h | 1 + panda/src/device/xInputDevice.cxx | 38 ++++++++++++++++++++++++++++++- panda/src/device/xInputDevice.h | 4 +++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/dtool/src/parser-inc/XInput.h b/dtool/src/parser-inc/XInput.h index f770cf3d71..21a2802287 100644 --- a/dtool/src/parser-inc/XInput.h +++ b/dtool/src/parser-inc/XInput.h @@ -1,2 +1,3 @@ struct XINPUT_STATE; struct XINPUT_CAPABILITIES; +struct XINPUT_VIBRATION; diff --git a/panda/src/device/xInputDevice.cxx b/panda/src/device/xInputDevice.cxx index 227c5a4b01..290cfb12f3 100644 --- a/panda/src/device/xInputDevice.cxx +++ b/panda/src/device/xInputDevice.cxx @@ -63,11 +63,13 @@ struct XINPUT_BUSINFO { }; typedef DWORD (*pXInputGetState)(DWORD, XINPUT_STATE *); +typedef DWORD (*pXInputSetState)(DWORD, XINPUT_VIBRATION *); typedef DWORD (*pXInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES *); typedef DWORD (*pXInputGetBatteryInformation)(DWORD, BYTE, XINPUT_BATTERY_INFORMATION *); typedef DWORD (*pXInputGetBaseBusInformation)(DWORD, XINPUT_BUSINFO *); static pXInputGetState get_state = NULL; +static pXInputSetState set_state = NULL; static pXInputGetCapabilities get_capabilities = NULL; static pXInputGetBatteryInformation get_battery_information = NULL; static pXInputGetBaseBusInformation get_base_bus_information = NULL; @@ -132,6 +134,17 @@ XInputDevice(DWORD user_index) : } } +//////////////////////////////////////////////////////////////////// +// Function: XInputDevice::Constructor +// Access: Published +// Description: Creates a new device using the Linux joystick +// device using the given device filename. +//////////////////////////////////////////////////////////////////// +XInputDevice:: +~XInputDevice() { + do_set_vibration(0, 0); +} + //////////////////////////////////////////////////////////////////// // Function: XInputDevice::detect // Access: Public @@ -210,6 +223,13 @@ init_xinput() { } } + set_state = (pXInputSetState)GetProcAddress(module, "XInputSetState"); + if (set_state == NULL) { + device_cat.error() + << "Failed to find function XInputSetState in " << dll_name << ".\n"; + return false; + } + get_capabilities = (pXInputGetCapabilities)GetProcAddress(module, "XInputGetCapabilities"); if (get_capabilities == NULL) { device_cat.error() @@ -234,7 +254,7 @@ init_xinput() { // just connected. //////////////////////////////////////////////////////////////////// void XInputDevice:: -init_device(XINPUT_CAPABILITIES &caps, XINPUT_STATE &state) { +init_device(const XINPUT_CAPABILITIES &caps, const XINPUT_STATE &state) { if (caps.Type == XINPUT_DEVTYPE_GAMEPAD) { _device_class = DC_gamepad; } else { @@ -324,6 +344,22 @@ init_device(XINPUT_CAPABILITIES &caps, XINPUT_STATE &state) { _last_packet = state.dwPacketNumber; } +//////////////////////////////////////////////////////////////////// +// Function: XInputDevice::do_set_vibration +// Access: Private, Virtual +// Description: Sets the vibration strength. The first argument +// controls a low-frequency motor, if present, and +// the latter controls a high-frequency motor. The +// values are within the 0-1 range. +//////////////////////////////////////////////////////////////////// +void XInputDevice:: +do_set_vibration(double strong, double weak) { + XINPUT_VIBRATION vibration; + vibration.wLeftMotorSpeed = strong * 0xffff; + vibration.wRightMotorSpeed = weak * 0xffff; + set_state(_index, &vibration); +} + //////////////////////////////////////////////////////////////////// // Function: InputDevice::do_poll // Access: Public, Virtual diff --git a/panda/src/device/xInputDevice.h b/panda/src/device/xInputDevice.h index fea8cd082f..3bfc9fe728 100644 --- a/panda/src/device/xInputDevice.h +++ b/panda/src/device/xInputDevice.h @@ -33,12 +33,14 @@ typedef struct _XINPUT_STATE XINPUT_STATE; class EXPCL_PANDA_DEVICE XInputDevice FINAL : public InputDevice { public: XInputDevice(DWORD user_index); + ~XInputDevice(); void detect(InputDeviceManager *mgr); static bool init_xinput(); private: - void init_device(XINPUT_CAPABILITIES &caps, XINPUT_STATE &state); + void init_device(const XINPUT_CAPABILITIES &caps, const XINPUT_STATE &state); + virtual void do_set_vibration(double strong, double weak); virtual void do_poll(); private: