cscg22-gearboy

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

testhaptic.c (13851B)


      1/*
      2Copyright (c) 2008, Edgar Simo Serra
      3All rights reserved.
      4
      5Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
      6
      7    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
      8    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
      9    * Neither the name of the Simple Directmedia Layer (SDL) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
     10
     11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     12*/
     13
     14/*
     15 * includes
     16 */
     17#include <stdlib.h>
     18#include <string.h>             /* strstr */
     19#include <ctype.h>              /* isdigit */
     20
     21#include "SDL.h"
     22
     23#ifndef SDL_HAPTIC_DISABLED
     24
     25#include "SDL_haptic.h"
     26
     27static SDL_Haptic *haptic;
     28
     29
     30/*
     31 * prototypes
     32 */
     33static void abort_execution(void);
     34static void HapticPrintSupported(SDL_Haptic * haptic);
     35
     36
     37/**
     38 * @brief The entry point of this force feedback demo.
     39 * @param[in] argc Number of arguments.
     40 * @param[in] argv Array of argc arguments.
     41 */
     42int
     43main(int argc, char **argv)
     44{
     45    int i;
     46    char *name;
     47    int index;
     48    SDL_HapticEffect efx[9];
     49    int id[9];
     50    int nefx;
     51    unsigned int supported;
     52
     53    /* Enable standard application logging */
     54    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
     55
     56    name = NULL;
     57    index = -1;
     58    if (argc > 1) {
     59        name = argv[1];
     60        if ((strcmp(name, "--help") == 0) || (strcmp(name, "-h") == 0)) {
     61            SDL_Log("USAGE: %s [device]\n"
     62                   "If device is a two-digit number it'll use it as an index, otherwise\n"
     63                   "it'll use it as if it were part of the device's name.\n",
     64                   argv[0]);
     65            return 0;
     66        }
     67
     68        i = strlen(name);
     69        if ((i < 3) && isdigit(name[0]) && ((i == 1) || isdigit(name[1]))) {
     70            index = atoi(name);
     71            name = NULL;
     72        }
     73    }
     74
     75    /* Initialize the force feedbackness */
     76    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK |
     77             SDL_INIT_HAPTIC);
     78    SDL_Log("%d Haptic devices detected.\n", SDL_NumHaptics());
     79    if (SDL_NumHaptics() > 0) {
     80        /* We'll just use index or the first force feedback device found */
     81        if (name == NULL) {
     82            i = (index != -1) ? index : 0;
     83        }
     84        /* Try to find matching device */
     85        else {
     86            for (i = 0; i < SDL_NumHaptics(); i++) {
     87                if (strstr(SDL_HapticName(i), name) != NULL)
     88                    break;
     89            }
     90
     91            if (i >= SDL_NumHaptics()) {
     92                SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find device matching '%s', aborting.\n",
     93                       name);
     94                return 1;
     95            }
     96        }
     97
     98        haptic = SDL_HapticOpen(i);
     99        if (haptic == NULL) {
    100            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s\n",
    101                   SDL_GetError());
    102            return 1;
    103        }
    104        SDL_Log("Device: %s\n", SDL_HapticName(i));
    105        HapticPrintSupported(haptic);
    106    } else {
    107        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No Haptic devices found!\n");
    108        return 1;
    109    }
    110
    111    /* We only want force feedback errors. */
    112    SDL_ClearError();
    113
    114    /* Create effects. */
    115    memset(&efx, 0, sizeof(efx));
    116    nefx = 0;
    117    supported = SDL_HapticQuery(haptic);
    118
    119    SDL_Log("\nUploading effects\n");
    120    /* First we'll try a SINE effect. */
    121    if (supported & SDL_HAPTIC_SINE) {
    122        SDL_Log("   effect %d: Sine Wave\n", nefx);
    123        efx[nefx].type = SDL_HAPTIC_SINE;
    124        efx[nefx].periodic.period = 1000;
    125        efx[nefx].periodic.magnitude = -0x2000;    /* Negative magnitude and ...                      */
    126        efx[nefx].periodic.phase = 18000;          /* ... 180 degrees phase shift => cancel eachother */
    127        efx[nefx].periodic.length = 5000;
    128        efx[nefx].periodic.attack_length = 1000;
    129        efx[nefx].periodic.fade_length = 1000;
    130        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    131        if (id[nefx] < 0) {
    132            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    133            abort_execution();
    134        }
    135        nefx++;
    136    }
    137    /* Now we'll try a SAWTOOTHUP */
    138    if (supported & SDL_HAPTIC_SAWTOOTHUP) {
    139        SDL_Log("   effect %d: Sawtooth Up\n", nefx);
    140        efx[nefx].type = SDL_HAPTIC_SAWTOOTHUP;
    141        efx[nefx].periodic.period = 500;
    142        efx[nefx].periodic.magnitude = 0x5000;
    143        efx[nefx].periodic.length = 5000;
    144        efx[nefx].periodic.attack_length = 1000;
    145        efx[nefx].periodic.fade_length = 1000;
    146        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    147        if (id[nefx] < 0) {
    148            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    149            abort_execution();
    150        }
    151        nefx++;
    152    }
    153    
    154    /* Now the classical constant effect. */
    155    if (supported & SDL_HAPTIC_CONSTANT) {
    156        SDL_Log("   effect %d: Constant Force\n", nefx);
    157        efx[nefx].type = SDL_HAPTIC_CONSTANT;
    158        efx[nefx].constant.direction.type = SDL_HAPTIC_POLAR;
    159        efx[nefx].constant.direction.dir[0] = 20000;    /* Force comes from the south-west. */
    160        efx[nefx].constant.length = 5000;
    161        efx[nefx].constant.level = 0x6000;
    162        efx[nefx].constant.attack_length = 1000;
    163        efx[nefx].constant.fade_length = 1000;
    164        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    165        if (id[nefx] < 0) {
    166            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    167            abort_execution();
    168        }
    169        nefx++;
    170    }
    171    
    172    /* The cute spring effect. */
    173    if (supported & SDL_HAPTIC_SPRING) {
    174        SDL_Log("   effect %d: Condition Spring\n", nefx);
    175        efx[nefx].type = SDL_HAPTIC_SPRING;
    176        efx[nefx].condition.length = 5000;
    177        for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
    178            efx[nefx].condition.right_sat[i] = 0xFFFF;
    179            efx[nefx].condition.left_sat[i] = 0xFFFF;
    180            efx[nefx].condition.right_coeff[i] = 0x2000;
    181            efx[nefx].condition.left_coeff[i] = 0x2000;
    182            efx[nefx].condition.center[i] = 0x1000;     /* Displace the center for it to move. */
    183        }
    184        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    185        if (id[nefx] < 0) {
    186            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    187            abort_execution();
    188        }
    189        nefx++;
    190    }
    191    /* The interesting damper effect. */
    192    if (supported & SDL_HAPTIC_DAMPER) {
    193        SDL_Log("   effect %d: Condition Damper\n", nefx);
    194        efx[nefx].type = SDL_HAPTIC_DAMPER;
    195        efx[nefx].condition.length = 5000;
    196        for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
    197            efx[nefx].condition.right_sat[i] = 0xFFFF;
    198            efx[nefx].condition.left_sat[i] = 0xFFFF;
    199            efx[nefx].condition.right_coeff[i] = 0x2000;
    200            efx[nefx].condition.left_coeff[i] = 0x2000;
    201        }
    202        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    203        if (id[nefx] < 0) {
    204            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    205            abort_execution();
    206        }
    207        nefx++;
    208    }
    209    /* The pretty awesome inertia effect. */
    210    if (supported & SDL_HAPTIC_INERTIA) {
    211        SDL_Log("   effect %d: Condition Inertia\n", nefx);
    212        efx[nefx].type = SDL_HAPTIC_INERTIA;
    213        efx[nefx].condition.length = 5000;
    214        for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
    215            efx[nefx].condition.right_sat[i] = 0xFFFF;
    216            efx[nefx].condition.left_sat[i] = 0xFFFF;
    217            efx[nefx].condition.right_coeff[i] = 0x2000;
    218            efx[nefx].condition.left_coeff[i] = 0x2000;
    219            efx[nefx].condition.deadband[i] = 0x1000;    /* 1/16th of axis-range around the center is 'dead'. */
    220        }
    221        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    222        if (id[nefx] < 0) {
    223            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    224            abort_execution();
    225        }
    226        nefx++;
    227    }
    228    /* The hot friction effect. */
    229    if (supported & SDL_HAPTIC_FRICTION) {
    230        SDL_Log("   effect %d: Condition Friction\n", nefx);
    231        efx[nefx].type = SDL_HAPTIC_FRICTION;
    232        efx[nefx].condition.length = 5000;
    233        for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
    234            efx[nefx].condition.right_sat[i] = 0xFFFF;
    235            efx[nefx].condition.left_sat[i] = 0xFFFF;
    236            efx[nefx].condition.right_coeff[i] = 0x2000;
    237            efx[nefx].condition.left_coeff[i] = 0x2000;
    238        }
    239        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    240        if (id[nefx] < 0) {
    241            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    242            abort_execution();
    243        }
    244        nefx++;
    245    }
    246    
    247    /* Now we'll try a ramp effect */
    248    if (supported & SDL_HAPTIC_RAMP) {
    249        SDL_Log("   effect %d: Ramp\n", nefx);
    250        efx[nefx].type = SDL_HAPTIC_RAMP;
    251        efx[nefx].ramp.direction.type = SDL_HAPTIC_CARTESIAN;
    252        efx[nefx].ramp.direction.dir[0] = 1;     /* Force comes from                 */
    253        efx[nefx].ramp.direction.dir[1] = -1;    /*                  the north-east. */
    254        efx[nefx].ramp.length = 5000;
    255        efx[nefx].ramp.start = 0x4000;
    256        efx[nefx].ramp.end = -0x4000;
    257        efx[nefx].ramp.attack_length = 1000;
    258        efx[nefx].ramp.fade_length = 1000;
    259        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    260        if (id[nefx] < 0) {
    261            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    262            abort_execution();
    263        }
    264        nefx++;
    265    }
    266
    267    /* Finally we'll try a left/right effect. */
    268    if (supported & SDL_HAPTIC_LEFTRIGHT) {
    269        SDL_Log("   effect %d: Left/Right\n", nefx);
    270        efx[nefx].type = SDL_HAPTIC_LEFTRIGHT;
    271        efx[nefx].leftright.length = 5000;
    272        efx[nefx].leftright.large_magnitude = 0x3000;
    273        efx[nefx].leftright.small_magnitude = 0xFFFF;
    274        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    275        if (id[nefx] < 0) {
    276            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    277            abort_execution();
    278        }
    279        nefx++;
    280    }
    281
    282
    283    SDL_Log
    284        ("\nNow playing effects for 5 seconds each with 1 second delay between\n");
    285    for (i = 0; i < nefx; i++) {
    286        SDL_Log("   Playing effect %d\n", i);
    287        SDL_HapticRunEffect(haptic, id[i], 1);
    288        SDL_Delay(6000);        /* Effects only have length 5000 */
    289    }
    290
    291    /* Quit */
    292    if (haptic != NULL)
    293        SDL_HapticClose(haptic);
    294    SDL_Quit();
    295
    296    return 0;
    297}
    298
    299
    300/*
    301 * Cleans up a bit.
    302 */
    303static void
    304abort_execution(void)
    305{
    306    SDL_Log("\nAborting program execution.\n");
    307
    308    SDL_HapticClose(haptic);
    309    SDL_Quit();
    310
    311    exit(1);
    312}
    313
    314
    315/*
    316 * Displays information about the haptic device.
    317 */
    318static void
    319HapticPrintSupported(SDL_Haptic * haptic)
    320{
    321    unsigned int supported;
    322
    323    supported = SDL_HapticQuery(haptic);
    324    SDL_Log("   Supported effects [%d effects, %d playing]:\n",
    325           SDL_HapticNumEffects(haptic), SDL_HapticNumEffectsPlaying(haptic));
    326    if (supported & SDL_HAPTIC_CONSTANT)
    327        SDL_Log("      constant\n");
    328    if (supported & SDL_HAPTIC_SINE)
    329        SDL_Log("      sine\n");
    330    /* !!! FIXME: put this back when we have more bits in 2.1 */
    331    /* if (supported & SDL_HAPTIC_SQUARE)
    332        SDL_Log("      square\n"); */
    333    if (supported & SDL_HAPTIC_TRIANGLE)
    334        SDL_Log("      triangle\n");
    335    if (supported & SDL_HAPTIC_SAWTOOTHUP)
    336        SDL_Log("      sawtoothup\n");
    337    if (supported & SDL_HAPTIC_SAWTOOTHDOWN)
    338        SDL_Log("      sawtoothdown\n");
    339    if (supported & SDL_HAPTIC_RAMP)
    340        SDL_Log("      ramp\n");
    341    if (supported & SDL_HAPTIC_FRICTION)
    342        SDL_Log("      friction\n");
    343    if (supported & SDL_HAPTIC_SPRING)
    344        SDL_Log("      spring\n");
    345    if (supported & SDL_HAPTIC_DAMPER)
    346        SDL_Log("      damper\n");
    347    if (supported & SDL_HAPTIC_INERTIA)
    348        SDL_Log("      inertia\n");
    349    if (supported & SDL_HAPTIC_CUSTOM)
    350        SDL_Log("      custom\n");
    351    if (supported & SDL_HAPTIC_LEFTRIGHT)
    352        SDL_Log("      left/right\n");
    353    SDL_Log("   Supported capabilities:\n");
    354    if (supported & SDL_HAPTIC_GAIN)
    355        SDL_Log("      gain\n");
    356    if (supported & SDL_HAPTIC_AUTOCENTER)
    357        SDL_Log("      autocenter\n");
    358    if (supported & SDL_HAPTIC_STATUS)
    359        SDL_Log("      status\n");
    360}
    361
    362#else
    363
    364int
    365main(int argc, char *argv[])
    366{
    367    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Haptic support.\n");
    368    exit(1);
    369}
    370
    371#endif