SDL  2.0
testgesture.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 1997-2018 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 
36 static int eventWrite;
37 
38 
39 static int colors[7] = {0xFF,0xFF00,0xFF0000,0xFFFF00,0x00FFFF,0xFF00FF,0xFFFFFF};
40 
44 
45 typedef struct {
46  float x,y;
47 } Point;
48 
49 typedef struct {
50  float ang,r;
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. */
160 {
161  if (!window) {
162  window = SDL_CreateWindow("Gesture Test",
164  width, height, SDL_WINDOW_RESIZABLE);
165  }
166  return window;
167 }
168 
169 void loop()
170 {
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) {
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;
281 
282  /* Enable standard application logging */
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