test/testgesture.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:09 -0800
changeset 11730 ac6c607e065c
parent 10942 62f33a66306e
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Enable building the Metal renderer by default, and weak link the Metal framework so the SDL library is safe to use on older Macs
Also generate iOS versions of the Metal shaders
slouken@5535
     1
/*
slouken@10737
     2
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@5535
     3
slouken@5535
     4
  This software is provided 'as-is', without any express or implied
slouken@5535
     5
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     6
  arising from the use of this software.
slouken@5535
     7
slouken@5535
     8
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
     9
  including commercial applications, and to alter it and redistribute it
slouken@5535
    10
  freely.
slouken@5535
    11
*/
jim@4689
    12
/*  Usage:
jim@4689
    13
 *  Spacebar to begin recording a gesture on all touches.
jim@4689
    14
 *  s to save all touches into "./gestureSave"
jim@4689
    15
 *  l to load all touches from "./gestureSave"
jim@4689
    16
 */
jim@4689
    17
slouken@5456
    18
#include "SDL.h"
philipp@9590
    19
#include <stdlib.h> /* for exit() */
jim@4689
    20
icculus@9278
    21
#ifdef __EMSCRIPTEN__
icculus@9278
    22
#include <emscripten/emscripten.h>
icculus@9278
    23
#endif
icculus@9278
    24
jim@4689
    25
#define WIDTH 640
jim@4689
    26
#define HEIGHT 480
jim@4689
    27
#define BPP 4
jim@4689
    28
gabomdq@7678
    29
/* MUST BE A POWER OF 2! */
jim@4689
    30
#define EVENT_BUF_SIZE 256
jim@4689
    31
jim@4689
    32
slouken@5458
    33
#define VERBOSE 0
jim@4689
    34
slouken@5457
    35
static SDL_Event events[EVENT_BUF_SIZE];
slouken@5457
    36
static int eventWrite;
jim@4689
    37
slouken@5456
    38
slouken@5457
    39
static int colors[7] = {0xFF,0xFF00,0xFF0000,0xFFFF00,0x00FFFF,0xFF00FF,0xFFFFFF};
jim@4689
    40
icculus@9278
    41
SDL_Surface *screen;
icculus@9289
    42
SDL_Window *window;
icculus@9278
    43
SDL_bool quitting = SDL_FALSE;
icculus@9278
    44
jim@4689
    45
typedef struct {
jim@4689
    46
  float x,y;
jim@4689
    47
} Point;
jim@4689
    48
jim@4689
    49
typedef struct {
jim@4689
    50
  float ang,r;
jim@4689
    51
  Point p;
jim@4689
    52
} Knob;
jim@4689
    53
slouken@5457
    54
static Knob knob;
jim@4689
    55
slouken@4918
    56
void setpix(SDL_Surface *screen, float _x, float _y, unsigned int col)
jim@4689
    57
{
jim@4689
    58
  Uint32 *pixmem32;
jim@4689
    59
  Uint32 colour;
slouken@4918
    60
  Uint8 r,g,b;
slouken@4918
    61
  int x = (int)_x;
slouken@4918
    62
  int y = (int)_y;
slouken@4918
    63
  float a;
slouken@7191
    64
slouken@6790
    65
  if(x < 0 || x >= screen->w) return;
slouken@6790
    66
  if(y < 0 || y >= screen->h) return;
jim@4689
    67
jim@4689
    68
  pixmem32 = (Uint32*) screen->pixels  + y*screen->pitch/BPP + x;
slouken@7191
    69
slouken@4918
    70
  SDL_memcpy(&colour,pixmem32,screen->format->BytesPerPixel);
jim@4689
    71
jim@4689
    72
  SDL_GetRGB(colour,screen->format,&r,&g,&b);
gabomdq@7678
    73
  /* r = 0;g = 0; b = 0; */
slouken@4918
    74
  a = (float)((col>>24)&0xFF);
gabomdq@7678
    75
  if(a == 0) a = 0xFF; /* Hack, to make things easier. */
jim@4689
    76
  a /= 0xFF;
slouken@4918
    77
  r = (Uint8)(r*(1-a) + ((col>>16)&0xFF)*(a));
slouken@4918
    78
  g = (Uint8)(g*(1-a) + ((col>> 8)&0xFF)*(a));
slouken@4918
    79
  b = (Uint8)(b*(1-a) + ((col>> 0)&0xFF)*(a));
jim@4689
    80
  colour = SDL_MapRGB( screen->format,r, g, b);
slouken@7191
    81
jim@4689
    82
jim@4689
    83
  *pixmem32 = colour;
jim@4689
    84
}
jim@4689
    85
slouken@4918
    86
void drawLine(SDL_Surface *screen,float x0,float y0,float x1,float y1,unsigned int col) {
jim@4689
    87
  float t;
slouken@4918
    88
  for(t=0;t<1;t+=(float)(1.f/SDL_max(SDL_fabs(x0-x1),SDL_fabs(y0-y1))))
jim@4689
    89
    setpix(screen,x1+t*(x0-x1),y1+t*(y0-y1),col);
jim@4689
    90
}
jim@4689
    91
slouken@4918
    92
void drawCircle(SDL_Surface* screen,float x,float y,float r,unsigned int c)
jim@4689
    93
{
slouken@4918
    94
  float tx,ty;
jim@4689
    95
  float xr;
slouken@4918
    96
  for(ty = (float)-SDL_fabs(r);ty <= (float)SDL_fabs((int)r);ty++) {
philipp@9274
    97
    xr = (float)SDL_sqrt(r*r - ty*ty);
gabomdq@7678
    98
    if(r > 0) { /* r > 0 ==> filled circle */
slouken@4918
    99
      for(tx=-xr+.5f;tx<=xr-.5;tx++) {
slouken@7191
   100
    setpix(screen,x+tx,y+ty,c);
jim@4689
   101
      }
jim@4689
   102
    }
jim@4689
   103
    else {
slouken@4918
   104
      setpix(screen,x-xr+.5f,y+ty,c);
slouken@4918
   105
      setpix(screen,x+xr-.5f,y+ty,c);
jim@4689
   106
    }
jim@4689
   107
  }
jim@4689
   108
}
jim@4689
   109
jim@4689
   110
void drawKnob(SDL_Surface* screen,Knob k) {
slouken@7191
   111
  drawCircle(screen,k.p.x*screen->w,k.p.y*screen->h,k.r*screen->w,0xFFFFFF);
philipp@7451
   112
  drawCircle(screen,(k.p.x+k.r/2*SDL_cosf(k.ang))*screen->w,
philipp@7451
   113
                (k.p.y+k.r/2*SDL_sinf(k.ang))*screen->h,k.r/4*screen->w,0);
jim@4689
   114
}
jim@4689
   115
philipp@9273
   116
void DrawScreen(SDL_Surface* screen, SDL_Window* window)
jim@4689
   117
{
slouken@5456
   118
  int i;
slouken@5456
   119
#if 1
slouken@5456
   120
  SDL_FillRect(screen, NULL, 0);
slouken@5456
   121
#else
slouken@5456
   122
  int x, y;
jim@4689
   123
  for(y = 0;y < screen->h;y++)
jim@4689
   124
    for(x = 0;x < screen->w;x++)
slouken@7191
   125
    setpix(screen,(float)x,(float)y,((x%255)<<16) + ((y%255)<<8) + (x+y)%255);
slouken@5456
   126
#endif
jim@4689
   127
gabomdq@7678
   128
  /* draw Touch History */
slouken@5460
   129
  for(i = eventWrite; i < eventWrite+EVENT_BUF_SIZE; ++i) {
slouken@5460
   130
    const SDL_Event *event = &events[i&(EVENT_BUF_SIZE-1)];
slouken@5460
   131
    float age = (float)(i - eventWrite) / EVENT_BUF_SIZE;
slouken@7191
   132
    float x, y;
slouken@7191
   133
    unsigned int c, col;
slouken@4918
   134
slouken@7191
   135
    if(event->type == SDL_FINGERMOTION ||
slouken@5460
   136
       event->type == SDL_FINGERDOWN ||
slouken@5460
   137
       event->type == SDL_FINGERUP) {
slouken@6951
   138
      x = event->tfinger.x;
slouken@6951
   139
      y = event->tfinger.y;
slouken@7191
   140
gabomdq@7678
   141
      /* draw the touch: */
slouken@7191
   142
      c = colors[event->tfinger.fingerId%7];
slouken@5460
   143
      col = ((unsigned int)(c*(.1+.85))) | (unsigned int)(0xFF*age)<<24;
jim@4689
   144
slouken@5460
   145
      if(event->type == SDL_FINGERMOTION)
slouken@7191
   146
    drawCircle(screen,x*screen->w,y*screen->h,5,col);
slouken@5460
   147
      else if(event->type == SDL_FINGERDOWN)
slouken@7191
   148
    drawCircle(screen,x*screen->w,y*screen->h,-10,col);
jim@4689
   149
    }
jim@4689
   150
  }
slouken@7191
   151
jim@4689
   152
  if(knob.p.x > 0)
jim@4689
   153
    drawKnob(screen,knob);
slouken@7191
   154
slouken@5456
   155
  SDL_UpdateWindowSurface(window);
jim@4689
   156
}
jim@4689
   157
philipp@9273
   158
/* Returns a new SDL_Window if window is NULL or window if not. */
philipp@9273
   159
SDL_Window* initWindow(SDL_Window *window, int width,int height)
jim@4689
   160
{
slouken@5456
   161
  if (!window) {
slouken@5456
   162
    window = SDL_CreateWindow("Gesture Test",
slouken@5456
   163
                              SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
slouken@6790
   164
                              width, height, SDL_WINDOW_RESIZABLE);
slouken@5456
   165
  }
philipp@9273
   166
  return window;
jim@4689
   167
}
jim@4689
   168
icculus@9278
   169
void loop()
slouken@7191
   170
{
icculus@9278
   171
    SDL_Event event;
icculus@9278
   172
    SDL_RWops *stream;
aschiffler@7639
   173
icculus@9278
   174
    while(SDL_PollEvent(&event))
jim@4689
   175
    {
gabomdq@7678
   176
    /* Record _all_ events */
slouken@7191
   177
    events[eventWrite & (EVENT_BUF_SIZE-1)] = event;
slouken@7191
   178
    eventWrite++;
slouken@7191
   179
slouken@7191
   180
    switch (event.type)
jim@4689
   181
      {
slouken@7191
   182
      case SDL_QUIT:
slouken@7191
   183
        quitting = SDL_TRUE;
slouken@7191
   184
        break;
slouken@7191
   185
      case SDL_KEYDOWN:
slouken@7191
   186
        switch (event.key.keysym.sym)
slouken@7191
   187
          {
urkle@9235
   188
              case SDLK_i:
urkle@9235
   189
              {
urkle@9235
   190
                  int i;
urkle@9235
   191
                  for (i = 0; i < SDL_GetNumTouchDevices(); ++i) {
urkle@9235
   192
                      SDL_TouchID id = SDL_GetTouchDevice(i);
urkle@9235
   193
                      SDL_Log("Fingers Down on device %"SDL_PRIs64": %d", id, SDL_GetNumTouchFingers(id));
urkle@9235
   194
                  }
urkle@9235
   195
                  break;
urkle@9235
   196
              }
slouken@7191
   197
          case SDLK_SPACE:
slouken@7191
   198
        SDL_RecordGesture(-1);
slouken@7191
   199
        break;
slouken@7191
   200
          case SDLK_s:
philipp@7900
   201
        stream = SDL_RWFromFile("gestureSave", "w");
philipp@7900
   202
        SDL_Log("Wrote %i templates", SDL_SaveAllDollarTemplates(stream));
philipp@7900
   203
        SDL_RWclose(stream);
slouken@7191
   204
        break;
slouken@7191
   205
          case SDLK_l:
philipp@7900
   206
        stream = SDL_RWFromFile("gestureSave", "r");
philipp@7900
   207
        SDL_Log("Loaded: %i", SDL_LoadDollarTemplates(-1, stream));
philipp@7900
   208
        SDL_RWclose(stream);
slouken@7191
   209
        break;
slouken@7191
   210
          case SDLK_ESCAPE:
slouken@7191
   211
        quitting = SDL_TRUE;
slouken@7191
   212
        break;
slouken@7191
   213
        }
slouken@7191
   214
        break;
slouken@7191
   215
      case SDL_WINDOWEVENT:
slouken@5456
   216
            if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
philipp@9273
   217
          if (!(window = initWindow(window, event.window.data1, event.window.data2)) ||
philipp@9273
   218
              !(screen = SDL_GetWindowSurface(window)))
slouken@7191
   219
          {
slouken@7191
   220
        SDL_Quit();
icculus@9278
   221
        exit(1);
slouken@7191
   222
          }
slouken@5456
   223
            }
slouken@7191
   224
        break;
slouken@7191
   225
      case SDL_FINGERMOTION:
jim@4689
   226
#if VERBOSE
slouken@8917
   227
        SDL_Log("Finger: %"SDL_PRIs64",x: %f, y: %f",event.tfinger.fingerId,
slouken@7191
   228
               event.tfinger.x,event.tfinger.y);
jim@4689
   229
#endif
slouken@7191
   230
        break;
slouken@7191
   231
      case SDL_FINGERDOWN:
jim@4689
   232
#if VERBOSE
slouken@8917
   233
        SDL_Log("Finger: %"SDL_PRIs64" down - x: %f, y: %f",
slouken@7191
   234
           event.tfinger.fingerId,event.tfinger.x,event.tfinger.y);
jim@4689
   235
#endif
slouken@7191
   236
        break;
slouken@7191
   237
      case SDL_FINGERUP:
jim@4689
   238
#if VERBOSE
slouken@8917
   239
        SDL_Log("Finger: %"SDL_PRIs64" up - x: %f, y: %f",
slouken@7191
   240
               event.tfinger.fingerId,event.tfinger.x,event.tfinger.y);
jim@4689
   241
#endif
slouken@7191
   242
        break;
slouken@7191
   243
      case SDL_MULTIGESTURE:
slouken@7191
   244
#if VERBOSE
slouken@7191
   245
        SDL_Log("Multi Gesture: x = %f, y = %f, dAng = %f, dR = %f",
slouken@7191
   246
           event.mgesture.x,
slouken@7191
   247
           event.mgesture.y,
slouken@7191
   248
           event.mgesture.dTheta,
slouken@7191
   249
           event.mgesture.dDist);
slouken@7191
   250
        SDL_Log("MG: numDownTouch = %i",event.mgesture.numFingers);
jim@4689
   251
#endif
slouken@7191
   252
        knob.p.x = event.mgesture.x;
slouken@7191
   253
        knob.p.y = event.mgesture.y;
slouken@7191
   254
        knob.ang += event.mgesture.dTheta;
slouken@7191
   255
        knob.r += event.mgesture.dDist;
slouken@7191
   256
        break;
slouken@7191
   257
      case SDL_DOLLARGESTURE:
slouken@8917
   258
        SDL_Log("Gesture %"SDL_PRIs64" performed, error: %f",
slouken@7191
   259
           event.dgesture.gestureId,
slouken@7191
   260
           event.dgesture.error);
slouken@7191
   261
        break;
slouken@7191
   262
      case SDL_DOLLARRECORD:
slouken@8917
   263
        SDL_Log("Recorded gesture: %"SDL_PRIs64"",event.dgesture.gestureId);
slouken@7191
   264
        break;
slouken@7191
   265
      }
icculus@9278
   266
    }
icculus@9287
   267
    DrawScreen(screen, window);
philipp@9607
   268
philipp@9607
   269
#ifdef __EMSCRIPTEN__
philipp@9607
   270
    if (quitting) {
philipp@9607
   271
        emscripten_cancel_main_loop();
philipp@9607
   272
    }
philipp@9607
   273
#endif
icculus@9278
   274
}
icculus@9278
   275
icculus@9278
   276
int main(int argc, char* argv[])
icculus@9278
   277
{
philipp@9290
   278
  window = NULL;
philipp@9290
   279
  screen = NULL;
philipp@9290
   280
  quitting = SDL_FALSE;
icculus@9278
   281
icculus@9278
   282
  /* Enable standard application logging */
icculus@9278
   283
  SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
icculus@9278
   284
icculus@9278
   285
  /* gesture variables */
icculus@9278
   286
  knob.r = .1f;
icculus@9278
   287
  knob.ang = 0;
icculus@9278
   288
icculus@9278
   289
  if (SDL_Init(SDL_INIT_VIDEO) < 0 ) return 1;
icculus@9278
   290
philipp@9290
   291
  if (!(window = initWindow(window, WIDTH, HEIGHT)) ||
philipp@9290
   292
      !(screen = SDL_GetWindowSurface(window)))
icculus@9289
   293
  {
icculus@9289
   294
      SDL_Quit();
icculus@9289
   295
      return 1;
icculus@9289
   296
  }
icculus@9289
   297
icculus@9278
   298
#ifdef __EMSCRIPTEN__
icculus@9278
   299
    emscripten_set_main_loop(loop, 0, 1);
icculus@9278
   300
#else
icculus@9278
   301
    while(!quitting) {
icculus@9278
   302
        loop();
icculus@9278
   303
    }
icculus@9278
   304
#endif
icculus@9278
   305
slouken@7191
   306
  SDL_Quit();
jim@4689
   307
  return 0;
jim@4689
   308
}
jim@4689
   309