1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "../SDL_internal.h"
23
24/* General gesture handling code for SDL */
25
26#include "SDL_events.h"
27#include "SDL_endian.h"
28#include "SDL_events_c.h"
29#include "SDL_gesture_c.h"
30
31/*
32#include <stdio.h>
33*/
34
35/* TODO: Replace with malloc */
36
37#define MAXPATHSIZE 1024
38
39#define ENABLE_DOLLAR
40
41#define DOLLARNPOINTS 64
42
43#if defined(ENABLE_DOLLAR)
44# define DOLLARSIZE 256
45# define PHI 0.618033989
46#endif
47
48typedef struct {
49 float x,y;
50} SDL_FloatPoint;
51
52typedef struct {
53 float length;
54
55 int numPoints;
56 SDL_FloatPoint p[MAXPATHSIZE];
57} SDL_DollarPath;
58
59typedef struct {
60 SDL_FloatPoint path[DOLLARNPOINTS];
61 unsigned long hash;
62} SDL_DollarTemplate;
63
64typedef struct {
65 SDL_TouchID id;
66 SDL_FloatPoint centroid;
67 SDL_DollarPath dollarPath;
68 Uint16 numDownFingers;
69
70 int numDollarTemplates;
71 SDL_DollarTemplate *dollarTemplate;
72
73 SDL_bool recording;
74} SDL_GestureTouch;
75
76static SDL_GestureTouch *SDL_gestureTouch;
77static int SDL_numGestureTouches = 0;
78static SDL_bool recordAll;
79
80#if 0
81static void PrintPath(SDL_FloatPoint *path)
82{
83 int i;
84 printf("Path:");
85 for (i=0; i<DOLLARNPOINTS; i++) {
86 printf(" (%f,%f)",path[i].x,path[i].y);
87 }
88 printf("\n");
89}
90#endif
91
92int SDL_RecordGesture(SDL_TouchID touchId)
93{
94 int i;
95 if (touchId < 0) recordAll = SDL_TRUE;
96 for (i = 0; i < SDL_numGestureTouches; i++) {
97 if ((touchId < 0) || (SDL_gestureTouch[i].id == touchId)) {
98 SDL_gestureTouch[i].recording = SDL_TRUE;
99 if (touchId >= 0)
100 return 1;
101 }
102 }
103 return (touchId < 0);
104}
105
106void SDL_GestureQuit()
107{
108 SDL_free(SDL_gestureTouch);
109 SDL_gestureTouch = NULL;
110}
111
112static unsigned long SDL_HashDollar(SDL_FloatPoint* points)
113{
114 unsigned long hash = 5381;
115 int i;
116 for (i = 0; i < DOLLARNPOINTS; i++) {
117 hash = ((hash<<5) + hash) + (unsigned long)points[i].x;
118 hash = ((hash<<5) + hash) + (unsigned long)points[i].y;
119 }
120 return hash;
121}
122
123
124static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops *dst)
125{
126 if (dst == NULL) {
127 return 0;
128 }
129
130 /* No Longer storing the Hash, rehash on load */
131 /* if (SDL_RWops.write(dst, &(templ->hash), sizeof(templ->hash), 1) != 1) return 0; */
132
133#if SDL_BYTEORDER == SDL_LIL_ENDIAN
134 if (SDL_RWwrite(dst, templ->path,
135 sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) {
136 return 0;
137 }
138#else
139 {
140 SDL_DollarTemplate copy = *templ;
141 SDL_FloatPoint *p = copy.path;
142 int i;
143 for (i = 0; i < DOLLARNPOINTS; i++, p++) {
144 p->x = SDL_SwapFloatLE(p->x);
145 p->y = SDL_SwapFloatLE(p->y);
146 }
147
148 if (SDL_RWwrite(dst, copy.path,
149 sizeof(copy.path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) {
150 return 0;
151 }
152 }
153#endif
154
155 return 1;
156}
157
158
159int SDL_SaveAllDollarTemplates(SDL_RWops *dst)
160{
161 int i,j,rtrn = 0;
162 for (i = 0; i < SDL_numGestureTouches; i++) {
163 SDL_GestureTouch* touch = &SDL_gestureTouch[i];
164 for (j = 0; j < touch->numDollarTemplates; j++) {
165 rtrn += SaveTemplate(&touch->dollarTemplate[j], dst);
166 }
167 }
168 return rtrn;
169}
170
171int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *dst)
172{
173 int i,j;
174 for (i = 0; i < SDL_numGestureTouches; i++) {
175 SDL_GestureTouch* touch = &SDL_gestureTouch[i];
176 for (j = 0; j < touch->numDollarTemplates; j++) {
177 if (touch->dollarTemplate[j].hash == gestureId) {
178 return SaveTemplate(&touch->dollarTemplate[j], dst);
179 }
180 }
181 }
182 return SDL_SetError("Unknown gestureId");
183}
184
185/* path is an already sampled set of points
186Returns the index of the gesture on success, or -1 */
187static int SDL_AddDollarGesture_one(SDL_GestureTouch* inTouch, SDL_FloatPoint* path)
188{
189 SDL_DollarTemplate* dollarTemplate;
190 SDL_DollarTemplate *templ;
191 int index;
192
193 index = inTouch->numDollarTemplates;
194 dollarTemplate =
195 (SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
196 (index + 1) *
197 sizeof(SDL_DollarTemplate));
198 if (!dollarTemplate) {
199 return SDL_OutOfMemory();
200 }
201 inTouch->dollarTemplate = dollarTemplate;
202
203 templ = &inTouch->dollarTemplate[index];
204 SDL_memcpy(templ->path, path, DOLLARNPOINTS*sizeof(SDL_FloatPoint));
205 templ->hash = SDL_HashDollar(templ->path);
206 inTouch->numDollarTemplates++;
207
208 return index;
209}
210
211static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch, SDL_FloatPoint* path)
212{
213 int index = -1;
214 int i = 0;
215 if (inTouch == NULL) {
216 if (SDL_numGestureTouches == 0) return SDL_SetError("no gesture touch devices registered");
217 for (i = 0; i < SDL_numGestureTouches; i++) {
218 inTouch = &SDL_gestureTouch[i];
219 index = SDL_AddDollarGesture_one(inTouch, path);
220 if (index < 0)
221 return -1;
222 }
223 /* Use the index of the last one added. */
224 return index;
225 }
226 return SDL_AddDollarGesture_one(inTouch, path);
227}
228
229int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src)
230{
231 int i,loaded = 0;
232 SDL_GestureTouch *touch = NULL;
233 if (src == NULL) return 0;
234 if (touchId >= 0) {
235 for (i = 0; i < SDL_numGestureTouches; i++) {
236 if (SDL_gestureTouch[i].id == touchId) {
237 touch = &SDL_gestureTouch[i];
238 }
239 }
240 if (touch == NULL) {
241 return SDL_SetError("given touch id not found");
242 }
243 }
244
245 while (1) {
246 SDL_DollarTemplate templ;
247
248 if (SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < DOLLARNPOINTS) {
249 if (loaded == 0) {
250 return SDL_SetError("could not read any dollar gesture from rwops");
251 }
252 break;
253 }
254
255#if SDL_BYTEORDER != SDL_LIL_ENDIAN
256 for (i = 0; i < DOLLARNPOINTS; i++) {
257 SDL_FloatPoint *p = &templ.path[i];
258 p->x = SDL_SwapFloatLE(p->x);
259 p->y = SDL_SwapFloatLE(p->y);
260 }
261#endif
262
263 if (touchId >= 0) {
264 /* printf("Adding loaded gesture to 1 touch\n"); */
265 if (SDL_AddDollarGesture(touch, templ.path) >= 0)
266 loaded++;
267 }
268 else {
269 /* printf("Adding to: %i touches\n",SDL_numGestureTouches); */
270 for (i = 0; i < SDL_numGestureTouches; i++) {
271 touch = &SDL_gestureTouch[i];
272 /* printf("Adding loaded gesture to + touches\n"); */
273 /* TODO: What if this fails? */
274 SDL_AddDollarGesture(touch,templ.path);
275 }
276 loaded++;
277 }
278 }
279
280 return loaded;
281}
282
283
284#if defined(ENABLE_DOLLAR)
285static float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float ang)
286{
287 /* SDL_FloatPoint p[DOLLARNPOINTS]; */
288 float dist = 0;
289 SDL_FloatPoint p;
290 int i;
291 for (i = 0; i < DOLLARNPOINTS; i++) {
292 p.x = (float)(points[i].x * SDL_cos(ang) - points[i].y * SDL_sin(ang));
293 p.y = (float)(points[i].x * SDL_sin(ang) + points[i].y * SDL_cos(ang));
294 dist += (float)(SDL_sqrt((p.x-templ[i].x)*(p.x-templ[i].x)+
295 (p.y-templ[i].y)*(p.y-templ[i].y)));
296 }
297 return dist/DOLLARNPOINTS;
298
299}
300
301static float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ)
302{
303 /*------------BEGIN DOLLAR BLACKBOX------------------
304 -TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-
305 -"http://depts.washington.edu/aimgroup/proj/dollar/"
306 */
307 double ta = -M_PI/4;
308 double tb = M_PI/4;
309 double dt = M_PI/90;
310 float x1 = (float)(PHI*ta + (1-PHI)*tb);
311 float f1 = dollarDifference(points,templ,x1);
312 float x2 = (float)((1-PHI)*ta + PHI*tb);
313 float f2 = dollarDifference(points,templ,x2);
314 while (SDL_fabs(ta-tb) > dt) {
315 if (f1 < f2) {
316 tb = x2;
317 x2 = x1;
318 f2 = f1;
319 x1 = (float)(PHI*ta + (1-PHI)*tb);
320 f1 = dollarDifference(points,templ,x1);
321 }
322 else {
323 ta = x1;
324 x1 = x2;
325 f1 = f2;
326 x2 = (float)((1-PHI)*ta + PHI*tb);
327 f2 = dollarDifference(points,templ,x2);
328 }
329 }
330 /*
331 if (f1 <= f2)
332 printf("Min angle (x1): %f\n",x1);
333 else if (f1 > f2)
334 printf("Min angle (x2): %f\n",x2);
335 */
336 return SDL_min(f1,f2);
337}
338
339/* DollarPath contains raw points, plus (possibly) the calculated length */
340static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points, SDL_bool is_recording)
341{
342 int i;
343 float interval;
344 float dist;
345 int numPoints = 0;
346 SDL_FloatPoint centroid;
347 float xmin,xmax,ymin,ymax;
348 float ang;
349 float w,h;
350 float length = path->length;
351
352 /* Calculate length if it hasn't already been done */
353 if (length <= 0) {
354 for (i=1;i < path->numPoints; i++) {
355 float dx = path->p[i ].x - path->p[i-1].x;
356 float dy = path->p[i ].y - path->p[i-1].y;
357 length += (float)(SDL_sqrt(dx*dx+dy*dy));
358 }
359 }
360
361 /* Resample */
362 interval = length/(DOLLARNPOINTS - 1);
363 dist = interval;
364
365 centroid.x = 0;centroid.y = 0;
366
367 /* printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y); */
368 for (i = 1; i < path->numPoints; i++) {
369 float d = (float)(SDL_sqrt((path->p[i-1].x-path->p[i].x)*(path->p[i-1].x-path->p[i].x)+
370 (path->p[i-1].y-path->p[i].y)*(path->p[i-1].y-path->p[i].y)));
371 /* printf("d = %f dist = %f/%f\n",d,dist,interval); */
372 while (dist + d > interval) {
373 points[numPoints].x = path->p[i-1].x +
374 ((interval-dist)/d)*(path->p[i].x-path->p[i-1].x);
375 points[numPoints].y = path->p[i-1].y +
376 ((interval-dist)/d)*(path->p[i].y-path->p[i-1].y);
377 centroid.x += points[numPoints].x;
378 centroid.y += points[numPoints].y;
379 numPoints++;
380
381 dist -= interval;
382 }
383 dist += d;
384 }
385 if (numPoints < DOLLARNPOINTS-1) {
386 if (is_recording) {
387 SDL_SetError("ERROR: NumPoints = %i", numPoints);
388 }
389 return 0;
390 }
391 /* copy the last point */
392 points[DOLLARNPOINTS-1] = path->p[path->numPoints-1];
393 numPoints = DOLLARNPOINTS;
394
395 centroid.x /= numPoints;
396 centroid.y /= numPoints;
397
398 /* printf("Centroid (%f,%f)",centroid.x,centroid.y); */
399 /* Rotate Points so point 0 is left of centroid and solve for the bounding box */
400 xmin = centroid.x;
401 xmax = centroid.x;
402 ymin = centroid.y;
403 ymax = centroid.y;
404
405 ang = (float)(SDL_atan2(centroid.y - points[0].y,
406 centroid.x - points[0].x));
407
408 for (i = 0; i<numPoints; i++) {
409 float px = points[i].x;
410 float py = points[i].y;
411 points[i].x = (float)((px - centroid.x)*SDL_cos(ang) -
412 (py - centroid.y)*SDL_sin(ang) + centroid.x);
413 points[i].y = (float)((px - centroid.x)*SDL_sin(ang) +
414 (py - centroid.y)*SDL_cos(ang) + centroid.y);
415
416
417 if (points[i].x < xmin) xmin = points[i].x;
418 if (points[i].x > xmax) xmax = points[i].x;
419 if (points[i].y < ymin) ymin = points[i].y;
420 if (points[i].y > ymax) ymax = points[i].y;
421 }
422
423 /* Scale points to DOLLARSIZE, and translate to the origin */
424 w = xmax-xmin;
425 h = ymax-ymin;
426
427 for (i=0; i<numPoints; i++) {
428 points[i].x = (points[i].x - centroid.x)*DOLLARSIZE/w;
429 points[i].y = (points[i].y - centroid.y)*DOLLARSIZE/h;
430 }
431 return numPoints;
432}
433
434static float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_GestureTouch* touch)
435{
436 SDL_FloatPoint points[DOLLARNPOINTS];
437 int i;
438 float bestDiff = 10000;
439
440 SDL_memset(points, 0, sizeof(points));
441
442 dollarNormalize(path, points, SDL_FALSE);
443
444 /* PrintPath(points); */
445 *bestTempl = -1;
446 for (i = 0; i < touch->numDollarTemplates; i++) {
447 float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
448 if (diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
449 }
450 return bestDiff;
451}
452#endif
453
454int SDL_GestureAddTouch(SDL_TouchID touchId)
455{
456 SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch,
457 (SDL_numGestureTouches + 1) *
458 sizeof(SDL_GestureTouch));
459
460 if (!gestureTouch) {
461 return SDL_OutOfMemory();
462 }
463
464 SDL_gestureTouch = gestureTouch;
465
466 SDL_zero(SDL_gestureTouch[SDL_numGestureTouches]);
467 SDL_gestureTouch[SDL_numGestureTouches].id = touchId;
468 SDL_numGestureTouches++;
469 return 0;
470}
471
472int SDL_GestureDelTouch(SDL_TouchID touchId)
473{
474 int i;
475 for (i = 0; i < SDL_numGestureTouches; i++) {
476 if (SDL_gestureTouch[i].id == touchId) {
477 break;
478 }
479 }
480
481 if (i == SDL_numGestureTouches) {
482 /* not found */
483 return -1;
484 }
485
486 SDL_free(SDL_gestureTouch[i].dollarTemplate);
487 SDL_zero(SDL_gestureTouch[i]);
488
489 SDL_numGestureTouches--;
490 if (i != SDL_numGestureTouches) {
491 SDL_memcpy(&SDL_gestureTouch[i], &SDL_gestureTouch[SDL_numGestureTouches], sizeof(SDL_gestureTouch[i]));
492 }
493 return 0;
494}
495
496static SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id)
497{
498 int i;
499 for (i = 0; i < SDL_numGestureTouches; i++) {
500 /* printf("%i ?= %i\n",SDL_gestureTouch[i].id,id); */
501 if (SDL_gestureTouch[i].id == id)
502 return &SDL_gestureTouch[i];
503 }
504 return NULL;
505}
506
507static void SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist)
508{
509 if (SDL_GetEventState(SDL_MULTIGESTURE) == SDL_ENABLE) {
510 SDL_Event event;
511 event.mgesture.type = SDL_MULTIGESTURE;
512 event.mgesture.touchId = touch->id;
513 event.mgesture.x = touch->centroid.x;
514 event.mgesture.y = touch->centroid.y;
515 event.mgesture.dTheta = dTheta;
516 event.mgesture.dDist = dDist;
517 event.mgesture.numFingers = touch->numDownFingers;
518 SDL_PushEvent(&event);
519 }
520}
521
522#if defined(ENABLE_DOLLAR)
523static void SDL_SendGestureDollar(SDL_GestureTouch* touch,
524 SDL_GestureID gestureId,float error)
525{
526 if (SDL_GetEventState(SDL_DOLLARGESTURE) == SDL_ENABLE) {
527 SDL_Event event;
528 event.dgesture.type = SDL_DOLLARGESTURE;
529 event.dgesture.touchId = touch->id;
530 event.dgesture.x = touch->centroid.x;
531 event.dgesture.y = touch->centroid.y;
532 event.dgesture.gestureId = gestureId;
533 event.dgesture.error = error;
534 /* A finger came up to trigger this event. */
535 event.dgesture.numFingers = touch->numDownFingers + 1;
536 SDL_PushEvent(&event);
537 }
538}
539
540static void SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId)
541{
542 if (SDL_GetEventState(SDL_DOLLARRECORD) == SDL_ENABLE) {
543 SDL_Event event;
544 event.dgesture.type = SDL_DOLLARRECORD;
545 event.dgesture.touchId = touch->id;
546 event.dgesture.gestureId = gestureId;
547 SDL_PushEvent(&event);
548 }
549}
550#endif
551
552
553void SDL_GestureProcessEvent(SDL_Event* event)
554{
555 float x,y;
556#if defined(ENABLE_DOLLAR)
557 int index;
558 int i;
559 float pathDx, pathDy;
560#endif
561 SDL_FloatPoint lastP;
562 SDL_FloatPoint lastCentroid;
563 float lDist;
564 float Dist;
565 float dtheta;
566 float dDist;
567
568 if (event->type == SDL_FINGERMOTION ||
569 event->type == SDL_FINGERDOWN ||
570 event->type == SDL_FINGERUP) {
571 SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
572
573 /* Shouldn't be possible */
574 if (inTouch == NULL) return;
575
576 x = event->tfinger.x;
577 y = event->tfinger.y;
578
579 /* Finger Up */
580 if (event->type == SDL_FINGERUP) {
581#if defined(ENABLE_DOLLAR)
582 SDL_FloatPoint path[DOLLARNPOINTS];
583#endif
584
585 inTouch->numDownFingers--;
586
587#if defined(ENABLE_DOLLAR)
588 if (inTouch->recording) {
589 inTouch->recording = SDL_FALSE;
590 dollarNormalize(&inTouch->dollarPath, path, SDL_TRUE);
591 /* PrintPath(path); */
592 if (recordAll) {
593 index = SDL_AddDollarGesture(NULL,path);
594 for (i = 0; i < SDL_numGestureTouches; i++)
595 SDL_gestureTouch[i].recording = SDL_FALSE;
596 }
597 else {
598 index = SDL_AddDollarGesture(inTouch,path);
599 }
600
601 if (index >= 0) {
602 SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
603 }
604 else {
605 SDL_SendDollarRecord(inTouch,-1);
606 }
607 }
608 else {
609 int bestTempl;
610 float error;
611 error = dollarRecognize(&inTouch->dollarPath,
612 &bestTempl,inTouch);
613 if (bestTempl >= 0){
614 /* Send Event */
615 unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
616 SDL_SendGestureDollar(inTouch,gestureId,error);
617 /* printf ("%s\n",);("Dollar error: %f\n",error); */
618 }
619 }
620#endif
621 /* inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers]; */
622 if (inTouch->numDownFingers > 0) {
623 inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
624 x)/inTouch->numDownFingers;
625 inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
626 y)/inTouch->numDownFingers;
627 }
628 }
629 else if (event->type == SDL_FINGERMOTION) {
630 float dx = event->tfinger.dx;
631 float dy = event->tfinger.dy;
632#if defined(ENABLE_DOLLAR)
633 SDL_DollarPath* path = &inTouch->dollarPath;
634 if (path->numPoints < MAXPATHSIZE) {
635 path->p[path->numPoints].x = inTouch->centroid.x;
636 path->p[path->numPoints].y = inTouch->centroid.y;
637 pathDx =
638 (path->p[path->numPoints].x-path->p[path->numPoints-1].x);
639 pathDy =
640 (path->p[path->numPoints].y-path->p[path->numPoints-1].y);
641 path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
642 path->numPoints++;
643 }
644#endif
645 lastP.x = x - dx;
646 lastP.y = y - dy;
647 lastCentroid = inTouch->centroid;
648
649 inTouch->centroid.x += dx/inTouch->numDownFingers;
650 inTouch->centroid.y += dy/inTouch->numDownFingers;
651 /* printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y); */
652 if (inTouch->numDownFingers > 1) {
653 SDL_FloatPoint lv; /* Vector from centroid to last x,y position */
654 SDL_FloatPoint v; /* Vector from centroid to current x,y position */
655 /* lv = inTouch->gestureLast[j].cv; */
656 lv.x = lastP.x - lastCentroid.x;
657 lv.y = lastP.y - lastCentroid.y;
658 lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
659 /* printf("lDist = %f\n",lDist); */
660 v.x = x - inTouch->centroid.x;
661 v.y = y - inTouch->centroid.y;
662 /* inTouch->gestureLast[j].cv = v; */
663 Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
664 /* SDL_cos(dTheta) = (v . lv)/(|v| * |lv|) */
665
666 /* Normalize Vectors to simplify angle calculation */
667 lv.x/=lDist;
668 lv.y/=lDist;
669 v.x/=Dist;
670 v.y/=Dist;
671 dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
672
673 dDist = (Dist - lDist);
674 if (lDist == 0) {dDist = 0;dtheta = 0;} /* To avoid impossible values */
675
676 /* inTouch->gestureLast[j].dDist = dDist;
677 inTouch->gestureLast[j].dtheta = dtheta;
678
679 printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
680 gdtheta = gdtheta*.9 + dtheta*.1;
681 gdDist = gdDist*.9 + dDist*.1
682 knob.r += dDist/numDownFingers;
683 knob.ang += dtheta;
684 printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
685 printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist); */
686 SDL_SendGestureMulti(inTouch,dtheta,dDist);
687 }
688 else {
689 /* inTouch->gestureLast[j].dDist = 0;
690 inTouch->gestureLast[j].dtheta = 0;
691 inTouch->gestureLast[j].cv.x = 0;
692 inTouch->gestureLast[j].cv.y = 0; */
693 }
694 /* inTouch->gestureLast[j].f.p.x = x;
695 inTouch->gestureLast[j].f.p.y = y;
696 break;
697 pressure? */
698 }
699 else if (event->type == SDL_FINGERDOWN) {
700
701 inTouch->numDownFingers++;
702 inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+
703 x)/inTouch->numDownFingers;
704 inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
705 y)/inTouch->numDownFingers;
706 /* printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
707 inTouch->centroid.x,inTouch->centroid.y); */
708
709#if defined(ENABLE_DOLLAR)
710 inTouch->dollarPath.length = 0;
711 inTouch->dollarPath.p[0].x = x;
712 inTouch->dollarPath.p[0].y = y;
713 inTouch->dollarPath.numPoints = 1;
714#endif
715 }
716 }
717}
718
719/* vi: set ts=4 sw=4 expandtab: */
720