Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/haptic/windows/SDL_windowshaptic.c
9912 views
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
4
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any damages
7
arising from the use of this software.
8
9
Permission is granted to anyone to use this software for any purpose,
10
including commercial applications, and to alter it and redistribute it
11
freely, subject to the following restrictions:
12
13
1. The origin of this software must not be misrepresented; you must not
14
claim that you wrote the original software. If you use this software
15
in a product, an acknowledgment in the product documentation would be
16
appreciated but is not required.
17
2. Altered source versions must be plainly marked as such, and must not be
18
misrepresented as being the original software.
19
3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "SDL_internal.h"
22
23
#ifdef SDL_HAPTIC_DINPUT
24
25
#include "../SDL_syshaptic.h"
26
#include "../../joystick/SDL_sysjoystick.h" // For the real SDL_Joystick
27
#include "../../joystick/windows/SDL_windowsjoystick_c.h" // For joystick hwdata
28
#include "../../joystick/windows/SDL_xinputjoystick_c.h" // For xinput rumble
29
30
#include "SDL_windowshaptic_c.h"
31
#include "SDL_dinputhaptic_c.h"
32
33
// Set up for C function definitions, even when using C++
34
#ifdef __cplusplus
35
extern "C" {
36
#endif
37
38
/*
39
* Internal stuff.
40
*/
41
SDL_hapticlist_item *SDL_hapticlist = NULL;
42
static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
43
static int numhaptics = 0;
44
45
/*
46
* Initializes the haptic subsystem.
47
*/
48
bool SDL_SYS_HapticInit(void)
49
{
50
JoyStick_DeviceData *device;
51
52
if (!SDL_DINPUT_HapticInit()) {
53
return false;
54
}
55
56
/* The joystick subsystem will usually be initialized before haptics,
57
* so the initial HapticMaybeAddDevice() calls from the joystick
58
* subsystem will arrive too early to create haptic devices. We will
59
* invoke those callbacks again here to pick up any joysticks that
60
* were added prior to haptics initialization. */
61
for (device = SYS_Joystick; device; device = device->pNext) {
62
SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice);
63
}
64
65
return true;
66
}
67
68
bool SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
69
{
70
if (!SDL_hapticlist_tail) {
71
SDL_hapticlist = SDL_hapticlist_tail = item;
72
} else {
73
SDL_hapticlist_tail->next = item;
74
SDL_hapticlist_tail = item;
75
}
76
77
// Device has been added.
78
++numhaptics;
79
80
return true;
81
}
82
83
bool SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
84
{
85
const bool result = item->haptic ? true : false;
86
if (prev) {
87
prev->next = item->next;
88
} else {
89
SDL_assert(SDL_hapticlist == item);
90
SDL_hapticlist = item->next;
91
}
92
if (item == SDL_hapticlist_tail) {
93
SDL_hapticlist_tail = prev;
94
}
95
--numhaptics;
96
// !!! TODO: Send a haptic remove event?
97
SDL_free(item);
98
return result;
99
}
100
101
int SDL_SYS_NumHaptics(void)
102
{
103
return numhaptics;
104
}
105
106
static SDL_hapticlist_item *HapticByDevIndex(int device_index)
107
{
108
SDL_hapticlist_item *item = SDL_hapticlist;
109
110
if ((device_index < 0) || (device_index >= numhaptics)) {
111
return NULL;
112
}
113
114
while (device_index > 0) {
115
SDL_assert(item != NULL);
116
--device_index;
117
item = item->next;
118
}
119
return item;
120
}
121
122
static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id)
123
{
124
SDL_hapticlist_item *item;
125
for (item = SDL_hapticlist; item; item = item->next) {
126
if (instance_id == item->instance_id) {
127
return item;
128
}
129
}
130
return NULL;
131
}
132
133
SDL_HapticID SDL_SYS_HapticInstanceID(int index)
134
{
135
SDL_hapticlist_item *item = HapticByDevIndex(index);
136
if (item) {
137
return item->instance_id;
138
}
139
return 0;
140
}
141
142
/*
143
* Return the name of a haptic device, does not need to be opened.
144
*/
145
const char *SDL_SYS_HapticName(int index)
146
{
147
SDL_hapticlist_item *item = HapticByDevIndex(index);
148
return item->name;
149
}
150
151
/*
152
* Opens a haptic device for usage.
153
*/
154
bool SDL_SYS_HapticOpen(SDL_Haptic *haptic)
155
{
156
SDL_hapticlist_item *item = HapticByInstanceID(haptic->instance_id);
157
return SDL_DINPUT_HapticOpen(haptic, item);
158
}
159
160
/*
161
* Opens a haptic device from first mouse it finds for usage.
162
*/
163
int SDL_SYS_HapticMouse(void)
164
{
165
#ifdef SDL_HAPTIC_DINPUT
166
SDL_hapticlist_item *item;
167
int index = 0;
168
169
// Grab the first mouse haptic device we find.
170
for (item = SDL_hapticlist; item; item = item->next) {
171
if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER) {
172
return index;
173
}
174
++index;
175
}
176
#endif // SDL_HAPTIC_DINPUT
177
return -1;
178
}
179
180
/*
181
* Checks to see if a joystick has haptic features.
182
*/
183
bool SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
184
{
185
if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
186
return false;
187
}
188
if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
189
return true;
190
}
191
return false;
192
}
193
194
/*
195
* Checks to see if the haptic device and joystick are in reality the same.
196
*/
197
bool SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
198
{
199
if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
200
return false;
201
}
202
return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
203
}
204
205
/*
206
* Opens a SDL_Haptic from a SDL_Joystick.
207
*/
208
bool SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
209
{
210
SDL_assert(joystick->driver == &SDL_WINDOWS_JoystickDriver);
211
212
return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
213
}
214
215
/*
216
* Closes the haptic device.
217
*/
218
void SDL_SYS_HapticClose(SDL_Haptic *haptic)
219
{
220
if (haptic->hwdata) {
221
222
// Free effects.
223
SDL_free(haptic->effects);
224
haptic->effects = NULL;
225
haptic->neffects = 0;
226
227
// Clean up
228
SDL_DINPUT_HapticClose(haptic);
229
230
// Free
231
SDL_free(haptic->hwdata);
232
haptic->hwdata = NULL;
233
}
234
}
235
236
/*
237
* Clean up after system specific haptic stuff
238
*/
239
void SDL_SYS_HapticQuit(void)
240
{
241
SDL_hapticlist_item *item;
242
SDL_hapticlist_item *next = NULL;
243
244
for (item = SDL_hapticlist; item; item = next) {
245
/* Opened and not closed haptics are leaked, this is on purpose.
246
* Close your haptic devices after usage. */
247
// !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not.
248
next = item->next;
249
SDL_free(item->name);
250
SDL_free(item);
251
}
252
253
SDL_DINPUT_HapticQuit();
254
255
numhaptics = 0;
256
SDL_hapticlist = NULL;
257
SDL_hapticlist_tail = NULL;
258
}
259
260
/*
261
* Creates a new haptic effect.
262
*/
263
bool SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect,
264
const SDL_HapticEffect *base)
265
{
266
bool result;
267
268
// Alloc the effect.
269
effect->hweffect = (struct haptic_hweffect *) SDL_calloc(1, sizeof(struct haptic_hweffect));
270
if (!effect->hweffect) {
271
return false;
272
}
273
274
result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
275
if (!result) {
276
SDL_free(effect->hweffect);
277
effect->hweffect = NULL;
278
}
279
return result;
280
}
281
282
/*
283
* Updates an effect.
284
*/
285
bool SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data)
286
{
287
return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
288
}
289
290
/*
291
* Runs an effect.
292
*/
293
bool SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
294
{
295
return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
296
}
297
298
/*
299
* Stops an effect.
300
*/
301
bool SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
302
{
303
return SDL_DINPUT_HapticStopEffect(haptic, effect);
304
}
305
306
/*
307
* Frees the effect.
308
*/
309
void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
310
{
311
SDL_DINPUT_HapticDestroyEffect(haptic, effect);
312
SDL_free(effect->hweffect);
313
effect->hweffect = NULL;
314
}
315
316
/*
317
* Gets the status of a haptic effect.
318
*/
319
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
320
{
321
return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
322
}
323
324
/*
325
* Sets the gain.
326
*/
327
bool SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
328
{
329
return SDL_DINPUT_HapticSetGain(haptic, gain);
330
}
331
332
/*
333
* Sets the autocentering.
334
*/
335
bool SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
336
{
337
return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
338
}
339
340
/*
341
* Pauses the device.
342
*/
343
bool SDL_SYS_HapticPause(SDL_Haptic *haptic)
344
{
345
return SDL_DINPUT_HapticPause(haptic);
346
}
347
348
/*
349
* Pauses the device.
350
*/
351
bool SDL_SYS_HapticResume(SDL_Haptic *haptic)
352
{
353
return SDL_DINPUT_HapticResume(haptic);
354
}
355
356
/*
357
* Stops all the playing effects on the device.
358
*/
359
bool SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
360
{
361
return SDL_DINPUT_HapticStopAll(haptic);
362
}
363
364
// Ends C function definitions when using C++
365
#ifdef __cplusplus
366
}
367
#endif
368
369
#endif // SDL_HAPTIC_DINPUT
370
371