1 /*************************************************************************/ 2 /* joystick.h */ 3 /*************************************************************************/ 4 /* This file is part of: */ 5 /* GODOT ENGINE */ 6 /* https://godotengine.org */ 7 /*************************************************************************/ 8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ 9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ 10 /* */ 11 /* Permission is hereby granted, free of charge, to any person obtaining */ 12 /* a copy of this software and associated documentation files (the */ 13 /* "Software"), to deal in the Software without restriction, including */ 14 /* without limitation the rights to use, copy, modify, merge, publish, */ 15 /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 /* permit persons to whom the Software is furnished to do so, subject to */ 17 /* the following conditions: */ 18 /* */ 19 /* The above copyright notice and this permission notice shall be */ 20 /* included in all copies or substantial portions of the Software. */ 21 /* */ 22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 /*************************************************************************/ 30 //author: Andreas Haas <hondres, liugam3@gmail.com> 31 #ifndef JOYSTICK_H 32 #define JOYSTICK_H 33 34 #include "os_windows.h" 35 #define DIRECTINPUT_VERSION 0x0800 36 #include <dinput.h> 37 #include <xinput.h> // on unix the file is called "xinput.h", on windows I'm sure it won't mind 38 39 #ifndef SAFE_RELEASE // when Windows Media Device M? is not present 40 #define SAFE_RELEASE(x) \ 41 if (x != NULL) { \ 42 x->Release(); \ 43 x = NULL; \ 44 } 45 #endif 46 47 #ifndef XUSER_MAX_COUNT 48 #define XUSER_MAX_COUNT 4 49 #endif 50 51 class joystick_windows { 52 public: 53 joystick_windows(); 54 joystick_windows(InputDefault *_input, HWND *hwnd); 55 ~joystick_windows(); 56 57 void probe_joysticks(); 58 unsigned int process_joysticks(unsigned int p_last_id); 59 60 private: 61 enum { 62 JOYSTICKS_MAX = 16, 63 JOY_AXIS_COUNT = 6, 64 MIN_JOY_AXIS = 10, 65 MAX_JOY_AXIS = 32768, 66 MAX_JOY_BUTTONS = 128, 67 KEY_EVENT_BUFFER_SIZE = 512, 68 MAX_TRIGGER = 255 69 }; 70 71 struct dinput_gamepad { 72 73 int id; 74 bool attached; 75 bool confirmed; 76 bool last_buttons[MAX_JOY_BUTTONS]; 77 DWORD last_pad; 78 79 LPDIRECTINPUTDEVICE8 di_joy; 80 List<DWORD> joy_axis; 81 GUID guid; 82 dinput_gamepaddinput_gamepad83 dinput_gamepad() { 84 id = -1; 85 last_pad = -1; 86 attached = false; 87 confirmed = false; 88 89 for (int i = 0; i < MAX_JOY_BUTTONS; i++) 90 last_buttons[i] = false; 91 } 92 }; 93 94 struct xinput_gamepad { 95 96 int id; 97 bool attached; 98 bool vibrating; 99 DWORD last_packet; 100 XINPUT_STATE state; 101 uint64_t ff_timestamp; 102 uint64_t ff_end_timestamp; 103 xinput_gamepadxinput_gamepad104 xinput_gamepad() { 105 attached = false; 106 vibrating = false; 107 ff_timestamp = 0; 108 ff_end_timestamp = 0; 109 last_packet = 0; 110 } 111 }; 112 113 typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex, XINPUT_STATE *pState); 114 typedef DWORD(WINAPI *XInputSetState_t)(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration); 115 116 HWND *hWnd; 117 HANDLE xinput_dll; 118 LPDIRECTINPUT8 dinput; 119 InputDefault *input; 120 121 int id_to_change; 122 int joystick_count; 123 bool attached_joysticks[JOYSTICKS_MAX]; 124 dinput_gamepad d_joysticks[JOYSTICKS_MAX]; 125 xinput_gamepad x_joysticks[XUSER_MAX_COUNT]; 126 127 static BOOL CALLBACK enumCallback(const DIDEVICEINSTANCE *p_instance, void *p_context); 128 static BOOL CALLBACK objectsCallback(const DIDEVICEOBJECTINSTANCE *instance, void *context); 129 130 void setup_joystick_object(const DIDEVICEOBJECTINSTANCE *ob, int p_joy_id); 131 void close_joystick(int id = -1); 132 void load_xinput(); 133 void unload_xinput(); 134 135 unsigned int post_hat(unsigned int p_last_id, int p_device, DWORD p_dpad); 136 137 bool have_device(const GUID &p_guid); 138 bool is_xinput_device(const GUID *p_guid); 139 bool setup_dinput_joystick(const DIDEVICEINSTANCE *instance); 140 void joystick_vibration_start_xinput(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); 141 void joystick_vibration_stop_xinput(int p_device, uint64_t p_timestamp); 142 143 InputDefault::JoyAxis axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const; 144 XInputGetState_t xinput_get_state; 145 XInputSetState_t xinput_set_state; 146 }; 147 148 #endif 149