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