test/controllermap.c
author Alex Baines <alex@abaines.me.uk>
Tue, 19 Aug 2014 23:31:50 +0100
changeset 9097 56d712662a82
parent 8786 5e8f02536cd4
child 9270 4b93f61e564d
permissions -rw-r--r--
Add a SDL_IM_INTERNAL_EDITING event to make IMs like iBus render editing text in its own UI instead of sending TEXTEDITING events.
This is useful for applications that handle TEXTINPUT events but not TEXTEDITING events.
     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 *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 
   340 int
   341 main(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 
   434 int
   435 main(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