test/controllermap.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Fri, 16 Dec 2016 22:58:32 +0100
changeset 10707 28c1a3f9c88b
parent 10706 71ce5d7d2610
child 10724 5ea5f198879f
permissions -rw-r--r--
Fixed hotplug with more than one device in testjoystick program.
gabomdq@8043
     1
/*
slouken@9998
     2
  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
gabomdq@8043
     3
gabomdq@8043
     4
  This software is provided 'as-is', without any express or implied
gabomdq@8043
     5
  warranty.  In no event will the authors be held liable for any damages
gabomdq@8043
     6
  arising from the use of this software.
gabomdq@8043
     7
gabomdq@8043
     8
  Permission is granted to anyone to use this software for any purpose,
gabomdq@8043
     9
  including commercial applications, and to alter it and redistribute it
gabomdq@8043
    10
  freely.
gabomdq@8043
    11
*/
gabomdq@8043
    12
gabomdq@8043
    13
/* Game controller mapping generator */
gabomdq@8043
    14
/* Gabriel Jacobo <gabomdq@gmail.com> */
gabomdq@8043
    15
gabomdq@8043
    16
#include <stdio.h>
gabomdq@8043
    17
#include <stdlib.h>
gabomdq@8043
    18
#include <string.h>
gabomdq@8043
    19
gabomdq@8043
    20
#include "SDL.h"
gabomdq@8043
    21
gabomdq@8043
    22
#ifndef SDL_JOYSTICK_DISABLED
gabomdq@8043
    23
gabomdq@8043
    24
#ifdef __IPHONEOS__
gabomdq@8043
    25
#define SCREEN_WIDTH    320
gabomdq@8043
    26
#define SCREEN_HEIGHT   480
gabomdq@8043
    27
#else
gabomdq@8043
    28
#define SCREEN_WIDTH    512
slouken@10526
    29
#define SCREEN_HEIGHT   320
gabomdq@8043
    30
#endif
gabomdq@8043
    31
gabomdq@8043
    32
#define MARKER_BUTTON 1
gabomdq@8043
    33
#define MARKER_AXIS 2
gabomdq@8043
    34
slouken@10705
    35
#define BINDING_COUNT (SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_MAX)
slouken@10705
    36
slouken@10705
    37
static struct 
gabomdq@8043
    38
{
gabomdq@8043
    39
    int x, y;
gabomdq@8043
    40
    double angle;
gabomdq@8043
    41
    int marker;
gabomdq@8043
    42
slouken@10705
    43
} s_arrBindingDisplay[BINDING_COUNT] = {
slouken@10705
    44
    { 387, 167, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_A */
slouken@10705
    45
    { 431, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_B */
slouken@10705
    46
    { 342, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_X */
slouken@10705
    47
    { 389, 101, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_Y */
slouken@10705
    48
    { 174, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_BACK */
slouken@10705
    49
    { 233, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_GUIDE */
slouken@10705
    50
    { 289, 132, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_START */
slouken@10705
    51
    {  75, 154, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_LEFTSTICK */
slouken@10705
    52
    { 305, 230, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_RIGHTSTICK */
slouken@10705
    53
    {  77,  40, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_LEFTSHOULDER */
slouken@10705
    54
    { 396,  36, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_RIGHTSHOULDER */
slouken@10705
    55
    { 154, 188, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_UP */
slouken@10705
    56
    { 154, 249, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_DOWN */
slouken@10705
    57
    { 116, 217, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_LEFT */
slouken@10705
    58
    { 186, 217, 0.0, MARKER_BUTTON }, /* SDL_CONTROLLER_BUTTON_DPAD_RIGHT */
slouken@10705
    59
    {  75, 154, 0.0,   MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_LEFTX */
slouken@10705
    60
    {  75, 154, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_LEFTY */
slouken@10705
    61
    { 305, 230, 0.0,   MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_RIGHTX */
slouken@10705
    62
    { 305, 230, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_RIGHTY */
slouken@10705
    63
    {  91,   0, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_TRIGGERLEFT */
slouken@10705
    64
    { 375,   0, 90.0,  MARKER_AXIS }, /* SDL_CONTROLLER_AXIS_TRIGGERRIGHT */
slouken@10705
    65
};
slouken@10705
    66
slouken@10705
    67
static int s_arrBindingOrder[BINDING_COUNT] = {
slouken@10705
    68
    SDL_CONTROLLER_BUTTON_A,
slouken@10705
    69
    SDL_CONTROLLER_BUTTON_B,
slouken@10705
    70
    SDL_CONTROLLER_BUTTON_Y,
slouken@10705
    71
    SDL_CONTROLLER_BUTTON_X,
slouken@10705
    72
    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_LEFTX,
slouken@10705
    73
    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_LEFTY,
slouken@10705
    74
    SDL_CONTROLLER_BUTTON_LEFTSTICK,
slouken@10705
    75
    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_RIGHTX,
slouken@10705
    76
    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_RIGHTY,
slouken@10705
    77
    SDL_CONTROLLER_BUTTON_RIGHTSTICK,
slouken@10705
    78
    SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
slouken@10705
    79
    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_TRIGGERLEFT,
slouken@10705
    80
    SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
slouken@10705
    81
    SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
slouken@10705
    82
    SDL_CONTROLLER_BUTTON_DPAD_UP,
slouken@10705
    83
    SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
slouken@10705
    84
    SDL_CONTROLLER_BUTTON_DPAD_DOWN,
slouken@10705
    85
    SDL_CONTROLLER_BUTTON_DPAD_LEFT,
slouken@10705
    86
    SDL_CONTROLLER_BUTTON_BACK,
slouken@10705
    87
    SDL_CONTROLLER_BUTTON_GUIDE,
slouken@10705
    88
    SDL_CONTROLLER_BUTTON_START,
slouken@10705
    89
};
slouken@10705
    90
slouken@10705
    91
static SDL_GameControllerButtonBind s_arrBindings[BINDING_COUNT];
slouken@10705
    92
static int s_iCurrentBinding;
slouken@10705
    93
static Uint32 s_unPendingAdvanceTime;
slouken@10705
    94
static SDL_bool s_bBindingComplete;
gabomdq@8043
    95
gabomdq@8043
    96
SDL_Texture *
philipp@10359
    97
LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
gabomdq@8043
    98
{
gabomdq@8043
    99
    SDL_Surface *temp;
gabomdq@8043
   100
    SDL_Texture *texture;
gabomdq@8043
   101
gabomdq@8043
   102
    /* Load the sprite image */
gabomdq@8043
   103
    temp = SDL_LoadBMP(file);
gabomdq@8043
   104
    if (temp == NULL) {
gabomdq@8043
   105
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
gabomdq@8043
   106
        return NULL;
gabomdq@8043
   107
    }
gabomdq@8043
   108
gabomdq@8043
   109
    /* Set transparent pixel as the pixel at (0,0) */
gabomdq@8043
   110
    if (transparent) {
gabomdq@8043
   111
        if (temp->format->palette) {
gabomdq@8043
   112
            SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels);
gabomdq@8043
   113
        } else {
gabomdq@8043
   114
            switch (temp->format->BitsPerPixel) {
gabomdq@8043
   115
            case 15:
gabomdq@8043
   116
                SDL_SetColorKey(temp, SDL_TRUE,
gabomdq@8043
   117
                                (*(Uint16 *) temp->pixels) & 0x00007FFF);
gabomdq@8043
   118
                break;
gabomdq@8043
   119
            case 16:
gabomdq@8043
   120
                SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels);
gabomdq@8043
   121
                break;
gabomdq@8043
   122
            case 24:
gabomdq@8043
   123
                SDL_SetColorKey(temp, SDL_TRUE,
gabomdq@8043
   124
                                (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
gabomdq@8043
   125
                break;
gabomdq@8043
   126
            case 32:
gabomdq@8043
   127
                SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels);
gabomdq@8043
   128
                break;
gabomdq@8043
   129
            }
gabomdq@8043
   130
        }
gabomdq@8043
   131
    }
gabomdq@8043
   132
gabomdq@8043
   133
    /* Create textures from the image */
gabomdq@8043
   134
    texture = SDL_CreateTextureFromSurface(renderer, temp);
gabomdq@8043
   135
    if (!texture) {
gabomdq@8043
   136
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
gabomdq@8043
   137
        SDL_FreeSurface(temp);
gabomdq@8043
   138
        return NULL;
gabomdq@8043
   139
    }
gabomdq@8043
   140
    SDL_FreeSurface(temp);
gabomdq@8043
   141
gabomdq@8043
   142
    /* We're ready to roll. :) */
gabomdq@8043
   143
    return texture;
gabomdq@8043
   144
}
gabomdq@8043
   145
slouken@10705
   146
void SetCurrentBinding(int iBinding)
slouken@10705
   147
{
slouken@10705
   148
    SDL_GameControllerButtonBind *pBinding;
slouken@10705
   149
slouken@10705
   150
    if (iBinding < 0) {
slouken@10705
   151
        return;
slouken@10705
   152
    }
slouken@10705
   153
slouken@10705
   154
    if (iBinding == BINDING_COUNT) {
slouken@10705
   155
        s_bBindingComplete = SDL_TRUE;
slouken@10705
   156
        return;
slouken@10705
   157
    }
slouken@10705
   158
slouken@10705
   159
    s_iCurrentBinding = iBinding;
slouken@10705
   160
slouken@10705
   161
    pBinding = &s_arrBindings[s_arrBindingOrder[s_iCurrentBinding]];
slouken@10705
   162
    SDL_zerop(pBinding);
slouken@10705
   163
slouken@10705
   164
    s_unPendingAdvanceTime = 0;
slouken@10705
   165
}
slouken@10705
   166
slouken@10705
   167
slouken@10705
   168
static void
slouken@10705
   169
ConfigureBinding(const SDL_GameControllerButtonBind *pBinding)
slouken@10705
   170
{
slouken@10705
   171
    SDL_GameControllerButtonBind *pCurrent;
slouken@10705
   172
    int iIndex;
slouken@10705
   173
    int iCurrentElement = s_arrBindingOrder[s_iCurrentBinding];
slouken@10705
   174
slouken@10705
   175
    /* Do we already have this binding? */
slouken@10705
   176
    for (iIndex = 0; iIndex < SDL_arraysize(s_arrBindings); ++iIndex) {
slouken@10705
   177
        if (SDL_memcmp(pBinding, &s_arrBindings[iIndex], sizeof(*pBinding)) == 0) {
slouken@10705
   178
            if (iIndex == SDL_CONTROLLER_BUTTON_A && iCurrentElement != SDL_CONTROLLER_BUTTON_B) {
slouken@10705
   179
                /* Skip to the next binding */
slouken@10705
   180
                SetCurrentBinding(s_iCurrentBinding + 1);
slouken@10705
   181
                return;
slouken@10705
   182
            }
slouken@10705
   183
slouken@10705
   184
            if (iIndex == SDL_CONTROLLER_BUTTON_B) {
slouken@10705
   185
                /* Go back to the previous binding */
slouken@10705
   186
                SetCurrentBinding(s_iCurrentBinding - 1);
slouken@10705
   187
                return;
slouken@10705
   188
            }
slouken@10705
   189
slouken@10705
   190
            /* Already have this binding, ignore it */
slouken@10705
   191
            return;
slouken@10705
   192
        }
slouken@10705
   193
    }
slouken@10705
   194
slouken@10705
   195
    /* Should the new binding override the existing one? */
slouken@10705
   196
    pCurrent = &s_arrBindings[iCurrentElement];
slouken@10705
   197
    if (pCurrent->bindType != SDL_CONTROLLER_BINDTYPE_NONE) {
slouken@10705
   198
        SDL_bool bNativeDPad, bCurrentDPad;
slouken@10705
   199
        SDL_bool bNativeAxis, bCurrentAxis;
slouken@10705
   200
        
slouken@10705
   201
        bNativeDPad = (iCurrentElement == SDL_CONTROLLER_BUTTON_DPAD_UP ||
slouken@10705
   202
                       iCurrentElement == SDL_CONTROLLER_BUTTON_DPAD_DOWN ||
slouken@10705
   203
                       iCurrentElement == SDL_CONTROLLER_BUTTON_DPAD_LEFT ||
slouken@10705
   204
                       iCurrentElement == SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
slouken@10705
   205
        bCurrentDPad = (pCurrent->bindType == SDL_CONTROLLER_BINDTYPE_HAT);
slouken@10705
   206
        if (bNativeDPad == bCurrentDPad) {
slouken@10705
   207
            /* We already have a binding of the type we want, ignore the new one */
slouken@10705
   208
            return;
slouken@10705
   209
        }
slouken@10705
   210
slouken@10705
   211
        bNativeAxis = (iCurrentElement >= SDL_CONTROLLER_BUTTON_MAX);
slouken@10705
   212
        bCurrentAxis = (pCurrent->bindType == SDL_CONTROLLER_BINDTYPE_AXIS);
slouken@10705
   213
        if (bNativeAxis == bCurrentAxis) {
slouken@10705
   214
            /* We already have a binding of the type we want, ignore the new one */
slouken@10705
   215
            return;
slouken@10705
   216
        }
slouken@10705
   217
    }
slouken@10705
   218
slouken@10705
   219
    *pCurrent = *pBinding;
slouken@10705
   220
slouken@10705
   221
    s_unPendingAdvanceTime = SDL_GetTicks();
slouken@10705
   222
}
slouken@10705
   223
slouken@10705
   224
static void
gabomdq@8043
   225
WatchJoystick(SDL_Joystick * joystick)
gabomdq@8043
   226
{
gabomdq@8043
   227
    SDL_Window *window = NULL;
gabomdq@8043
   228
    SDL_Renderer *screen = NULL;
icculus@8202
   229
    SDL_Texture *background, *button, *axis, *marker;
gabomdq@8043
   230
    const char *name = NULL;
slouken@10705
   231
    SDL_bool done = SDL_FALSE;
gabomdq@8043
   232
    SDL_Event event;
gabomdq@8043
   233
    SDL_Rect dst;
gabomdq@8043
   234
    Uint8 alpha=200, alpha_step = -1;
philipp@8786
   235
    Uint32 alpha_ticks = 0;
slouken@10705
   236
    SDL_JoystickID nJoystickID;
slouken@10705
   237
    Uint32 unDeflectedAxes = 0;
gabomdq@8043
   238
gabomdq@8043
   239
    /* Create a window to display joystick axis position */
gabomdq@8046
   240
    window = SDL_CreateWindow("Game Controller Map", SDL_WINDOWPOS_CENTERED,
gabomdq@8043
   241
                              SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
gabomdq@8043
   242
                              SCREEN_HEIGHT, 0);
gabomdq@8043
   243
    if (window == NULL) {
gabomdq@8043
   244
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
slouken@10705
   245
        return;
gabomdq@8043
   246
    }
gabomdq@8043
   247
gabomdq@8043
   248
    screen = SDL_CreateRenderer(window, -1, 0);
gabomdq@8043
   249
    if (screen == NULL) {
gabomdq@8043
   250
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
gabomdq@8043
   251
        SDL_DestroyWindow(window);
slouken@10705
   252
        return;
gabomdq@8043
   253
    }
gabomdq@8043
   254
    
gabomdq@8043
   255
    background = LoadTexture(screen, "controllermap.bmp", SDL_FALSE);
gabomdq@8043
   256
    button = LoadTexture(screen, "button.bmp", SDL_TRUE);
gabomdq@8043
   257
    axis = LoadTexture(screen, "axis.bmp", SDL_TRUE);
gabomdq@8043
   258
    SDL_RaiseWindow(window);
gabomdq@8043
   259
icculus@8202
   260
    /* scale for platforms that don't give you the window size you asked for. */
icculus@8202
   261
    SDL_RenderSetLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
icculus@8202
   262
gabomdq@8043
   263
    /* Print info about the joystick we are watching */
gabomdq@8043
   264
    name = SDL_JoystickName(joystick);
gabomdq@8043
   265
    SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
gabomdq@8043
   266
           name ? name : "Unknown Joystick");
gabomdq@8043
   267
    SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
gabomdq@8043
   268
           SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
gabomdq@8043
   269
           SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
gabomdq@8043
   270
    
gabomdq@8043
   271
    SDL_Log("\n\n\
gabomdq@8043
   272
    ====================================================================================\n\
gabomdq@8043
   273
    Press the buttons on your controller when indicated\n\
gabomdq@8043
   274
    (Your controller may look different than the picture)\n\
gabomdq@8043
   275
    If you want to correct a mistake, press backspace or the back button on your device\n\
gabomdq@8046
   276
    To skip a button, press SPACE or click/touch the screen\n\
gabomdq@8043
   277
    To exit, press ESC\n\
gabomdq@8043
   278
    ====================================================================================\n");
slouken@10705
   279
slouken@10705
   280
    nJoystickID = SDL_JoystickInstanceID(joystick);
gabomdq@8043
   281
gabomdq@8043
   282
    /* Loop, getting joystick events! */
slouken@10705
   283
    while (!done && !s_bBindingComplete) {
slouken@10705
   284
        int iElement = s_arrBindingOrder[s_iCurrentBinding];
slouken@10705
   285
slouken@10705
   286
        switch (s_arrBindingDisplay[iElement].marker) {
gabomdq@8043
   287
            case MARKER_AXIS:
gabomdq@8043
   288
                marker = axis;
gabomdq@8043
   289
                break;
gabomdq@8043
   290
            case MARKER_BUTTON:
gabomdq@8043
   291
                marker = button;
gabomdq@8043
   292
                break;
gabomdq@8043
   293
            default:
gabomdq@8043
   294
                break;
gabomdq@8043
   295
        }
gabomdq@8043
   296
        
slouken@10705
   297
        dst.x = s_arrBindingDisplay[iElement].x;
slouken@10705
   298
        dst.y = s_arrBindingDisplay[iElement].y;
gabomdq@8043
   299
        SDL_QueryTexture(marker, NULL, NULL, &dst.w, &dst.h);
icculus@8202
   300
slouken@10705
   301
        if (SDL_GetTicks() - alpha_ticks > 5) {
slouken@10705
   302
            alpha_ticks = SDL_GetTicks();
slouken@10705
   303
            alpha += alpha_step;
slouken@10705
   304
            if (alpha == 255) {
slouken@10705
   305
                alpha_step = -1;
gabomdq@8043
   306
            }
slouken@10705
   307
            if (alpha < 128) {
slouken@10705
   308
                alpha_step = 1;
gabomdq@8043
   309
            }
gabomdq@8043
   310
        }
gabomdq@8043
   311
slouken@10705
   312
        SDL_SetRenderDrawColor(screen, 0xFF, 0xFF, 0xFF, SDL_ALPHA_OPAQUE);
slouken@10705
   313
        SDL_RenderClear(screen);
slouken@10705
   314
        SDL_RenderCopy(screen, background, NULL, NULL);
slouken@10705
   315
        SDL_SetTextureAlphaMod(marker, alpha);
slouken@10705
   316
        SDL_SetTextureColorMod(marker, 10, 255, 21);
slouken@10705
   317
        SDL_RenderCopyEx(screen, marker, NULL, &dst, s_arrBindingDisplay[iElement].angle, NULL, SDL_FLIP_NONE);
slouken@10705
   318
        SDL_RenderPresent(screen);
slouken@10705
   319
            
slouken@10705
   320
        while (SDL_PollEvent(&event) > 0) {
slouken@10705
   321
            switch (event.type) {
slouken@10705
   322
            case SDL_JOYDEVICEREMOVED:
slouken@10705
   323
                if (event.jaxis.which == nJoystickID) {
slouken@10705
   324
                    done = SDL_TRUE;
slouken@10705
   325
                }
slouken@10705
   326
                break;
slouken@10705
   327
            case SDL_JOYAXISMOTION:
slouken@10705
   328
                if (event.jaxis.which == nJoystickID) {
slouken@10705
   329
                    uint32_t unAxisMask = (1 << event.jaxis.axis);
slouken@10705
   330
                    SDL_bool bDeflected = (event.jaxis.value <= -20000 || event.jaxis.value >= 20000);
slouken@10705
   331
                    if (bDeflected && !(unDeflectedAxes & unAxisMask)) {
slouken@10705
   332
                        SDL_GameControllerButtonBind binding;
slouken@10705
   333
                        SDL_zero(binding);
slouken@10705
   334
                        binding.bindType = SDL_CONTROLLER_BINDTYPE_AXIS;
slouken@10705
   335
                        binding.value.axis = event.jaxis.axis;
slouken@10705
   336
                        ConfigureBinding(&binding);
slouken@10705
   337
                    }
slouken@10705
   338
                    if (bDeflected) {
slouken@10705
   339
                        unDeflectedAxes |= unAxisMask;
slouken@10705
   340
                    } else {
slouken@10705
   341
                        unDeflectedAxes &= ~unAxisMask;
slouken@10705
   342
                    }
slouken@10705
   343
                }
slouken@10705
   344
                break;
slouken@10705
   345
            case SDL_JOYHATMOTION:
slouken@10705
   346
                if (event.jhat.which == nJoystickID) {
slouken@10705
   347
                    if (event.jhat.value != SDL_HAT_CENTERED) {
slouken@10705
   348
                        SDL_GameControllerButtonBind binding;
slouken@10705
   349
                        SDL_zero(binding);
slouken@10705
   350
                        binding.bindType = SDL_CONTROLLER_BINDTYPE_HAT;
slouken@10705
   351
                        binding.value.hat.hat = event.jhat.hat;
slouken@10705
   352
                        binding.value.hat.hat_mask = event.jhat.value;
slouken@10705
   353
                        ConfigureBinding(&binding);
slouken@10705
   354
                    }
slouken@10705
   355
                }
slouken@10705
   356
                break;
slouken@10705
   357
            case SDL_JOYBALLMOTION:
slouken@10705
   358
                break;
slouken@10705
   359
            case SDL_JOYBUTTONDOWN:
slouken@10705
   360
                if (event.jbutton.which == nJoystickID) {
slouken@10705
   361
                    SDL_GameControllerButtonBind binding;
slouken@10705
   362
                    SDL_zero(binding);
slouken@10705
   363
                    binding.bindType = SDL_CONTROLLER_BINDTYPE_BUTTON;
slouken@10705
   364
                    binding.value.button = event.jbutton.button;
slouken@10705
   365
                    ConfigureBinding(&binding);
slouken@10705
   366
                }
slouken@10705
   367
                break;
slouken@10705
   368
            case SDL_FINGERDOWN:
slouken@10705
   369
            case SDL_MOUSEBUTTONDOWN:
slouken@10705
   370
                /* Skip this step */
slouken@10705
   371
                SetCurrentBinding(s_iCurrentBinding + 1);
slouken@10705
   372
                break;
slouken@10705
   373
            case SDL_KEYDOWN:
slouken@10705
   374
                if (event.key.keysym.sym == SDLK_BACKSPACE || event.key.keysym.sym == SDLK_AC_BACK) {
slouken@10705
   375
                    SetCurrentBinding(s_iCurrentBinding - 1);
slouken@10705
   376
                    break;
slouken@10705
   377
                }
slouken@10705
   378
                if (event.key.keysym.sym == SDLK_SPACE) {
slouken@10705
   379
                    SetCurrentBinding(s_iCurrentBinding + 1);
slouken@10705
   380
                    break;
slouken@10705
   381
                }
slouken@10705
   382
slouken@10705
   383
                if ((event.key.keysym.sym != SDLK_ESCAPE)) {
slouken@10705
   384
                    break;
slouken@10705
   385
                }
slouken@10705
   386
                /* Fall through to signal quit */
slouken@10705
   387
            case SDL_QUIT:
slouken@10705
   388
                done = SDL_TRUE;
slouken@10705
   389
                break;
slouken@10705
   390
            default:
slouken@10705
   391
                break;
slouken@10705
   392
            }
slouken@10705
   393
        }
slouken@10705
   394
slouken@10705
   395
        SDL_Delay(15);
slouken@10705
   396
slouken@10705
   397
        /* Wait 100 ms for joystick events to stop coming in,
slouken@10705
   398
           in case a controller sends multiple events for a single control (e.g. axis and button for trigger)
slouken@10705
   399
        */
slouken@10705
   400
        if (s_unPendingAdvanceTime && SDL_GetTicks() - s_unPendingAdvanceTime >= 100) {
slouken@10705
   401
            SetCurrentBinding(s_iCurrentBinding + 1);
slouken@10705
   402
        }
gabomdq@8043
   403
    }
gabomdq@8043
   404
slouken@10705
   405
    if (s_bBindingComplete) {
slouken@10705
   406
        char mapping[1024];
slouken@10705
   407
        char trimmed_name[128];
slouken@10705
   408
        char *spot;
slouken@10705
   409
        int iIndex;
slouken@10705
   410
        char pszElement[12];
slouken@10705
   411
slouken@10705
   412
        SDL_strlcpy(trimmed_name, name, SDL_arraysize(trimmed_name));
slouken@10705
   413
        while (SDL_isspace(trimmed_name[0])) {
slouken@10705
   414
            SDL_memmove(&trimmed_name[0], &trimmed_name[1], SDL_strlen(trimmed_name));
slouken@10705
   415
        }
slouken@10705
   416
        while (trimmed_name[0] && SDL_isspace(trimmed_name[SDL_strlen(trimmed_name) - 1])) {
slouken@10705
   417
            trimmed_name[SDL_strlen(trimmed_name) - 1] = '\0';
slouken@10705
   418
        }
slouken@10705
   419
        while ((spot = SDL_strchr(trimmed_name, ',')) != NULL) {
slouken@10705
   420
            SDL_memmove(spot, spot + 1, SDL_strlen(spot));
slouken@10705
   421
        }
slouken@10705
   422
slouken@10705
   423
        /* Initialize mapping with GUID and name */
slouken@10705
   424
        SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), mapping, SDL_arraysize(mapping));
slouken@10705
   425
        SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
slouken@10705
   426
        SDL_strlcat(mapping, trimmed_name, SDL_arraysize(mapping));
slouken@10705
   427
        SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
slouken@10705
   428
        SDL_strlcat(mapping, "platform:", SDL_arraysize(mapping));
slouken@10705
   429
        SDL_strlcat(mapping, SDL_GetPlatform(), SDL_arraysize(mapping));
slouken@10705
   430
        SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
slouken@10705
   431
slouken@10705
   432
        for (iIndex = 0; iIndex < SDL_arraysize(s_arrBindings); ++iIndex) {
slouken@10705
   433
            SDL_GameControllerButtonBind *pBinding = &s_arrBindings[iIndex];
slouken@10705
   434
            if (pBinding->bindType == SDL_CONTROLLER_BINDTYPE_NONE) {
slouken@10705
   435
                continue;
slouken@10705
   436
            }
slouken@10705
   437
slouken@10705
   438
            if (iIndex < SDL_CONTROLLER_BUTTON_MAX) {
slouken@10705
   439
                SDL_GameControllerButton eButton = (SDL_GameControllerButton)iIndex;
slouken@10705
   440
                SDL_strlcat(mapping, SDL_GameControllerGetStringForButton(eButton), SDL_arraysize(mapping));
slouken@10705
   441
            } else {
slouken@10705
   442
                SDL_GameControllerAxis eAxis = (SDL_GameControllerAxis)(iIndex - SDL_CONTROLLER_BUTTON_MAX);
slouken@10705
   443
                SDL_strlcat(mapping, SDL_GameControllerGetStringForAxis(eAxis), SDL_arraysize(mapping));
slouken@10705
   444
            }
slouken@10705
   445
            SDL_strlcat(mapping, ":", SDL_arraysize(mapping));
slouken@10705
   446
slouken@10705
   447
            pszElement[0] = '\0';
slouken@10705
   448
            switch (pBinding->bindType) {
slouken@10705
   449
            case SDL_CONTROLLER_BINDTYPE_BUTTON:
slouken@10705
   450
                SDL_snprintf(pszElement, sizeof(pszElement), "b%d", pBinding->value.button);
slouken@10705
   451
                break;
slouken@10705
   452
            case SDL_CONTROLLER_BINDTYPE_AXIS:
slouken@10705
   453
                SDL_snprintf(pszElement, sizeof(pszElement), "a%d", pBinding->value.axis);
slouken@10705
   454
                break;
slouken@10705
   455
            case SDL_CONTROLLER_BINDTYPE_HAT:
slouken@10705
   456
                SDL_snprintf(pszElement, sizeof(pszElement), "h%d.%d", pBinding->value.hat.hat, pBinding->value.hat.hat_mask);
slouken@10705
   457
                break;
slouken@10705
   458
            default:
slouken@10705
   459
                SDL_assert(!"Unknown bind type");
slouken@10705
   460
                break;
slouken@10705
   461
            }
slouken@10705
   462
            SDL_strlcat(mapping, pszElement, SDL_arraysize(mapping));
slouken@10705
   463
            SDL_strlcat(mapping, ",", SDL_arraysize(mapping));
slouken@10705
   464
        }
slouken@10705
   465
gabomdq@8043
   466
        SDL_Log("Mapping:\n\n%s\n\n", mapping);
gabomdq@8043
   467
        /* Print to stdout as well so the user can cat the output somewhere */
gabomdq@8043
   468
        printf("%s\n", mapping);
gabomdq@8043
   469
    }
gabomdq@8043
   470
    
gabomdq@8043
   471
    SDL_DestroyRenderer(screen);
gabomdq@8043
   472
    SDL_DestroyWindow(window);
gabomdq@8043
   473
}
gabomdq@8043
   474
gabomdq@8043
   475
int
gabomdq@8043
   476
main(int argc, char *argv[])
gabomdq@8043
   477
{
gabomdq@8043
   478
    const char *name;
gabomdq@8043
   479
    int i;
gabomdq@8043
   480
    SDL_Joystick *joystick;
gabomdq@8043
   481
gabomdq@8043
   482
    /* Enable standard application logging */
philipp@9922
   483
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
gabomdq@8043
   484
gabomdq@8043
   485
    /* Initialize SDL (Note: video is required to start event loop) */
gabomdq@8043
   486
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
gabomdq@8043
   487
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
gabomdq@8043
   488
        exit(1);
gabomdq@8043
   489
    }
gabomdq@8043
   490
gabomdq@8043
   491
    /* Print information about the joysticks */
gabomdq@8043
   492
    SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
gabomdq@8043
   493
    for (i = 0; i < SDL_NumJoysticks(); ++i) {
gabomdq@8043
   494
        name = SDL_JoystickNameForIndex(i);
gabomdq@8043
   495
        SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
gabomdq@8043
   496
        joystick = SDL_JoystickOpen(i);
gabomdq@8043
   497
        if (joystick == NULL) {
gabomdq@8043
   498
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
gabomdq@8043
   499
                    SDL_GetError());
gabomdq@8043
   500
        } else {
gabomdq@8043
   501
            char guid[64];
gabomdq@8043
   502
            SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
gabomdq@8043
   503
                                      guid, sizeof (guid));
gabomdq@8043
   504
            SDL_Log("       axes: %d\n", SDL_JoystickNumAxes(joystick));
gabomdq@8043
   505
            SDL_Log("      balls: %d\n", SDL_JoystickNumBalls(joystick));
gabomdq@8043
   506
            SDL_Log("       hats: %d\n", SDL_JoystickNumHats(joystick));
gabomdq@8043
   507
            SDL_Log("    buttons: %d\n", SDL_JoystickNumButtons(joystick));
gabomdq@8043
   508
            SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
gabomdq@8043
   509
            SDL_Log("       guid: %s\n", guid);
slouken@10597
   510
            SDL_Log("    VID/PID: 0x%.4x/0x%.4x\n", SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick));
gabomdq@8043
   511
            SDL_JoystickClose(joystick);
gabomdq@8043
   512
        }
gabomdq@8043
   513
    }
gabomdq@8043
   514
gabomdq@8762
   515
#ifdef __ANDROID__
gabomdq@8043
   516
    if (SDL_NumJoysticks() > 0) {
gabomdq@8043
   517
#else
gabomdq@8043
   518
    if (argv[1]) {
gabomdq@8043
   519
#endif
philipp@8078
   520
        int device;
gabomdq@8762
   521
#ifdef __ANDROID__
philipp@8078
   522
        device = 0;
gabomdq@8043
   523
#else
philipp@8078
   524
        device = atoi(argv[1]);
gabomdq@8043
   525
#endif
philipp@8078
   526
        joystick = SDL_JoystickOpen(device);
slouken@10705
   527
        if (joystick == NULL) {
slouken@10705
   528
            SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
slouken@10705
   529
        } else {
slouken@10705
   530
            WatchJoystick(joystick);
slouken@10705
   531
            SDL_JoystickClose(joystick);
gabomdq@8043
   532
        }
gabomdq@8043
   533
    }
gabomdq@8043
   534
    else {
gabomdq@8043
   535
        SDL_Log("\n\nUsage: ./controllermap number\nFor example: ./controllermap 0\nOr: ./controllermap 0 >> gamecontrollerdb.txt");
gabomdq@8043
   536
    }
gabomdq@8043
   537
    SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
gabomdq@8043
   538
gabomdq@8043
   539
    return 0;
gabomdq@8043
   540
}
gabomdq@8043
   541
gabomdq@8043
   542
#else
gabomdq@8043
   543
gabomdq@8043
   544
int
gabomdq@8043
   545
main(int argc, char *argv[])
gabomdq@8043
   546
{
gabomdq@8043
   547
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Joystick support.\n");
gabomdq@8043
   548
    exit(1);
gabomdq@8043
   549
}
gabomdq@8043
   550
gabomdq@8043
   551
#endif
slouken@10597
   552
slouken@10597
   553
/* vi: set ts=4 sw=4 expandtab: */