cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_windowshaptic.c (10847B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      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#if SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
     24
     25#include "SDL_assert.h"
     26#include "SDL_thread.h"
     27#include "SDL_mutex.h"
     28#include "SDL_timer.h"
     29#include "SDL_hints.h"
     30#include "SDL_haptic.h"
     31#include "../SDL_syshaptic.h"
     32#include "SDL_joystick.h"
     33#include "../../joystick/SDL_sysjoystick.h"     /* For the real SDL_Joystick */
     34#include "../../joystick/windows/SDL_windowsjoystick_c.h"      /* For joystick hwdata */
     35#include "../../joystick/windows/SDL_xinputjoystick_c.h"      /* For xinput rumble */
     36
     37#include "SDL_windowshaptic_c.h"
     38#include "SDL_dinputhaptic_c.h"
     39#include "SDL_xinputhaptic_c.h"
     40
     41
     42/*
     43 * Internal stuff.
     44 */
     45SDL_hapticlist_item *SDL_hapticlist = NULL;
     46static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
     47static int numhaptics = 0;
     48
     49
     50/*
     51 * Initializes the haptic subsystem.
     52 */
     53int
     54SDL_SYS_HapticInit(void)
     55{
     56    if (SDL_DINPUT_HapticInit() < 0) {
     57        return -1;
     58    }
     59    if (SDL_XINPUT_HapticInit() < 0) {
     60        return -1;
     61    }
     62    return numhaptics;
     63}
     64
     65int
     66SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
     67{
     68    if (SDL_hapticlist_tail == NULL) {
     69        SDL_hapticlist = SDL_hapticlist_tail = item;
     70    } else {
     71        SDL_hapticlist_tail->next = item;
     72        SDL_hapticlist_tail = item;
     73    }
     74
     75    /* Device has been added. */
     76    ++numhaptics;
     77
     78    return numhaptics;
     79}
     80
     81int
     82SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
     83{
     84    const int retval = item->haptic ? item->haptic->index : -1;
     85    if (prev != NULL) {
     86        prev->next = item->next;
     87    } else {
     88        SDL_assert(SDL_hapticlist == item);
     89        SDL_hapticlist = item->next;
     90    }
     91    if (item == SDL_hapticlist_tail) {
     92        SDL_hapticlist_tail = prev;
     93    }
     94    --numhaptics;
     95    /* !!! TODO: Send a haptic remove event? */
     96    SDL_free(item);
     97    return retval;
     98}
     99
    100int
    101SDL_SYS_NumHaptics()
    102{
    103    return numhaptics;
    104}
    105
    106static SDL_hapticlist_item *
    107HapticByDevIndex(int device_index)
    108{
    109    SDL_hapticlist_item *item = SDL_hapticlist;
    110
    111    if ((device_index < 0) || (device_index >= numhaptics)) {
    112        return NULL;
    113    }
    114
    115    while (device_index > 0) {
    116        SDL_assert(item != NULL);
    117        --device_index;
    118        item = item->next;
    119    }
    120    return item;
    121}
    122
    123/*
    124 * Return the name of a haptic device, does not need to be opened.
    125 */
    126const char *
    127SDL_SYS_HapticName(int index)
    128{
    129    SDL_hapticlist_item *item = HapticByDevIndex(index);
    130    return item->name;
    131}
    132
    133/*
    134 * Opens a haptic device for usage.
    135 */
    136int
    137SDL_SYS_HapticOpen(SDL_Haptic * haptic)
    138{
    139    SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
    140    if (item->bXInputHaptic) {
    141        return SDL_XINPUT_HapticOpen(haptic, item);
    142    } else {
    143        return SDL_DINPUT_HapticOpen(haptic, item);
    144    }
    145}
    146
    147
    148/*
    149 * Opens a haptic device from first mouse it finds for usage.
    150 */
    151int
    152SDL_SYS_HapticMouse(void)
    153{
    154#if SDL_HAPTIC_DINPUT
    155    SDL_hapticlist_item *item;
    156    int index = 0;
    157
    158    /* Grab the first mouse haptic device we find. */
    159    for (item = SDL_hapticlist; item != NULL; item = item->next) {
    160        if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER ) {
    161            return index;
    162        }
    163        ++index;
    164    }
    165#endif /* SDL_HAPTIC_DINPUT */
    166    return -1;
    167}
    168
    169
    170/*
    171 * Checks to see if a joystick has haptic features.
    172 */
    173int
    174SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
    175{
    176    const struct joystick_hwdata *hwdata = joystick->hwdata;
    177#if SDL_HAPTIC_XINPUT
    178    if (hwdata->bXInputHaptic) {
    179        return 1;
    180    }
    181#endif
    182#if SDL_HAPTIC_DINPUT
    183    if (hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
    184        return 1;
    185    }
    186#endif
    187    return 0;
    188}
    189
    190/*
    191 * Checks to see if the haptic device and joystick are in reality the same.
    192 */
    193int
    194SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
    195{
    196    if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
    197        return 0;  /* one is XInput, one is not; not the same device. */
    198    } else if (joystick->hwdata->bXInputHaptic) {
    199        return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
    200    } else {
    201        return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
    202    }
    203}
    204
    205/*
    206 * Opens a SDL_Haptic from a SDL_Joystick.
    207 */
    208int
    209SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
    210{
    211    if (joystick->hwdata->bXInputDevice) {
    212        return SDL_XINPUT_HapticOpenFromJoystick(haptic, joystick);
    213    } else {
    214        return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
    215    }
    216}
    217
    218/*
    219 * Closes the haptic device.
    220 */
    221void
    222SDL_SYS_HapticClose(SDL_Haptic * haptic)
    223{
    224    if (haptic->hwdata) {
    225
    226        /* Free effects. */
    227        SDL_free(haptic->effects);
    228        haptic->effects = NULL;
    229        haptic->neffects = 0;
    230
    231        /* Clean up */
    232        if (haptic->hwdata->bXInputHaptic) {
    233            SDL_XINPUT_HapticClose(haptic);
    234        } else {
    235            SDL_DINPUT_HapticClose(haptic);
    236        }
    237
    238        /* Free */
    239        SDL_free(haptic->hwdata);
    240        haptic->hwdata = NULL;
    241    }
    242}
    243
    244/*
    245 * Clean up after system specific haptic stuff
    246 */
    247void
    248SDL_SYS_HapticQuit(void)
    249{
    250    SDL_hapticlist_item *item;
    251    SDL_hapticlist_item *next = NULL;
    252    SDL_Haptic *hapticitem = NULL;
    253
    254    extern SDL_Haptic *SDL_haptics;
    255    for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
    256        if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
    257            /* we _have_ to stop the thread before we free the XInput DLL! */
    258            hapticitem->hwdata->stopThread = 1;
    259            SDL_WaitThread(hapticitem->hwdata->thread, NULL);
    260            hapticitem->hwdata->thread = NULL;
    261        }
    262    }
    263
    264    for (item = SDL_hapticlist; item; item = next) {
    265        /* Opened and not closed haptics are leaked, this is on purpose.
    266         * Close your haptic devices after usage. */
    267        /* !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. */
    268        next = item->next;
    269        SDL_free(item->name);
    270        SDL_free(item);
    271    }
    272
    273    SDL_XINPUT_HapticQuit();
    274    SDL_DINPUT_HapticQuit();
    275}
    276
    277/*
    278 * Creates a new haptic effect.
    279 */
    280int
    281SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
    282                        SDL_HapticEffect * base)
    283{
    284    int result;
    285
    286    /* Alloc the effect. */
    287    effect->hweffect = (struct haptic_hweffect *)
    288        SDL_malloc(sizeof(struct haptic_hweffect));
    289    if (effect->hweffect == NULL) {
    290        SDL_OutOfMemory();
    291        return -1;
    292    }
    293    SDL_zerop(effect->hweffect);
    294
    295    if (haptic->hwdata->bXInputHaptic) {
    296        result = SDL_XINPUT_HapticNewEffect(haptic, effect, base);
    297    } else {
    298        result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
    299    }
    300    if (result < 0) {
    301        SDL_free(effect->hweffect);
    302        effect->hweffect = NULL;
    303    }
    304    return result;
    305}
    306
    307/*
    308 * Updates an effect.
    309 */
    310int
    311SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic,
    312                           struct haptic_effect *effect,
    313                           SDL_HapticEffect * data)
    314{
    315    if (haptic->hwdata->bXInputHaptic) {
    316        return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
    317    } else {
    318        return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
    319    }
    320}
    321
    322/*
    323 * Runs an effect.
    324 */
    325int
    326SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
    327                        Uint32 iterations)
    328{
    329    if (haptic->hwdata->bXInputHaptic) {
    330        return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations);
    331    } else {
    332        return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
    333    }
    334}
    335
    336/*
    337 * Stops an effect.
    338 */
    339int
    340SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
    341{
    342    if (haptic->hwdata->bXInputHaptic) {
    343        return SDL_XINPUT_HapticStopEffect(haptic, effect);
    344    } else {
    345        return SDL_DINPUT_HapticStopEffect(haptic, effect);
    346    }
    347}
    348
    349/*
    350 * Frees the effect.
    351 */
    352void
    353SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
    354{
    355    if (haptic->hwdata->bXInputHaptic) {
    356        SDL_XINPUT_HapticDestroyEffect(haptic, effect);
    357    } else {
    358        SDL_DINPUT_HapticDestroyEffect(haptic, effect);
    359    }
    360    SDL_free(effect->hweffect);
    361    effect->hweffect = NULL;
    362}
    363
    364/*
    365 * Gets the status of a haptic effect.
    366 */
    367int
    368SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic,
    369                              struct haptic_effect *effect)
    370{
    371    if (haptic->hwdata->bXInputHaptic) {
    372        return SDL_XINPUT_HapticGetEffectStatus(haptic, effect);
    373    } else {
    374        return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
    375    }
    376}
    377
    378/*
    379 * Sets the gain.
    380 */
    381int
    382SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
    383{
    384    if (haptic->hwdata->bXInputHaptic) {
    385        return SDL_XINPUT_HapticSetGain(haptic, gain);
    386    } else {
    387        return SDL_DINPUT_HapticSetGain(haptic, gain);
    388    }
    389}
    390
    391/*
    392 * Sets the autocentering.
    393 */
    394int
    395SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
    396{
    397    if (haptic->hwdata->bXInputHaptic) {
    398        return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
    399    } else {
    400        return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
    401    }
    402}
    403
    404/*
    405 * Pauses the device.
    406 */
    407int
    408SDL_SYS_HapticPause(SDL_Haptic * haptic)
    409{
    410    if (haptic->hwdata->bXInputHaptic) {
    411        return SDL_XINPUT_HapticPause(haptic);
    412    } else {
    413        return SDL_DINPUT_HapticPause(haptic);
    414    }
    415}
    416
    417/*
    418 * Pauses the device.
    419 */
    420int
    421SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
    422{
    423    if (haptic->hwdata->bXInputHaptic) {
    424        return SDL_XINPUT_HapticUnpause(haptic);
    425    } else {
    426        return SDL_DINPUT_HapticUnpause(haptic);
    427    }
    428}
    429
    430/*
    431 * Stops all the playing effects on the device.
    432 */
    433int
    434SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
    435{
    436    if (haptic->hwdata->bXInputHaptic) {
    437        return SDL_XINPUT_HapticStopAll(haptic);
    438    } else {
    439        return SDL_DINPUT_HapticStopAll(haptic);
    440    }
    441}
    442
    443#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
    444
    445/* vi: set ts=4 sw=4 expandtab: */