diff src/events/SDL_gesture.c @ 4688:494f71f57a80

Fixed bugs related to keyboard handling in gestureSDLTest. Fixed gesture code (dynamic memory allocation). Cleaned up gesture and test code.
author Jim Grandpre <jim.tla@gmail.com>
date Fri, 13 Aug 2010 23:08:32 -0400
parents 463cd74304b9
children f9ab8df6d45a
line wrap: on
line diff
--- a/src/events/SDL_gesture.c	Fri Aug 13 17:05:06 2010 -0700
+++ b/src/events/SDL_gesture.c	Fri Aug 13 23:08:32 2010 -0400
@@ -27,11 +27,12 @@
 #include "SDL_gesture_c.h"
 
 //TODO: Replace with malloc
-#define MAXFINGERS 5
-#define MAXTOUCHES 2
-#define MAXTEMPLATES 4
+
 #define MAXPATHSIZE 1024
 
+ 
+
+
 #define DOLLARNPOINTS 64
 #define DOLLARSIZE 256
 
@@ -42,55 +43,38 @@
 
 typedef struct {
   float x,y;
-} Point;
-
-
-typedef struct {
-  Point p;
-  float pressure;
-  SDL_FingerID id;
-} Finger;
-
+} SDL_FloatPoint;
 
 typedef struct {
   float length;
   
   int numPoints;
-  Point p[MAXPATHSIZE];
-} DollarPath;
+  SDL_FloatPoint p[MAXPATHSIZE];
+} SDL_DollarPath;
 
-/*
 typedef struct {
-  Finger f;
-  Point cv;
-  float dtheta,dDist;
-  DollarPath dollarPath;
-} TouchPoint;
-*/
-typedef struct {
-  Point path[DOLLARNPOINTS];
+  SDL_FloatPoint path[DOLLARNPOINTS];
   unsigned long hash;
-} DollarTemplate;
+} SDL_DollarTemplate;
 
 typedef struct {
   SDL_GestureID id;
-  Point res;
-  Point centroid;
-  //TouchPoint gestureLast[MAXFINGERS];
-  DollarPath dollarPath;
+  SDL_FloatPoint res;
+  SDL_FloatPoint centroid;
+  SDL_DollarPath dollarPath;
   Uint16 numDownFingers;
 
   int numDollarTemplates;
-  DollarTemplate dollarTemplate[MAXTEMPLATES];
+  SDL_DollarTemplate *dollarTemplate;
 
   SDL_bool recording;
-} GestureTouch;
+} SDL_GestureTouch;
 
-GestureTouch gestureTouch[MAXTOUCHES];
-int numGestureTouches = 0;
+SDL_GestureTouch *SDL_gestureTouch;
+int SDL_numGestureTouches = 0;
 SDL_bool recordAll;
 
-void SDL_PrintPath(Point *path) {
+void SDL_PrintPath(SDL_FloatPoint *path) {
   int i;
   printf("Path:");
   for(i=0;i<DOLLARNPOINTS;i++) {
@@ -102,9 +86,9 @@
 int SDL_RecordGesture(SDL_TouchID touchId) {
   int i;
   if(touchId < 0) recordAll = SDL_TRUE;
-  for(i = 0;i < numGestureTouches; i++) {
-    if((touchId < 0) || (gestureTouch[i].id == touchId)) {
-      gestureTouch[i].recording = SDL_TRUE;
+  for(i = 0;i < SDL_numGestureTouches; i++) {
+    if((touchId < 0) || (SDL_gestureTouch[i].id == touchId)) {
+      SDL_gestureTouch[i].recording = SDL_TRUE;
       if(touchId >= 0)
 	return 1;
     }      
@@ -112,7 +96,7 @@
   return (touchId < 0);
 }
 
-unsigned long SDL_HashDollar(Point* points) {
+unsigned long SDL_HashDollar(SDL_FloatPoint* points) {
   unsigned long hash = 5381;
   int i;
   for(i = 0;i < DOLLARNPOINTS; i++) { 
@@ -123,14 +107,14 @@
 }
 
 
-static int SaveTemplate(DollarTemplate *templ, SDL_RWops * src) {
+static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops * src) {
   if(src == NULL) return 0;
 
   int i;
   
   //No Longer storing the Hash, rehash on load
   //if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
-
+  
   if(SDL_RWwrite(src,templ->path,
 		 sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) 
     return 0;
@@ -141,8 +125,8 @@
 
 int SDL_SaveAllDollarTemplates(SDL_RWops *src) {  
   int i,j,rtrn = 0;
-  for(i = 0; i < numGestureTouches; i++) {
-    GestureTouch* touch = &gestureTouch[i];
+  for(i = 0; i < SDL_numGestureTouches; i++) {
+    SDL_GestureTouch* touch = &SDL_gestureTouch[i];
     for(j = 0;j < touch->numDollarTemplates; j++) {
 	rtrn += SaveTemplate(&touch->dollarTemplate[i],src);
     }
@@ -152,8 +136,8 @@
 
 int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *src) {
   int i,j;
-  for(i = 0; i < numGestureTouches; i++) {
-    GestureTouch* touch = &gestureTouch[i];
+  for(i = 0; i < SDL_numGestureTouches; i++) {
+    SDL_GestureTouch* touch = &SDL_gestureTouch[i];
     for(j = 0;j < touch->numDollarTemplates; j++) {
       if(touch->dollarTemplate[i].hash == gestureId) {
 	return SaveTemplate(&touch->dollarTemplate[i],src);
@@ -166,25 +150,46 @@
 
 //path is an already sampled set of points
 //Returns the index of the gesture on success, or -1
-static int SDL_AddDollarGesture(GestureTouch* inTouch,Point* path) {
+static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch,SDL_FloatPoint* path) {
   if(inTouch == NULL) {
-    if(numGestureTouches == 0) return -1;
+    if(SDL_numGestureTouches == 0) return -1;
     int i = 0;
-    for(i = 0;i < numGestureTouches; i++) {
-      inTouch = &gestureTouch[i];
-      if(inTouch->numDollarTemplates < MAXTEMPLATES) {
-	DollarTemplate *templ = 
-	  &inTouch->dollarTemplate[inTouch->numDollarTemplates];
-	memcpy(templ->path,path,DOLLARNPOINTS*sizeof(Point));
-	templ->hash = SDL_HashDollar(templ->path);
-	inTouch->numDollarTemplates++;
+    for(i = 0;i < SDL_numGestureTouches; i++) {
+      inTouch = &SDL_gestureTouch[i];
+
+      SDL_DollarTemplate* dollarTemplate = 
+	SDL_realloc(inTouch->dollarTemplate,
+		    (inTouch->numDollarTemplates + 1) * 
+		    sizeof(SDL_DollarTemplate));
+      if(!dollarTemplate) {
+	SDL_OutOfMemory();
+	return -1;
       }
+	
+      inTouch->dollarTemplate = dollarTemplate;
+
+      SDL_DollarTemplate *templ = 
+	&inTouch->dollarTemplate[inTouch->numDollarTemplates];
+      memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
+      templ->hash = SDL_HashDollar(templ->path);
+      inTouch->numDollarTemplates++;    
     }
     return inTouch->numDollarTemplates - 1;
-  }else if(inTouch->numDollarTemplates < MAXTEMPLATES) {
-    DollarTemplate *templ = 
+  } else {
+    SDL_DollarTemplate* dollarTemplate = 
+      SDL_realloc(inTouch->dollarTemplate,
+		  (inTouch->numDollarTemplates + 1) * 
+		  sizeof(SDL_DollarTemplate));
+    if(!dollarTemplate) {
+      SDL_OutOfMemory();
+      return -1;
+    }
+    
+    inTouch->dollarTemplate = dollarTemplate;
+
+    SDL_DollarTemplate *templ = 
       &inTouch->dollarTemplate[inTouch->numDollarTemplates];
-    memcpy(templ->path,path,DOLLARNPOINTS*sizeof(Point));
+    memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
     templ->hash = SDL_HashDollar(templ->path);
     inTouch->numDollarTemplates++;
     return inTouch->numDollarTemplates - 1;
@@ -195,36 +200,28 @@
 int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src) {
   if(src == NULL) return 0;
   int i,loaded = 0;
-  GestureTouch *touch = NULL;
+  SDL_GestureTouch *touch = NULL;
   if(touchId >= 0) {
-    for(i = 0;i < numGestureTouches; i++)
-      if(gestureTouch[i].id == touchId)
-	touch = &gestureTouch[i];
+    for(i = 0;i < SDL_numGestureTouches; i++)
+      if(SDL_gestureTouch[i].id == touchId)
+	touch = &SDL_gestureTouch[i];
     if(touch == NULL) return -1;
   }
 
   while(1) {
-    DollarTemplate templ;
-    //fscanf(fp,"%lu ",&templ.hash);
-    /*
-    for(i = 0;i < DOLLARNPOINTS; i++) {		
-      int x,y;
-      if(fscanf(fp,"%i %i ",&x,&y) != 2) break;
-      templ.path[i].x = x;
-      templ.path[i].y = y;
-    }
-    fscanf(fp,"\n");
-    */
-    if(SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < DOLLARNPOINTS) break;
+    SDL_DollarTemplate templ;
+
+    if(SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < 
+       DOLLARNPOINTS) break;
 
     if(touchId >= 0) {
       printf("Adding loaded gesture to 1 touch\n");
       if(SDL_AddDollarGesture(touch,templ.path)) loaded++;
     }
     else {
-      printf("Adding to: %i touches\n",numGestureTouches);
-      for(i = 0;i < numGestureTouches; i++) {
-	touch = &gestureTouch[i];
+      printf("Adding to: %i touches\n",SDL_numGestureTouches);
+      for(i = 0;i < SDL_numGestureTouches; i++) {
+	touch = &SDL_gestureTouch[i];
 	printf("Adding loaded gesture to + touches\n");
 	//TODO: What if this fails?
 	SDL_AddDollarGesture(touch,templ.path);	
@@ -237,10 +234,10 @@
 }
 
 
-float dollarDifference(Point* points,Point* templ,float ang) {
-  //  Point p[DOLLARNPOINTS];
+float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float ang) {
+  //  SDL_FloatPoint p[DOLLARNPOINTS];
   float dist = 0;
-  Point p;
+  SDL_FloatPoint p;
   int i;
   for(i = 0; i < DOLLARNPOINTS; i++) {
     p.x = points[i].x * cos(ang) - points[i].y * sin(ang);
@@ -252,7 +249,7 @@
   
 }
 
-float bestDollarDifference(Point* points,Point* templ) {
+float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ) {
   //------------BEGIN DOLLAR BLACKBOX----------------//
   //-TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-//
   //-"http://depts.washington.edu/aimgroup/proj/dollar/"-//
@@ -289,10 +286,9 @@
 }
 
 //DollarPath contains raw points, plus (possibly) the calculated length
-int dollarNormalize(DollarPath path,Point *points) {
+int dollarNormalize(SDL_DollarPath path,SDL_FloatPoint *points) {
   int i;
   //Calculate length if it hasn't already been done
-  printf("length: %f\n",path.length);
   if(path.length <= 0) {
     for(i=1;i<path.numPoints;i++) {
       float dx = path.p[i  ].x - 
@@ -302,14 +298,13 @@
       path.length += sqrt(dx*dx+dy*dy);
     }
   }
-  printf("New length: %f\n",path.length);
 
   //Resample
   float interval = path.length/(DOLLARNPOINTS - 1);
   float dist = interval;
 
   int numPoints = 0;
-  Point centroid; 
+  SDL_FloatPoint centroid; 
   centroid.x = 0;centroid.y = 0;
   
   //printf("(%f,%f)\n",path.p[path.numPoints-1].x,path.p[path.numPoints-1].y);
@@ -378,9 +373,9 @@
   return numPoints;
 }
 
-float dollarRecognize(DollarPath path,int *bestTempl,GestureTouch* touch) {
+float dollarRecognize(SDL_DollarPath path,int *bestTempl,SDL_GestureTouch* touch) {
 	
-	Point points[DOLLARNPOINTS];
+	SDL_FloatPoint points[DOLLARNPOINTS];
 	int numPoints = dollarNormalize(path,points);
 	//SDL_PrintPath(points);
 	int i;
@@ -394,34 +389,56 @@
 	return bestDiff;
 }
 
-int SDL_GestureAddTouch(SDL_Touch* touch) { 
-  if(numGestureTouches >= MAXTOUCHES) return -1;
-  
-  gestureTouch[numGestureTouches].res.x = touch->xres;
-  gestureTouch[numGestureTouches].res.y = touch->yres;
-  gestureTouch[numGestureTouches].numDownFingers = 0;
+int SDL_GestureAddTouch(SDL_Touch* touch) {  
+  SDL_GestureTouch *gestureTouch = SDL_realloc(SDL_gestureTouch,
+					       (SDL_numGestureTouches + 1) *
+					       sizeof(SDL_GestureTouch));
+
+  if(!gestureTouch) {
+    SDL_OutOfMemory();
+    return -1;
+  }
+
+  SDL_gestureTouch = gestureTouch;
 
-  gestureTouch[numGestureTouches].res.x = touch->xres;
-  gestureTouch[numGestureTouches].id = touch->id;
+  SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
+  SDL_gestureTouch[SDL_numGestureTouches].res.y = touch->yres;
+  SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0;
 
-  gestureTouch[numGestureTouches].numDollarTemplates = 0;
+  SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
+  SDL_gestureTouch[SDL_numGestureTouches].id = touch->id;
 
-  gestureTouch[numGestureTouches].recording = SDL_FALSE;
+  SDL_gestureTouch[SDL_numGestureTouches].numDollarTemplates = 0;
 
-  numGestureTouches++;
+  SDL_gestureTouch[SDL_numGestureTouches].recording = SDL_FALSE;
+
+  SDL_numGestureTouches++;
   return 0;
 }
 
-GestureTouch * SDL_GetGestureTouch(SDL_TouchID id) {
+int SDL_GestureRemoveTouch(SDL_TouchID id) {
   int i;
-  for(i = 0;i < numGestureTouches; i++) {
-    //printf("%i ?= %i\n",gestureTouch[i].id,id);
-    if(gestureTouch[i].id == id) return &gestureTouch[i];
+  for(i = 0;i < SDL_numGestureTouches; i++) {
+    if(SDL_gestureTouch[i].id == id) {
+      SDL_numGestureTouches--;
+      SDL_gestureTouch[i] = SDL_gestureTouch[SDL_numGestureTouches];
+      return 1;
+    }
+  }
+  return -1;
+}
+
+
+SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id) {
+  int i;
+  for(i = 0;i < SDL_numGestureTouches; i++) {
+    //printf("%i ?= %i\n",SDL_gestureTouch[i].id,id);
+    if(SDL_gestureTouch[i].id == id) return &SDL_gestureTouch[i];
   }
   return NULL;
 }
 
-int SDL_SendGestureMulti(GestureTouch* touch,float dTheta,float dDist) {
+int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist) {
   SDL_Event event;
   event.mgesture.type = SDL_MULTIGESTURE;
   event.mgesture.touchId = touch->id;
@@ -433,7 +450,7 @@
   return SDL_PushEvent(&event) > 0;
 }
 
-int SDL_SendGestureDollar(GestureTouch* touch,
+int SDL_SendGestureDollar(SDL_GestureTouch* touch,
 			  SDL_GestureID gestureId,float error) {
   SDL_Event event;
   event.dgesture.type = SDL_DOLLARGESTURE;
@@ -449,7 +466,7 @@
 }
 
 
-int SDL_SendDollarRecord(GestureTouch* touch,SDL_GestureID gestureId) {
+int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId) {
   SDL_Event event;
   event.dgesture.type = SDL_DOLLARRECORD;
   event.dgesture.touchId = touch->id;
@@ -464,7 +481,7 @@
   if(event->type == SDL_FINGERMOTION || 
      event->type == SDL_FINGERDOWN ||
      event->type == SDL_FINGERUP) {
-    GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
+    SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
     
     //Shouldn't be possible
     if(inTouch == NULL) return;
@@ -485,15 +502,15 @@
 #ifdef ENABLE_DOLLAR
       if(inTouch->recording) {
 	inTouch->recording = SDL_FALSE;
-	Point path[DOLLARNPOINTS];
+	SDL_FloatPoint path[DOLLARNPOINTS];
 	dollarNormalize(inTouch->dollarPath,path);
 	//SDL_PrintPath(path);
 	int index;
 	if(recordAll) {
 	  index = SDL_AddDollarGesture(NULL,path);
 	  int i;
-	  for(i = 0;i < numGestureTouches; i++)
-	    gestureTouch[i].recording = SDL_FALSE;
+	  for(i = 0;i < SDL_numGestureTouches; i++)
+	    SDL_gestureTouch[i].recording = SDL_FALSE;
 	}
 	else {
 	  index = SDL_AddDollarGesture(inTouch,path);
@@ -532,7 +549,7 @@
       float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y;
       //printf("dx,dy: (%f,%f)\n",dx,dy); 
 #ifdef ENABLE_DOLLAR
-      DollarPath* path = &inTouch->dollarPath;
+      SDL_DollarPath* path = &inTouch->dollarPath;
       if(path->numPoints < MAXPATHSIZE) {
 	path->p[path->numPoints].x = inTouch->centroid.x;
 	path->p[path->numPoints].y = inTouch->centroid.y;
@@ -544,18 +561,18 @@
 	path->numPoints++;
       }
 #endif
-      Point lastP;
+      SDL_FloatPoint lastP;
       lastP.x = x - dx;
       lastP.y = y - dy;
-      Point lastCentroid;
+      SDL_FloatPoint lastCentroid;
       lastCentroid = inTouch->centroid;
       
       inTouch->centroid.x += dx/inTouch->numDownFingers;
       inTouch->centroid.y += dy/inTouch->numDownFingers;
       //printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
       if(inTouch->numDownFingers > 1) {
-	Point lv; //Vector from centroid to last x,y position
-	Point v; //Vector from centroid to current x,y position
+	SDL_FloatPoint lv; //Vector from centroid to last x,y position
+	SDL_FloatPoint v; //Vector from centroid to current x,y position
 	//lv = inTouch->gestureLast[j].cv;
 	lv.x = lastP.x - lastCentroid.x;
 	lv.y = lastP.y - lastCentroid.y;
@@ -608,15 +625,9 @@
 			     x)/inTouch->numDownFingers;
       inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
 			     y)/inTouch->numDownFingers;
-      printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
-	     inTouch->centroid.x,inTouch->centroid.y);
-      /*
-	inTouch->gestureLast[j].f.id = event->tfinger.fingerId;
-	inTouch->gestureLast[j].f.p.x  = x;
-	inTouch->gestureLast[j].f.p.y  = y;	
-	inTouch->gestureLast[j].cv.x = 0;
-	inTouch->gestureLast[j].cv.y = 0;
-      */
+      //printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
+      //     inTouch->centroid.x,inTouch->centroid.y);
+
 #ifdef ENABLE_DOLLAR
       inTouch->dollarPath.length = 0;
       inTouch->dollarPath.p[0].x = x;