cgv
Loading...
Searching...
No Matches
xinput_gamepad_driver.cxx
1#ifdef WIN32
2
3#include <cassert>
4#include "gamepad_driver.h"
5#include <Windows.h>
6#include <Xinput.h>
7
8#ifdef WIN32
9#pragma warning (disable:4995)
10#endif
11
12using namespace gamepad;
13
15float convert(BYTE value) { return (float)value / 255; }
16float convert(SHORT value) { return value > 0 ? (float)value / 32767 : (float)value / 32768; }
17float convert(WORD value) { return (float)value / 65535; }
18
19// encode user index in handle
20void* get_handle(int user_index)
21{
22 void* device_handle = 0;
23 (int&)device_handle = user_index;
24 return device_handle;
25}
26
27// decode user index from handle
28int get_user_index(void* device_handle)
29{
30 int user_index = (int&)device_handle;
31 assert(user_index >= 0 && user_index < 4);
32 return user_index;
33}
34
35struct xinput_gamepad_driver : public gamepad_driver
36{
37 bool enabled[4];
39 xinput_gamepad_driver(const std::string& options)
40 {
41 for (unsigned user_index = 0; user_index < 4; ++user_index)
42 enabled[user_index] = true;
43 }
45 std::string get_name()
46 {
47 return "XInput Gamepad Driver";
48 }
50 void set_driver_state(bool enabled)
51 {
52 XInputEnable(enabled ? TRUE : FALSE);
53 }
55 void scan_devices(std::vector<device_info>& infos)
56 {
57 XINPUT_CAPABILITIES caps;
58 unsigned nr_devices = 0;
59 for (unsigned user_index = 0; user_index < 4; ++user_index) {
60 DWORD result = XInputGetCapabilities(user_index, XINPUT_FLAG_GAMEPAD, &caps);
61 if (result == ERROR_DEVICE_NOT_CONNECTED) {
62 enabled[user_index] = false;
63 continue;
64 }
65 enabled[user_index] = true;
66 infos.resize(infos.size() + 1);
67 infos.back().device_handle = get_handle(user_index);
68 infos.back().enabled = true;
69 infos.back().force_feedback_support = (caps.Flags | XINPUT_CAPS_FFB_SUPPORTED) != 0;
70 infos.back().is_wireless = (caps.Flags | XINPUT_CAPS_WIRELESS) != 0;
71 infos.back().no_menu_buttons = (caps.Flags | XINPUT_CAPS_NO_NAVIGATION) != 0;
72 infos.back().name = std::string("controler_");
73 infos.back().name += '0' + user_index;
74 infos.back().vibration_strength[0] = convert(caps.Vibration.wLeftMotorSpeed);
75 infos.back().vibration_strength[1] = convert(caps.Vibration.wRightMotorSpeed);
76 }
77 }
79 void set_device_state(void* device_handle, bool _enabled)
80 {
81 enabled[get_user_index(device_handle)] = _enabled;
82 }
84 bool get_device_battery_info(void* device_handle, BatteryType& battery_type, float& fill_state)
85 {
86 int user_index = get_user_index(device_handle);
87 XINPUT_BATTERY_INFORMATION battery_info;
88 DWORD result = XInputGetBatteryInformation(user_index, BATTERY_DEVTYPE_GAMEPAD, &battery_info);
89 if (result == ERROR_DEVICE_NOT_CONNECTED)
90 return false;
91 switch (battery_info.BatteryType) {
92 case BATTERY_TYPE_DISCONNECTED: return false;
93 case BATTERY_TYPE_WIRED: battery_type = BT_WIRED; break;
94 case BATTERY_TYPE_ALKALINE: battery_type = BT_ALKALINE; break;
95 case BATTERY_TYPE_NIMH: battery_type = BT_NIMH; break;
96 case BATTERY_TYPE_UNKNOWN: battery_type = BT_UNKNOWN; break;
97 }
98
99 switch (battery_info.BatteryLevel) {
100 case BATTERY_LEVEL_EMPTY: fill_state = 0.0f; break;
101 case BATTERY_LEVEL_LOW: fill_state = 0.2f; break;
102 case BATTERY_LEVEL_MEDIUM: fill_state = 0.5f; break;
103 case BATTERY_LEVEL_FULL: fill_state = 1.0f; break;
104 }
105 return true;
106 }
108 bool query_device_key_event(void* device_handle, GamepadKeys& gk, KeyAction& action)
109 {
110 XINPUT_KEYSTROKE keystroke;
111 DWORD result = XInputGetKeystroke(get_user_index(device_handle), 0, &keystroke);
112 if (result == ERROR_DEVICE_NOT_CONNECTED)
113 return false;
114 if (result == ERROR_EMPTY)
115 return false;
116 switch (keystroke.VirtualKey) {
117 case VK_PAD_A: gk = GPK_A; break;
118 case VK_PAD_B: gk = GPK_B; break;
119 case VK_PAD_X: gk = GPK_X; break;
120 case VK_PAD_Y: gk = GPK_Y; break;
121 case VK_PAD_RSHOULDER: gk = GPK_RIGHT_BUMPER; break;
122 case VK_PAD_LSHOULDER: gk = GPK_LEFT_BUMPER; break;
123 case VK_PAD_LTRIGGER: gk = GPK_LEFT_TRIGGER; break;
124 case VK_PAD_RTRIGGER: gk = GPK_RIGHT_TRIGGER; break;
125 case VK_PAD_DPAD_UP: gk = GPK_DPAD_UP; break;
126 case VK_PAD_DPAD_DOWN: gk = GPK_DPAD_DOWN; break;
127 case VK_PAD_DPAD_LEFT: gk = GPK_DPAD_LEFT; break;
128 case VK_PAD_DPAD_RIGHT: gk = GPK_DPAD_RIGHT; break;
129 case VK_PAD_START: gk = GPK_START; break;
130 case VK_PAD_BACK: gk = GPK_BACK; break;
131 case VK_PAD_LTHUMB_PRESS: gk = GPK_LEFT_STICK_PRESS; break;
132 case VK_PAD_RTHUMB_PRESS: gk = GPK_RIGHT_STICK_PRESS; break;
133 case VK_PAD_LTHUMB_UP: gk = GPK_LEFT_STICK_UP; break;
134 case VK_PAD_LTHUMB_DOWN: gk = GPK_LEFT_STICK_DOWN; break;
135 case VK_PAD_LTHUMB_RIGHT: gk = GPK_LEFT_STICK_RIGHT; break;
136 case VK_PAD_LTHUMB_LEFT: gk = GPK_LEFT_STICK_LEFT; break;
137 case VK_PAD_LTHUMB_UPLEFT: gk = GPK_LEFT_STICK_UPLEFT; break;
138 case VK_PAD_LTHUMB_UPRIGHT: gk = GPK_LEFT_STICK_UPRIGHT; break;
139 case VK_PAD_LTHUMB_DOWNRIGHT: gk = GPK_LEFT_STICK_DOWNRIGHT; break;
140 case VK_PAD_LTHUMB_DOWNLEFT: gk = GPK_LEFT_STICK_DOWNLEFT; break;
141 case VK_PAD_RTHUMB_UP: gk = GPK_RIGHT_STICK_UP; break;
142 case VK_PAD_RTHUMB_DOWN: gk = GPK_RIGHT_STICK_DOWN; break;
143 case VK_PAD_RTHUMB_RIGHT: gk = GPK_RIGHT_STICK_RIGHT; break;
144 case VK_PAD_RTHUMB_LEFT: gk = GPK_RIGHT_STICK_LEFT; break;
145 case VK_PAD_RTHUMB_UPLEFT: gk = GPK_RIGHT_STICK_UPLEFT; break;
146 case VK_PAD_RTHUMB_UPRIGHT: gk = GPK_RIGHT_STICK_UPRIGHT; break;
147 case VK_PAD_RTHUMB_DOWNRIGHT: gk = GPK_RIGHT_STICK_DOWNRIGHT; break;
148 case VK_PAD_RTHUMB_DOWNLEFT: gk = GPK_RIGHT_STICK_DOWNLEFT; break;
149 default: gk = GPK_UNKNOWN; break;
150 }
151 switch (keystroke.Flags) {
152 case XINPUT_KEYSTROKE_KEYUP: action = KA_RELEASE; break;
153 case XINPUT_KEYSTROKE_KEYDOWN: action = KA_PRESS; break;
154 case XINPUT_KEYSTROKE_KEYDOWN + XINPUT_KEYSTROKE_REPEAT: action = KA_REPEAT; break;
155 default: action = KeyAction(-1); break;
156 }
157 return true;
158 }
160 bool xinput_gamepad_driver::get_device_state(void* device_handle, gamepad_state& state)
161 {
162 XINPUT_STATE pad_state;
163 DWORD result = XInputGetState(get_user_index(device_handle), &pad_state);
164 if (result == ERROR_DEVICE_NOT_CONNECTED)
165 return false;
166 state.time_stamp = pad_state.dwPacketNumber;
167 state.button_flags = pad_state.Gamepad.wButtons;
168 state.trigger_position[0] = convert(pad_state.Gamepad.bLeftTrigger);
169 state.trigger_position[1] = convert(pad_state.Gamepad.bRightTrigger);
170 state.left_stick_position[0] = convert(pad_state.Gamepad.sThumbLX);
171 state.left_stick_position[1] = convert(pad_state.Gamepad.sThumbLY);
172 state.right_stick_position[0] = convert(pad_state.Gamepad.sThumbRX);
173 state.right_stick_position[1] = convert(pad_state.Gamepad.sThumbRY);
174 return true;
175 }
177 bool xinput_gamepad_driver::set_device_vibration(void* device_handle, float low_frequency_strength, float high_frequency_strength)
178 {
179 XINPUT_VIBRATION vibration;
180 vibration.wLeftMotorSpeed = WORD(low_frequency_strength * 65535);
181 vibration.wRightMotorSpeed = WORD(high_frequency_strength * 65535);
182 DWORD result = XInputSetState(get_user_index(device_handle), &vibration);
183 if (result == ERROR_DEVICE_NOT_CONNECTED)
184 return false;
185 return true;
186 }
187};
188
189driver_registry<xinput_gamepad_driver> xinput_gpd_registry("xinput");
190
191#endif
use this template to register your own driver
interface class for gamepad drivers, when implementing your driver, provide a constructor with a sing...
see https://upload.wikimedia.org/wikipedia/commons/2/2c/360_controller.svg for an explanation of the ...
Definition gamepad.h:152
float right_stick_position[2]
x and y position of left thumb in the range [-1,1]
Definition gamepad.h:160
unsigned time_stamp
time stamp can be used whether a change has happened between two states
Definition gamepad.h:154
float left_stick_position[2]
x and y position of left thumb in the range [-1,1]
Definition gamepad.h:158
unsigned button_flags
combination of flags in GamepadButtonStateFlags combined with the OR operation
Definition gamepad.h:156
float trigger_position[2]
values of left and right triggers in the range [0,1]
Definition gamepad.h:162