test/testgamecontroller.c
author Alex Baines <alex@abaines.me.uk>
Tue, 19 Aug 2014 23:31:50 +0100
changeset 9097 56d712662a82
parent 8687 1d2ca48523a7
child 9102 a22458d5eed9
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 /* Simple program to test the SDL game controller routines */
    14 
    15 #include <stdio.h>
    16 #include <stdlib.h>
    17 #include <string.h>
    18 
    19 #include "SDL.h"
    20 
    21 #ifndef SDL_JOYSTICK_DISABLED
    22 
    23 #ifdef __IPHONEOS__
    24 #define SCREEN_WIDTH    320
    25 #define SCREEN_HEIGHT    480
    26 #else
    27 #define SCREEN_WIDTH    512
    28 #define SCREEN_HEIGHT   317
    29 #endif
    30 
    31 static const char *
    32 ControllerAxisName(const SDL_GameControllerAxis axis)
    33 {
    34     switch (axis)
    35     {
    36         #define AXIS_CASE(ax) case SDL_CONTROLLER_AXIS_##ax: return #ax
    37         AXIS_CASE(INVALID);
    38         AXIS_CASE(LEFTX);
    39         AXIS_CASE(LEFTY);
    40         AXIS_CASE(RIGHTX);
    41         AXIS_CASE(RIGHTY);
    42         AXIS_CASE(TRIGGERLEFT);
    43         AXIS_CASE(TRIGGERRIGHT);
    44         #undef AXIS_CASE
    45         default: return "???";
    46     }
    47 }
    48 
    49 static const char *
    50 ControllerButtonName(const SDL_GameControllerButton button)
    51 {
    52     switch (button)
    53     {
    54         #define BUTTON_CASE(btn) case SDL_CONTROLLER_BUTTON_##btn: return #btn
    55         BUTTON_CASE(INVALID);
    56         BUTTON_CASE(A);
    57         BUTTON_CASE(B);
    58         BUTTON_CASE(X);
    59         BUTTON_CASE(Y);
    60         BUTTON_CASE(BACK);
    61         BUTTON_CASE(GUIDE);
    62         BUTTON_CASE(START);
    63         BUTTON_CASE(LEFTSTICK);
    64         BUTTON_CASE(RIGHTSTICK);
    65         BUTTON_CASE(LEFTSHOULDER);
    66         BUTTON_CASE(RIGHTSHOULDER);
    67         BUTTON_CASE(DPAD_UP);
    68         BUTTON_CASE(DPAD_DOWN);
    69         BUTTON_CASE(DPAD_LEFT);
    70         BUTTON_CASE(DPAD_RIGHT);
    71         #undef BUTTON_CASE
    72         default: return "???";
    73     }
    74 }
    75 
    76 static SDL_Texture *
    77 LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
    78 {
    79     SDL_Surface *temp = NULL;
    80     SDL_Texture *texture = NULL;
    81 
    82     temp = SDL_LoadBMP(file);
    83     if (temp == NULL) {
    84         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
    85     } else {
    86         /* Set transparent pixel as the pixel at (0,0) */
    87         if (transparent) {
    88             if (temp->format->BytesPerPixel == 1) {
    89                 SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *)temp->pixels);
    90             } else {
    91                 SDL_assert(!temp->format->palette);
    92                 SDL_assert(temp->format->BitsPerPixel == 24);
    93                 SDL_SetColorKey(temp, SDL_TRUE, (*(Uint32 *)temp->pixels) & 0x00FFFFFF);
    94             }
    95         }
    96 
    97         texture = SDL_CreateTextureFromSurface(renderer, temp);
    98         if (!texture) {
    99             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
   100         }
   101     }
   102     if (temp) {
   103         SDL_FreeSurface(temp);
   104     }
   105     return texture;
   106 }
   107 
   108 SDL_bool
   109 WatchGameController(SDL_GameController * gamecontroller)
   110 {
   111     /* This is indexed by SDL_GameControllerButton. */
   112     static const struct { int x; int y; } button_positions[] = {
   113         {387, 167},  /* A */
   114         {431, 132},  /* B */
   115         {342, 132},  /* X */
   116         {389, 101},  /* Y */
   117         {174, 132},  /* BACK */
   118         {233, 132},  /* GUIDE */
   119         {289, 132},  /* START */
   120         {75,  154},  /* LEFTSTICK */
   121         {305, 230},  /* RIGHTSTICK */
   122         {77,  40},   /* LEFTSHOULDER */
   123         {396, 36},   /* RIGHTSHOULDER */
   124         {154, 188},  /* DPAD_UP */
   125         {154, 249},  /* DPAD_DOWN */
   126         {116, 217},  /* DPAD_LEFT */
   127         {186, 217},  /* DPAD_RIGHT */
   128     };
   129 
   130     /* This is indexed by SDL_GameControllerAxis. */
   131     static const struct { int x; int y; double angle; } axis_positions[] = {
   132         {75,  154, 0.0},  /* LEFTX */
   133         {75,  154, 90.0},  /* LEFTY */
   134         {305, 230, 0.0},  /* RIGHTX */
   135         {305, 230, 90.0},  /* RIGHTY */
   136         {91, 0, 90.0},     /* TRIGGERLEFT */
   137         {375, 0, 90.0},    /* TRIGGERRIGHT */
   138     };
   139 
   140     const char *name = SDL_GameControllerName(gamecontroller);
   141     const char *basetitle = "Game Controller Test: ";
   142     const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1;
   143     char *title = (char *)SDL_malloc(titlelen);
   144     SDL_Texture *background, *button, *axis;
   145     SDL_Window *window = NULL;
   146     SDL_Renderer *screen = NULL;
   147     SDL_bool retval = SDL_FALSE;
   148     SDL_bool done = SDL_FALSE;
   149     SDL_Event event;
   150     int i;
   151 
   152     if (title) {
   153         SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
   154     }
   155 
   156     /* Create a window to display controller state */
   157     window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED,
   158                               SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
   159                               SCREEN_HEIGHT, 0);
   160     if (window == NULL) {
   161         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
   162         return SDL_FALSE;
   163     }
   164 
   165     screen = SDL_CreateRenderer(window, -1, 0);
   166     if (screen == NULL) {
   167         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
   168         SDL_DestroyWindow(window);
   169         return SDL_FALSE;
   170     }
   171 
   172     SDL_SetRenderDrawColor(screen, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE);
   173     SDL_RenderClear(screen);
   174     SDL_RenderPresent(screen);
   175     SDL_RaiseWindow(window);
   176 
   177     /* scale for platforms that don't give you the window size you asked for. */
   178     SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
   179 
   180     background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
   181     button = LoadTexture(screen, "button.bmp", SDL_TRUE);
   182     axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
   183 
   184     if (!background || !button || !axis) {
   185         SDL_DestroyRenderer(screen);
   186         SDL_DestroyWindow(window);
   187         return SDL_FALSE;
   188     }
   189     SDL_SetTextureColorMod(button, 10, 255, 21);
   190     SDL_SetTextureColorMod(axis, 10, 255, 21);
   191 
   192     /* !!! FIXME: */
   193     /*SDL_RenderSetLogicalSize(screen, background->w, background->h);*/
   194 
   195     /* Print info about the controller we are watching */
   196     SDL_Log("Watching controller %s\n",  name ? name : "Unknown Controller");
   197 
   198     /* Loop, getting controller events! */
   199     while (!done) {
   200         /* blank screen, set up for drawing this frame. */
   201         SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
   202         SDL_RenderClear(screen);
   203         SDL_RenderCopy(screen, background, NULL, NULL);
   204 
   205         while (SDL_PollEvent(&event)) {
   206             switch (event.type) {
   207             case SDL_KEYDOWN:
   208                 if (event.key.keysym.sym != SDLK_ESCAPE) {
   209                     break;
   210                 }
   211                 /* Fall through to signal quit */
   212             case SDL_QUIT:
   213                 done = SDL_TRUE;
   214                 break;
   215             default:
   216                 break;
   217             }
   218         }
   219 
   220         /* Update visual controller state */
   221         for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) {
   222             if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
   223                 const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 };
   224                 SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, 0);
   225             }
   226         }
   227 
   228         for (i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) {
   229             const Sint16 deadzone = 8000;  /* !!! FIXME: real deadzone */
   230             const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i));
   231             if (value < -deadzone) {
   232                 const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
   233                 const double angle = axis_positions[i].angle;
   234                 SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0);
   235             } else if (value > deadzone) {
   236                 const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
   237                 const double angle = axis_positions[i].angle + 180.0;
   238                 SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0);
   239             }
   240         }
   241 
   242         SDL_RenderPresent(screen);
   243 
   244         if (!SDL_GameControllerGetAttached(gamecontroller)) {
   245             done = SDL_TRUE;
   246             retval = SDL_TRUE;  /* keep going, wait for reattach. */
   247         }
   248     }
   249 
   250     SDL_DestroyRenderer(screen);
   251     SDL_DestroyWindow(window);
   252     return retval;
   253 }
   254 
   255 int
   256 main(int argc, char *argv[])
   257 {
   258     int i;
   259     int nController = 0;
   260     int retcode = 0;
   261     char guid[64];
   262     SDL_GameController *gamecontroller;
   263 
   264     /* Enable standard application logging */
   265 	SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   266 
   267     /* Initialize SDL (Note: video is required to start event loop) */
   268     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER ) < 0) {
   269         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
   270         return 1;
   271     }
   272     
   273     SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
   274 
   275     /* Print information about the controller */
   276     for (i = 0; i < SDL_NumJoysticks(); ++i) {
   277         const char *name;
   278         const char *description;
   279 
   280         SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i),
   281                                   guid, sizeof (guid));
   282 
   283         if ( SDL_IsGameController(i) )
   284         {
   285             nController++;
   286             name = SDL_GameControllerNameForIndex(i);
   287             description = "Controller";
   288         } else {
   289             name = SDL_JoystickNameForIndex(i);
   290             description = "Joystick";
   291         }
   292         SDL_Log("%s %d: %s (guid %s)\n", description, i, name ? name : "Unknown", guid);
   293     }
   294     SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n", nController, SDL_NumJoysticks());
   295 
   296     if (argv[1]) {
   297         SDL_bool reportederror = SDL_FALSE;
   298         SDL_bool keepGoing = SDL_TRUE;
   299         SDL_Event event;
   300         int device = atoi(argv[1]);
   301         if (device >= SDL_NumJoysticks()) {
   302 			SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%i is an invalid joystick index.\n", device);
   303             retcode = 1;
   304         } else {
   305             SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(device),
   306                                       guid, sizeof (guid));
   307             SDL_Log("Attempting to open device %i, guid %s\n", device, guid);
   308             gamecontroller = SDL_GameControllerOpen(device);
   309             while (keepGoing) {
   310                 if (gamecontroller == NULL) {
   311                     if (!reportederror) {
   312                         if (gamecontroller == NULL) {
   313                             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open gamecontroller %d: %s\n", device, SDL_GetError());
   314                             retcode = 1;
   315                         }
   316                         keepGoing = SDL_FALSE;
   317                         reportederror = SDL_TRUE;
   318                     }
   319                 } else {
   320                     reportederror = SDL_FALSE;
   321                     keepGoing = WatchGameController(gamecontroller);
   322                     SDL_GameControllerClose(gamecontroller);
   323                 }
   324 
   325                 gamecontroller = NULL;
   326                 if (keepGoing) {
   327                     SDL_Log("Waiting for attach\n");
   328                 }
   329                 while (keepGoing) {
   330                     SDL_WaitEvent(&event);
   331                     if ((event.type == SDL_QUIT) || (event.type == SDL_FINGERDOWN)
   332                         || (event.type == SDL_MOUSEBUTTONDOWN)) {
   333                         keepGoing = SDL_FALSE;
   334                     } else if (event.type == SDL_CONTROLLERDEVICEADDED) {
   335                         gamecontroller = SDL_GameControllerOpen(event.cdevice.which);
   336                         break;
   337                     }
   338                 }
   339             }
   340         }
   341     }
   342 
   343     SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
   344 
   345     return retcode;
   346 }
   347 
   348 #else
   349 
   350 int
   351 main(int argc, char *argv[])
   352 {
   353     SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
   354     exit(1);
   355 }
   356 
   357 #endif