test/controllermap.c
author Gabriel Jacobo <gabomdq@gmail.com>
Mon, 10 Feb 2014 09:26:22 -0300
changeset 8201 4a16c26b6055
parent 8200 17b801b31cd5
child 8202 b84a1f55075e
permissions -rw-r--r--
Backed out 51935d107921

The render target usage in controllermap is required if you are forced to use
the app at a different resolution than the one the art has been made for, for
example on Android, where you don't control the resolution.
(The coordinates for each button are hardcoded to the art size, and appear out
of place otherwise)
     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 
    38 typedef 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 
    49 SDL_Texture *
    50 LoadTexture(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 
    99 static SDL_bool
   100 WatchJoystick(SDL_Joystick * joystick)
   101 {
   102     SDL_Window *window = NULL;
   103     SDL_Renderer *screen = NULL;
   104     SDL_Texture *target, *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;
   113     char mapping[4096], temp[4096];
   114     MappingStep *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     target = SDL_CreateTexture(screen, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, MAP_WIDTH, MAP_HEIGHT);
   156     background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
   157     button = LoadTexture(screen, "button.bmp", SDL_TRUE);
   158     axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
   159     SDL_RaiseWindow(window);
   160 
   161     /* Print info about the joystick we are watching */
   162     name = SDL_JoystickName(joystick);
   163     SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
   164            name ? name : "Unknown Joystick");
   165     SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
   166            SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
   167            SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
   168     
   169     SDL_Log("\n\n\
   170     ====================================================================================\n\
   171     Press the buttons on your controller when indicated\n\
   172     (Your controller may look different than the picture)\n\
   173     If you want to correct a mistake, press backspace or the back button on your device\n\
   174     To skip a button, press SPACE or click/touch the screen\n\
   175     To exit, press ESC\n\
   176     ====================================================================================\n");
   177     
   178     /* Initialize mapping with GUID and name */
   179     SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), temp, SDL_arraysize(temp));
   180     SDL_snprintf(mapping, SDL_arraysize(mapping), "%s,%s,platform:%s,",
   181         temp, name ? name : "Unknown Joystick", SDL_GetPlatform());
   182 
   183     /* Loop, getting joystick events! */
   184     for(s=0; s<SDL_arraysize(steps) && !done;) {
   185         /* blank screen, set up for drawing this frame. */
   186         step = &steps[s];
   187         SDL_strlcpy(step->mapping, mapping, SDL_arraysize(step->mapping));
   188         step->axis = -1;
   189         step->button = -1;
   190         step->hat = -1;
   191         step->hat_value = -1;
   192         SDL_SetClipboardText("TESTING TESTING 123");
   193         
   194         switch(step->marker) {
   195             case MARKER_AXIS:
   196                 marker = axis;
   197                 break;
   198             case MARKER_BUTTON:
   199                 marker = button;
   200                 break;
   201             default:
   202                 break;
   203         }
   204         
   205         dst.x = step->x;
   206         dst.y = step->y;
   207         SDL_QueryTexture(marker, NULL, NULL, &dst.w, &dst.h);
   208         next=SDL_FALSE;
   209         
   210         while (!done && !next) {
   211             if (SDL_GetTicks() - alpha_ticks > 5) {
   212                 alpha_ticks = SDL_GetTicks();
   213                 alpha += alpha_step;
   214                 if (alpha == 255) {
   215                     alpha_step = -1;
   216                 }
   217                 if (alpha < 128) {
   218                     alpha_step = 1;
   219                 }
   220             }
   221             
   222             SDL_SetRenderTarget(screen, target);
   223             SDL_RenderCopy(screen, background, NULL, NULL);
   224             SDL_SetTextureAlphaMod(marker, alpha);
   225             SDL_SetTextureColorMod(marker, 10, 255, 21);
   226             SDL_RenderCopyEx(screen, marker, NULL, &dst, step->angle, NULL, 0);
   227             SDL_SetRenderTarget(screen, NULL);
   228             SDL_RenderCopy(screen, target, NULL, NULL);
   229             SDL_RenderPresent(screen);
   230             
   231             if (SDL_PollEvent(&event)) {
   232                 switch (event.type) {
   233                 case SDL_JOYAXISMOTION:
   234                     if (event.jaxis.value > 20000 || event.jaxis.value < -20000) {
   235                         for (_s = 0; _s < s; _s++) {
   236                             if (steps[_s].axis == event.jaxis.axis) {
   237                                 break;
   238                             }
   239                         }
   240                         if (_s == s) {
   241                             step->axis = event.jaxis.axis;
   242                             SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
   243                             SDL_snprintf(temp, SDL_arraysize(temp), ":a%u,", event.jaxis.axis);
   244                             SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
   245                             s++;
   246                             next=SDL_TRUE;
   247                         }
   248                     }
   249                     
   250                     break;
   251                 case SDL_JOYHATMOTION:
   252                         for (_s = 0; _s < s; _s++) {
   253                             if (steps[_s].hat == event.jhat.hat && steps[_s].hat_value == event.jhat.value) {
   254                                 break;
   255                             }
   256                         }
   257                         if (_s == s) {
   258                             step->hat = event.jhat.hat;
   259                             step->hat_value = event.jhat.value;
   260                             SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
   261                             SDL_snprintf(temp, SDL_arraysize(temp), ":h%u.%u,", event.jhat.hat, event.jhat.value );
   262                             SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
   263                             s++;
   264                             next=SDL_TRUE;
   265                         }
   266                     break;
   267                 case SDL_JOYBALLMOTION:
   268                     break;
   269                 case SDL_JOYBUTTONUP:
   270                     for (_s = 0; _s < s; _s++) {
   271                         if (steps[_s].button == event.jbutton.button) {
   272                             break;
   273                         }
   274                     }
   275                     if (_s == s) {
   276                         step->button = event.jbutton.button;
   277                         SDL_strlcat(mapping, step->field, SDL_arraysize(mapping));
   278                         SDL_snprintf(temp, SDL_arraysize(temp), ":b%u,", event.jbutton.button);
   279                         SDL_strlcat(mapping, temp, SDL_arraysize(mapping));
   280                         s++;
   281                         next=SDL_TRUE;
   282                     }
   283                     break;
   284                 case SDL_FINGERDOWN:
   285                 case SDL_MOUSEBUTTONDOWN:
   286                     /* Skip this step */
   287                     s++;
   288                     next=SDL_TRUE;
   289                     break;
   290                 case SDL_KEYDOWN:
   291                     if (event.key.keysym.sym == SDLK_BACKSPACE || event.key.keysym.sym == SDLK_AC_BACK) {
   292                         /* Undo! */
   293                         if (s > 0) {
   294                             SDL_strlcpy(mapping, step->mapping, SDL_arraysize(step->mapping));
   295                             s--;
   296                             next = SDL_TRUE;
   297                         }
   298                         break;
   299                     }
   300                     if (event.key.keysym.sym == SDLK_SPACE) {
   301                         /* Skip this step */
   302                         s++;
   303                         next=SDL_TRUE;
   304                         break;
   305                     }
   306                     
   307                     if ((event.key.keysym.sym != SDLK_ESCAPE)) {
   308                         break;
   309                     }
   310                     /* Fall through to signal quit */
   311                 case SDL_QUIT:
   312                     done = SDL_TRUE;
   313                     break;
   314                 default:
   315                     break;
   316                 }
   317             }
   318         }
   319 
   320     }
   321 
   322     if (s == SDL_arraysize(steps) ) {
   323         SDL_Log("Mapping:\n\n%s\n\n", mapping);
   324         /* Print to stdout as well so the user can cat the output somewhere */
   325         printf("%s\n", mapping);
   326     }
   327     
   328     while(SDL_PollEvent(&event)) {};
   329     
   330     SDL_DestroyRenderer(screen);
   331     SDL_DestroyWindow(window);
   332     return retval;
   333 }
   334 
   335 int
   336 main(int argc, char *argv[])
   337 {
   338     const char *name;
   339     int i;
   340     SDL_Joystick *joystick;
   341 
   342     /* Enable standard application logging */
   343     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);	
   344 
   345     /* Initialize SDL (Note: video is required to start event loop) */
   346     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
   347         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
   348         exit(1);
   349     }
   350 
   351     /* Print information about the joysticks */
   352     SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
   353     for (i = 0; i < SDL_NumJoysticks(); ++i) {
   354         name = SDL_JoystickNameForIndex(i);
   355         SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
   356         joystick = SDL_JoystickOpen(i);
   357         if (joystick == NULL) {
   358             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
   359                     SDL_GetError());
   360         } else {
   361             char guid[64];
   362             SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
   363                                       guid, sizeof (guid));
   364             SDL_Log("       axes: %d\n", SDL_JoystickNumAxes(joystick));
   365             SDL_Log("      balls: %d\n", SDL_JoystickNumBalls(joystick));
   366             SDL_Log("       hats: %d\n", SDL_JoystickNumHats(joystick));
   367             SDL_Log("    buttons: %d\n", SDL_JoystickNumButtons(joystick));
   368             SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
   369             SDL_Log("       guid: %s\n", guid);
   370             SDL_JoystickClose(joystick);
   371         }
   372     }
   373 
   374 #ifdef ANDROID
   375     if (SDL_NumJoysticks() > 0) {
   376 #else
   377     if (argv[1]) {
   378 #endif
   379         SDL_bool reportederror = SDL_FALSE;
   380         SDL_bool keepGoing = SDL_TRUE;
   381         SDL_Event event;
   382         int device;
   383 #ifdef ANDROID
   384         device = 0;
   385 #else
   386         device = atoi(argv[1]);
   387 #endif
   388         joystick = SDL_JoystickOpen(device);
   389 
   390         while ( keepGoing ) {
   391             if (joystick == NULL) {
   392                 if ( !reportederror ) {
   393                     SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
   394                     keepGoing = SDL_FALSE;
   395                     reportederror = SDL_TRUE;
   396                 }
   397             } else {
   398                 reportederror = SDL_FALSE;
   399                 keepGoing = WatchJoystick(joystick);
   400                 SDL_JoystickClose(joystick);
   401             }
   402 
   403             joystick = NULL;
   404             if (keepGoing) {
   405                 SDL_Log("Waiting for attach\n");
   406             }
   407             while (keepGoing) {
   408                 SDL_WaitEvent(&event);
   409                 if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
   410                     || (event.type == SDL_MOUSEBUTTONDOWN)) {
   411                     keepGoing = SDL_FALSE;
   412                 } else if (event.type == SDL_JOYDEVICEADDED) {
   413                     joystick = SDL_JoystickOpen(device);
   414                     break;
   415                 }
   416             }
   417         }
   418     }
   419     else {
   420         SDL_Log("\n\nUsage: ./controllermap number\nFor example: ./controllermap 0\nOr: ./controllermap 0 >> gamecontrollerdb.txt");
   421     }
   422     SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
   423 
   424     return 0;
   425 }
   426 
   427 #else
   428 
   429 int
   430 main(int argc, char *argv[])
   431 {
   432     SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
   433     exit(1);
   434 }
   435 
   436 #endif