cscg22-gearboy

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

controllermap.c (16362B)


      1/*
      2  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      3
      4  This software is provided 'as-is', without any express or implied
      5  warranty.  In no event will the authors be held liable for any damages
      6  arising from the use of this software.
      7
      8  Permission is granted to anyone to use this software for any purpose,
      9  including commercial applications, and to alter it and redistribute it
     10  freely.
     11*/
     12
     13/* Game controller mapping generator */
     14/* Gabriel Jacobo <gabomdq@gmail.com> */
     15
     16#include <stdio.h>
     17#include <stdlib.h>
     18#include <string.h>
     19
     20#include "SDL.h"
     21
     22#ifndef SDL_JOYSTICK_DISABLED
     23
     24#ifdef __IPHONEOS__
     25#define SCREEN_WIDTH    320
     26#define SCREEN_HEIGHT   480
     27#else
     28#define SCREEN_WIDTH    512
     29#define SCREEN_HEIGHT   317
     30#endif
     31
     32#define MAP_WIDTH 512
     33#define MAP_HEIGHT 317
     34
     35#define MARKER_BUTTON 1
     36#define MARKER_AXIS 2
     37
     38typedef struct MappingStep
     39{
     40    int x, y;
     41    double angle;
     42    int marker;
     43    char *field;
     44    int axis, button, hat, hat_value;
     45    char mapping[4096];
     46}MappingStep;
     47
     48
     49SDL_Texture *
     50LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
     51{
     52    SDL_Surface *temp;
     53    SDL_Texture *texture;
     54
     55    /* Load the sprite image */
     56    temp = SDL_LoadBMP(file);
     57    if (temp == NULL) {
     58        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
     59        return NULL;
     60    }
     61
     62    /* Set transparent pixel as the pixel at (0,0) */
     63    if (transparent) {
     64        if (temp->format->palette) {
     65            SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
     66        } else {
     67            switch (temp->format->BitsPerPixel) {
     68            case 15:
     69                SDL_SetColorKey(temp, SDL_TRUE,
     70                                (*(Uint16 *) temp->pixels) & 0x00007FFF);
     71                break;
     72            case 16:
     73                SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
     74                break;
     75            case 24:
     76                SDL_SetColorKey(temp, SDL_TRUE,
     77                                (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
     78                break;
     79            case 32:
     80                SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
     81                break;
     82            }
     83        }
     84    }
     85
     86    /* Create textures from the image */
     87    texture = SDL_CreateTextureFromSurface(renderer, temp);
     88    if (!texture) {
     89        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
     90        SDL_FreeSurface(temp);
     91        return NULL;
     92    }
     93    SDL_FreeSurface(temp);
     94
     95    /* We're ready to roll. :) */
     96    return texture;
     97}
     98
     99static SDL_bool
    100WatchJoystick(SDL_Joystick * joystick)
    101{
    102    SDL_Window *window = NULL;
    103    SDL_Renderer *screen = NULL;
    104    SDL_Texture *background, *button, *axis, *marker;
    105    const char *name = NULL;
    106    SDL_bool retval = SDL_FALSE;
    107    SDL_bool done = SDL_FALSE, next=SDL_FALSE;
    108    SDL_Event event;
    109    SDL_Rect dst;
    110    int s, _s;
    111    Uint8 alpha=200, alpha_step = -1;
    112    Uint32 alpha_ticks = 0;
    113    char mapping[4096], temp[4096];
    114    MappingStep *step, *prev_step;
    115    MappingStep steps[] = {
    116        {342, 132,  0.0,  MARKER_BUTTON, "x", -1, -1, -1, -1, ""},
    117        {387, 167,  0.0,  MARKER_BUTTON, "a", -1, -1, -1, -1, ""},
    118        {431, 132,  0.0,  MARKER_BUTTON, "b", -1, -1, -1, -1, ""},
    119        {389, 101,  0.0,  MARKER_BUTTON, "y", -1, -1, -1, -1, ""},
    120        {174, 132,  0.0,  MARKER_BUTTON, "back", -1, -1, -1, -1, ""},
    121        {233, 132,  0.0,  MARKER_BUTTON, "guide", -1, -1, -1, -1, ""},
    122        {289, 132,  0.0,  MARKER_BUTTON, "start", -1, -1, -1, -1, ""},        
    123        {116, 217,  0.0,  MARKER_BUTTON, "dpleft", -1, -1, -1, -1, ""},
    124        {154, 249,  0.0,  MARKER_BUTTON, "dpdown", -1, -1, -1, -1, ""},
    125        {186, 217,  0.0,  MARKER_BUTTON, "dpright", -1, -1, -1, -1, ""},
    126        {154, 188,  0.0,  MARKER_BUTTON, "dpup", -1, -1, -1, -1, ""},
    127        {77,  40,   0.0,  MARKER_BUTTON, "leftshoulder", -1, -1, -1, -1, ""},
    128        {91, 0,    0.0,  MARKER_BUTTON, "lefttrigger", -1, -1, -1, -1, ""},
    129        {396, 36,   0.0,  MARKER_BUTTON, "rightshoulder", -1, -1, -1, -1, ""},
    130        {375, 0,    0.0,  MARKER_BUTTON, "righttrigger", -1, -1, -1, -1, ""},
    131        {75,  154,  0.0,  MARKER_BUTTON, "leftstick", -1, -1, -1, -1, ""},
    132        {305, 230,  0.0,  MARKER_BUTTON, "rightstick", -1, -1, -1, -1, ""},
    133        {75,  154,  0.0,  MARKER_AXIS,   "leftx", -1, -1, -1, -1, ""},
    134        {75,  154,  90.0, MARKER_AXIS,   "lefty", -1, -1, -1, -1, ""},        
    135        {305, 230,  0.0,  MARKER_AXIS,   "rightx", -1, -1, -1, -1, ""},
    136        {305, 230,  90.0, MARKER_AXIS,   "righty", -1, -1, -1, -1, ""},
    137    };
    138
    139    /* Create a window to display joystick axis position */
    140    window = SDL_CreateWindow("Game Controller Map", SDL_WINDOWPOS_CENTERED,
    141                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
    142                              SCREEN_HEIGHT, 0);
    143    if (window == NULL) {
    144        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
    145        return SDL_FALSE;
    146    }
    147
    148    screen = SDL_CreateRenderer(window, -1, 0);
    149    if (screen == NULL) {
    150        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
    151        SDL_DestroyWindow(window);
    152        return SDL_FALSE;
    153    }
    154    
    155    background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
    156    button = LoadTexture(screen, "button.bmp", SDL_TRUE);
    157    axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
    158    SDL_RaiseWindow(window);
    159
    160    /* scale for platforms that don't give you the window size you asked for. */
    161    SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
    162
    163    /* Print info about the joystick we are watching */
    164    name = SDL_JoystickName(joystick);
    165    SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
    166           name ? name : "Unknown Joystick");
    167    SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
    168           SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
    169           SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
    170    
    171    SDL_Log("\n\n\
    172    ====================================================================================\n\
    173    Press the buttons on your controller when indicated\n\
    174    (Your controller may look different than the picture)\n\
    175    If you want to correct a mistake, press backspace or the back button on your device\n\
    176    To skip a button, press SPACE or click/touch the screen\n\
    177    To exit, press ESC\n\
    178    ====================================================================================\n");
    179    
    180    /* Initialize mapping with GUID and name */
    181    SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), temp, SDL_arraysize(temp));
    182    SDL_snprintf(mapping, SDL_arraysize(mapping), "%s,%s,platform:%s,",
    183        temp, name ? name : "Unknown Joystick", SDL_GetPlatform());
    184
    185    /* Loop, getting joystick events! */
    186    for(s=0; s<SDL_arraysize(steps) && !done;) {
    187        /* blank screen, set up for drawing this frame. */
    188        step = &steps[s];
    189        SDL_strlcpy(step->mapping, mapping, SDL_arraysize(step->mapping));
    190        step->axis = -1;
    191        step->button = -1;
    192        step->hat = -1;
    193        step->hat_value = -1;
    194        SDL_SetClipboardText("TESTING TESTING 123");
    195        
    196        switch(step->marker) {
    197            case MARKER_AXIS:
    198                marker = axis;
    199                break;
    200            case MARKER_BUTTON:
    201                marker = button;
    202                break;
    203            default:
    204                break;
    205        }
    206        
    207        dst.x = step->x;
    208        dst.y = step->y;
    209        SDL_QueryTexture(marker, NULL, NULL, &dst.w, &dst.h);
    210        next=SDL_FALSE;
    211
    212        SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
    213
    214        while (!done && !next) {
    215            if (SDL_GetTicks() - alpha_ticks > 5) {
    216                alpha_ticks = SDL_GetTicks();
    217                alpha += alpha_step;
    218                if (alpha == 255) {
    219                    alpha_step = -1;
    220                }
    221                if (alpha < 128) {
    222                    alpha_step = 1;
    223                }
    224            }
    225            
    226            SDL_RenderClear(screen);
    227            SDL_RenderCopy(screen, background, NULL, NULL);
    228            SDL_SetTextureAlphaMod(marker, alpha);
    229            SDL_SetTextureColorMod(marker, 10, 255, 21);
    230            SDL_RenderCopyEx(screen, marker, NULL, &dst, step->angle, NULL, 0);
    231            SDL_RenderPresent(screen);
    232            
    233            if (SDL_PollEvent(&event)) {
    234                switch (event.type) {
    235                case SDL_JOYAXISMOTION:
    236                    if (event.jaxis.value > 20000 || event.jaxis.value < -20000) {
    237                        for (_s = 0; _s < s; _s++) {
    238                            if (steps[_s].axis == event.jaxis.axis) {
    239                                break;
    240                            }
    241                        }
    242                        if (_s == s) {
    243                            step->axis = event.jaxis.axis;
    244                            SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
    245                            SDL_snprintf(temp, SDL_arraysize(temp), ":a%u,", event.jaxis.axis);
    246                            SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
    247                            s++;
    248                            next=SDL_TRUE;
    249                        }
    250                    }
    251                    
    252                    break;
    253                case SDL_JOYHATMOTION:
    254                        if (event.jhat.value == SDL_HAT_CENTERED) {
    255                            break;  /* ignore centering, we're probably just coming back to the center from the previous item we set. */
    256                        }
    257                        for (_s = 0; _s < s; _s++) {
    258                            if (steps[_s].hat == event.jhat.hat && steps[_s].hat_value == event.jhat.value) {
    259                                break;
    260                            }
    261                        }
    262                        if (_s == s) {
    263                            step->hat = event.jhat.hat;
    264                            step->hat_value = event.jhat.value;
    265                            SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
    266                            SDL_snprintf(temp, SDL_arraysize(temp), ":h%u.%u,", event.jhat.hat, event.jhat.value );
    267                            SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
    268                            s++;
    269                            next=SDL_TRUE;
    270                        }
    271                    break;
    272                case SDL_JOYBALLMOTION:
    273                    break;
    274                case SDL_JOYBUTTONUP:
    275                    for (_s = 0; _s < s; _s++) {
    276                        if (steps[_s].button == event.jbutton.button) {
    277                            break;
    278                        }
    279                    }
    280                    if (_s == s) {
    281                        step->button = event.jbutton.button;
    282                        SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
    283                        SDL_snprintf(temp, SDL_arraysize(temp), ":b%u,", event.jbutton.button);
    284                        SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
    285                        s++;
    286                        next=SDL_TRUE;
    287                    }
    288                    break;
    289                case SDL_FINGERDOWN:
    290                case SDL_MOUSEBUTTONDOWN:
    291                    /* Skip this step */
    292                    s++;
    293                    next=SDL_TRUE;
    294                    break;
    295                case SDL_KEYDOWN:
    296                    if (event.key.keysym.sym == SDLK_BACKSPACE || event.key.keysym.sym == SDLK_AC_BACK) {
    297                        /* Undo! */
    298                        if (s > 0) {
    299                            prev_step = &steps[--s];
    300                            SDL_strlcpy(mapping, prev_step->mapping, SDL_arraysize(prev_step->mapping));
    301                            next = SDL_TRUE;
    302                        }
    303                        break;
    304                    }
    305                    if (event.key.keysym.sym == SDLK_SPACE) {
    306                        /* Skip this step */
    307                        s++;
    308                        next=SDL_TRUE;
    309                        break;
    310                    }
    311                    
    312                    if ((event.key.keysym.sym != SDLK_ESCAPE)) {
    313                        break;
    314                    }
    315                    /* Fall through to signal quit */
    316                case SDL_QUIT:
    317                    done = SDL_TRUE;
    318                    break;
    319                default:
    320                    break;
    321                }
    322            }
    323        }
    324
    325    }
    326
    327    if (s == SDL_arraysize(steps) ) {
    328        SDL_Log("Mapping:\n\n%s\n\n", mapping);
    329        /* Print to stdout as well so the user can cat the output somewhere */
    330        printf("%s\n", mapping);
    331    }
    332    
    333    while(SDL_PollEvent(&event)) {};
    334    
    335    SDL_DestroyRenderer(screen);
    336    SDL_DestroyWindow(window);
    337    return retval;
    338}
    339
    340int
    341main(int argc, char *argv[])
    342{
    343    const char *name;
    344    int i;
    345    SDL_Joystick *joystick;
    346
    347    /* Enable standard application logging */
    348    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);	
    349
    350    /* Initialize SDL (Note: video is required to start event loop) */
    351    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
    352        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
    353        exit(1);
    354    }
    355
    356    /* Print information about the joysticks */
    357    SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
    358    for (i = 0; i < SDL_NumJoysticks(); ++i) {
    359        name = SDL_JoystickNameForIndex(i);
    360        SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
    361        joystick = SDL_JoystickOpen(i);
    362        if (joystick == NULL) {
    363            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
    364                    SDL_GetError());
    365        } else {
    366            char guid[64];
    367            SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
    368                                      guid, sizeof (guid));
    369            SDL_Log("       axes: %d\n", SDL_JoystickNumAxes(joystick));
    370            SDL_Log("      balls: %d\n", SDL_JoystickNumBalls(joystick));
    371            SDL_Log("       hats: %d\n", SDL_JoystickNumHats(joystick));
    372            SDL_Log("    buttons: %d\n", SDL_JoystickNumButtons(joystick));
    373            SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
    374            SDL_Log("       guid: %s\n", guid);
    375            SDL_JoystickClose(joystick);
    376        }
    377    }
    378
    379#ifdef __ANDROID__
    380    if (SDL_NumJoysticks() > 0) {
    381#else
    382    if (argv[1]) {
    383#endif
    384        SDL_bool reportederror = SDL_FALSE;
    385        SDL_bool keepGoing = SDL_TRUE;
    386        SDL_Event event;
    387        int device;
    388#ifdef __ANDROID__
    389        device = 0;
    390#else
    391        device = atoi(argv[1]);
    392#endif
    393        joystick = SDL_JoystickOpen(device);
    394
    395        while ( keepGoing ) {
    396            if (joystick == NULL) {
    397                if ( !reportederror ) {
    398                    SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
    399                    keepGoing = SDL_FALSE;
    400                    reportederror = SDL_TRUE;
    401                }
    402            } else {
    403                reportederror = SDL_FALSE;
    404                keepGoing = WatchJoystick(joystick);
    405                SDL_JoystickClose(joystick);
    406            }
    407
    408            joystick = NULL;
    409            if (keepGoing) {
    410                SDL_Log("Waiting for attach\n");
    411            }
    412            while (keepGoing) {
    413                SDL_WaitEvent(&event);
    414                if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
    415                    || (event.type == SDL_MOUSEBUTTONDOWN)) {
    416                    keepGoing = SDL_FALSE;
    417                } else if (event.type == SDL_JOYDEVICEADDED) {
    418                    joystick = SDL_JoystickOpen(device);
    419                    break;
    420                }
    421            }
    422        }
    423    }
    424    else {
    425        SDL_Log("\n\nUsage: ./controllermap number\nFor example: ./controllermap 0\nOr: ./controllermap 0 >> gamecontrollerdb.txt");
    426    }
    427    SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
    428
    429    return 0;
    430}
    431
    432#else
    433
    434int
    435main(int argc, char *argv[])
    436{
    437    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
    438    exit(1);
    439}
    440
    441#endif