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