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