Atlas - testgamecontroller.c

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