src/events/SDL_gesture.c
changeset 4683 15dfe42edbfd
parent 4682 4ba1048a324c
child 4684 f47c2640c667
equal deleted inserted replaced
4682:4ba1048a324c 4683:15dfe42edbfd
    73 typedef struct {
    73 typedef struct {
    74   SDL_GestureID id;
    74   SDL_GestureID id;
    75   Point res;
    75   Point res;
    76   Point centroid;
    76   Point centroid;
    77   TouchPoint gestureLast[MAXFINGERS];
    77   TouchPoint gestureLast[MAXFINGERS];
    78   int numDownFingers;
    78   Uint16 numDownFingers;
    79 
    79 
    80   int numDollarTemplates;
    80   int numDollarTemplates;
    81   DollarTemplate dollarTemplate[MAXTEMPLATES];
    81   DollarTemplate dollarTemplate[MAXTEMPLATES];
    82 
    82 
    83   SDL_bool recording;
    83   SDL_bool recording;
   404   event.mgesture.touchId = touch->id;
   404   event.mgesture.touchId = touch->id;
   405   event.mgesture.x = touch->centroid.x;
   405   event.mgesture.x = touch->centroid.x;
   406   event.mgesture.y = touch->centroid.y;
   406   event.mgesture.y = touch->centroid.y;
   407   event.mgesture.dTheta = dTheta;
   407   event.mgesture.dTheta = dTheta;
   408   event.mgesture.dDist = dDist;  
   408   event.mgesture.dDist = dDist;  
       
   409   event.mgesture.numFingers = touch->numDownFingers;
   409   return SDL_PushEvent(&event) > 0;
   410   return SDL_PushEvent(&event) > 0;
   410 }
   411 }
   411 
   412 
   412 int SDL_SendGestureDollar(GestureTouch* touch,
   413 int SDL_SendGestureDollar(GestureTouch* touch,
   413 			  SDL_GestureID gestureId,float error) {
   414 			  SDL_GestureID gestureId,float error) {
   439 {
   440 {
   440   if(event->type == SDL_FINGERMOTION || 
   441   if(event->type == SDL_FINGERMOTION || 
   441      event->type == SDL_FINGERDOWN ||
   442      event->type == SDL_FINGERDOWN ||
   442      event->type == SDL_FINGERUP) {
   443      event->type == SDL_FINGERUP) {
   443     GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
   444     GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
   444 
   445     
   445     //Shouldn't be possible
   446     //Shouldn't be possible
   446     if(inTouch == NULL) return;
   447     if(inTouch == NULL) return;
   447     
   448     
       
   449     //printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x,
       
   450     //	   (int)event->tfinger.y,
       
   451     //   (int)inTouch->res.x,(int)inTouch->res.y);
       
   452 
   448     
   453     
   449     float x = ((float)event->tfinger.x)/inTouch->res.x;
   454     float x = ((float)event->tfinger.x)/(float)inTouch->res.x;
   450     float y = ((float)event->tfinger.y)/inTouch->res.y;
   455     float y = ((float)event->tfinger.y)/(float)inTouch->res.y;   
   451     int j,empty = -1;
   456 
   452     
   457 
   453     for(j = 0;j<inTouch->numDownFingers;j++) {
   458     //Finger Up
   454       if(inTouch->gestureLast[j].f.id != event->tfinger.fingerId) continue;
   459     if(event->type == SDL_FINGERUP) {
   455       //Finger Up
   460       inTouch->numDownFingers--;
   456       if(event->type == SDL_FINGERUP) {
   461       
   457 	inTouch->numDownFingers--;
   462 #ifdef ENABLE_DOLLAR
   458 
   463       if(inTouch->recording) {
   459 	if(inTouch->recording) {
   464 	inTouch->recording = SDL_FALSE;
   460 	  inTouch->recording = SDL_FALSE;
   465 	Point path[DOLLARNPOINTS];
   461 	  Point path[DOLLARNPOINTS];
   466 	dollarNormalize(inTouch->gestureLast[j].dollarPath,path);
   462 	  dollarNormalize(inTouch->gestureLast[j].dollarPath,path);
   467 	int index;
   463 	  int index;
   468 	if(recordAll) {
   464 	  if(recordAll) {
   469 	  index = SDL_AddDollarGesture(NULL,path);
   465 	    index = SDL_AddDollarGesture(NULL,path);
   470 	  int i;
   466 	    int i;
   471 	  for(i = 0;i < numGestureTouches; i++)
   467 	    for(i = 0;i < numGestureTouches; i++)
   472 	    gestureTouch[i].recording = SDL_FALSE;
   468 	      gestureTouch[i].recording = SDL_FALSE;
       
   469 	  }
       
   470 	  else {
       
   471 	    index = SDL_AddDollarGesture(inTouch,path);
       
   472 	  }
       
   473 	  
       
   474 	  if(index >= 0) {
       
   475 	    SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
       
   476 	  }
       
   477 	  else {
       
   478 	    SDL_SendDollarRecord(inTouch,-1);
       
   479 	  }
       
   480 	}
       
   481 	else {	
       
   482 	  int bestTempl;
       
   483 	  float error;
       
   484 	  error = dollarRecognize(inTouch->gestureLast[j].dollarPath,
       
   485 				  &bestTempl,inTouch);
       
   486 	  if(bestTempl >= 0){
       
   487 	    //Send Event
       
   488 	    unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
       
   489 	    SDL_SendGestureDollar(inTouch,gestureId,error);
       
   490 	    printf("Dollar error: %f\n",error);
       
   491 	  }
       
   492 	} 
       
   493 	inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
       
   494 	j = -1;
       
   495 	break;
       
   496       }
       
   497       else if(event->type == SDL_FINGERMOTION) {
       
   498 	float dx = x - inTouch->gestureLast[j].f.p.x;
       
   499 	float dy = y - inTouch->gestureLast[j].f.p.y;
       
   500 	DollarPath* path = &inTouch->gestureLast[j].dollarPath;
       
   501 	if(path->numPoints < MAXPATHSIZE) {
       
   502 	  path->p[path->numPoints].x = x;
       
   503 	  path->p[path->numPoints].y = y;
       
   504 	  path->length += sqrt(dx*dx + dy*dy);
       
   505 	  path->numPoints++;
       
   506 	}
       
   507 
       
   508 
       
   509 	inTouch->centroid.x += dx/inTouch->numDownFingers;
       
   510 	inTouch->centroid.y += dy/inTouch->numDownFingers;    
       
   511 	if(inTouch->numDownFingers > 1) {
       
   512 	  Point lv; //Vector from centroid to last x,y position
       
   513 	  Point v; //Vector from centroid to current x,y position
       
   514 	  lv = inTouch->gestureLast[j].cv;
       
   515 	  float lDist = sqrt(lv.x*lv.x + lv.y*lv.y);
       
   516 	  //printf("lDist = %f\n",lDist);
       
   517 	  v.x = x - inTouch->centroid.x;
       
   518 	  v.y = y - inTouch->centroid.y;
       
   519 	  inTouch->gestureLast[j].cv = v;
       
   520 	  float Dist = sqrt(v.x*v.x+v.y*v.y);
       
   521 	  // cos(dTheta) = (v . lv)/(|v| * |lv|)
       
   522 	  
       
   523 	  //Normalize Vectors to simplify angle calculation
       
   524 	  lv.x/=lDist;
       
   525 	  lv.y/=lDist;
       
   526 	  v.x/=Dist;
       
   527 	  v.y/=Dist;
       
   528 	  float dtheta = atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
       
   529 	  
       
   530 	  float dDist = (Dist - lDist);
       
   531 	  if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
       
   532 	  inTouch->gestureLast[j].dDist = dDist;
       
   533 	  inTouch->gestureLast[j].dtheta = dtheta;
       
   534 	  
       
   535 	  //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
       
   536 	  //gdtheta = gdtheta*.9 + dtheta*.1;
       
   537 	  //gdDist  =  gdDist*.9 +  dDist*.1
       
   538 	  //knob.r += dDist/numDownFingers;
       
   539 	  //knob.ang += dtheta;
       
   540 	  //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
       
   541 	  //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
       
   542 	  SDL_SendGestureMulti(inTouch,dtheta,dDist);
       
   543 	}
   473 	}
   544 	else {
   474 	else {
   545 	  inTouch->gestureLast[j].dDist = 0;
   475 	  index = SDL_AddDollarGesture(inTouch,path);
   546 	  inTouch->gestureLast[j].dtheta = 0;
       
   547 	  inTouch->gestureLast[j].cv.x = 0;
       
   548 	  inTouch->gestureLast[j].cv.y = 0;
       
   549 	}
   476 	}
   550 	inTouch->gestureLast[j].f.p.x = x;
   477 	
   551 	inTouch->gestureLast[j].f.p.y = y;
   478 	if(index >= 0) {
   552 	break;
   479 	  SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
   553 	//pressure?
   480 	}
   554       }      
   481 	else {
       
   482 	  SDL_SendDollarRecord(inTouch,-1);
       
   483 	}
       
   484       }
       
   485       else {	
       
   486 	int bestTempl;
       
   487 	float error;
       
   488 	error = dollarRecognize(inTouch->gestureLast[j].dollarPath,
       
   489 				&bestTempl,inTouch);
       
   490 	if(bestTempl >= 0){
       
   491 	  //Send Event
       
   492 	  unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
       
   493 	  SDL_SendGestureDollar(inTouch,gestureId,error);
       
   494 	    printf ("%s\n",);("Dollar error: %f\n",error);
       
   495 	}
       
   496       }
       
   497 #endif 
       
   498       //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
       
   499       if(inTouch->numDownFingers > 0) {
       
   500 	inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
       
   501 			       x)/inTouch->numDownFingers;
       
   502 	inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
       
   503 			       y)/inTouch->numDownFingers;
       
   504       }
       
   505     }
       
   506     else if(event->type == SDL_FINGERMOTION) {
       
   507       float dx = ((float)event->tfinger.dx)/(float)inTouch->res.x;
       
   508       float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y;
       
   509       //printf("dx,dy: (%f,%f)\n",dx,dy); 
       
   510 #ifdef ENABLE_DOLLAR
       
   511       DollarPath* path = &inTouch->gestureLast[j].dollarPath;
       
   512       if(path->numPoints < MAXPATHSIZE) {
       
   513 	path->p[path->numPoints].x = x;
       
   514 	path->p[path->numPoints].y = y;
       
   515 	path->length += sqrt(dx*dx + dy*dy);
       
   516 	path->numPoints++;
       
   517       }
       
   518 #endif
       
   519       Point lastP;
       
   520       lastP.x = x - dx;
       
   521       lastP.y = y - dy;
       
   522       Point lastCentroid;
       
   523       lastCentroid = inTouch->centroid;
       
   524       
       
   525       inTouch->centroid.x += dx/inTouch->numDownFingers;
       
   526       inTouch->centroid.y += dy/inTouch->numDownFingers;    
       
   527       if(inTouch->numDownFingers > 1) {
       
   528 	Point lv; //Vector from centroid to last x,y position
       
   529 	Point v; //Vector from centroid to current x,y position
       
   530 	//lv = inTouch->gestureLast[j].cv;
       
   531 	lv.x = lastP.x - lastCentroid.x;
       
   532 	lv.y = lastP.y - lastCentroid.y;
       
   533 	float lDist = sqrt(lv.x*lv.x + lv.y*lv.y);
       
   534 	//printf("lDist = %f\n",lDist);
       
   535 	v.x = x - inTouch->centroid.x;
       
   536 	v.y = y - inTouch->centroid.y;
       
   537 	//inTouch->gestureLast[j].cv = v;
       
   538 	float Dist = sqrt(v.x*v.x+v.y*v.y);
       
   539 	// cos(dTheta) = (v . lv)/(|v| * |lv|)
       
   540 	
       
   541 	//Normalize Vectors to simplify angle calculation
       
   542 	lv.x/=lDist;
       
   543 	lv.y/=lDist;
       
   544 	v.x/=Dist;
       
   545 	v.y/=Dist;
       
   546 	float dtheta = atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
       
   547 	
       
   548 	float dDist = (Dist - lDist);
       
   549 	if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
       
   550 	
       
   551 	//inTouch->gestureLast[j].dDist = dDist;
       
   552 	//inTouch->gestureLast[j].dtheta = dtheta;
       
   553 	
       
   554 	//printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
       
   555 	//gdtheta = gdtheta*.9 + dtheta*.1;
       
   556 	//gdDist  =  gdDist*.9 +  dDist*.1
       
   557 	//knob.r += dDist/numDownFingers;
       
   558 	//knob.ang += dtheta;
       
   559 	//printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
       
   560 	//printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
       
   561 	SDL_SendGestureMulti(inTouch,dtheta,dDist);
       
   562       }
       
   563       else {
       
   564 	//inTouch->gestureLast[j].dDist = 0;
       
   565 	//inTouch->gestureLast[j].dtheta = 0;
       
   566 	//inTouch->gestureLast[j].cv.x = 0;
       
   567 	//inTouch->gestureLast[j].cv.y = 0;
       
   568       }
       
   569       //inTouch->gestureLast[j].f.p.x = x;
       
   570       //inTouch->gestureLast[j].f.p.y = y;
       
   571       //break;
       
   572       //pressure?
   555     }
   573     }
   556     
   574     
   557     if(j == inTouch->numDownFingers) {
   575     if(event->type == SDL_FINGERDOWN) {
   558       //printf("Finger Down!!!\n");
   576 
   559       inTouch->numDownFingers++;
   577       inTouch->numDownFingers++;
   560       inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+ 
   578       inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+ 
   561 			     x)/inTouch->numDownFingers;
   579 			     x)/inTouch->numDownFingers;
   562       inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
   580       inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
   563 			     y)/inTouch->numDownFingers;
   581 			     y)/inTouch->numDownFingers;
   564       
   582       printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
   565       inTouch->gestureLast[j].f.id = event->tfinger.fingerId;
   583 	     inTouch->centroid.x,inTouch->centroid.y);
   566       inTouch->gestureLast[j].f.p.x  = x;
   584       /*
   567       inTouch->gestureLast[j].f.p.y  = y;	
   585 	inTouch->gestureLast[j].f.id = event->tfinger.fingerId;
   568       inTouch->gestureLast[j].cv.x = 0;
   586 	inTouch->gestureLast[j].f.p.x  = x;
   569       inTouch->gestureLast[j].cv.y = 0;
   587 	inTouch->gestureLast[j].f.p.y  = y;	
   570 
   588 	inTouch->gestureLast[j].cv.x = 0;
       
   589 	inTouch->gestureLast[j].cv.y = 0;
       
   590       */
       
   591 #ifdef ENABlE_DOLLAR
   571       inTouch->gestureLast[j].dollarPath.length = 0;
   592       inTouch->gestureLast[j].dollarPath.length = 0;
   572       inTouch->gestureLast[j].dollarPath.p[0].x = x;
   593       inTouch->gestureLast[j].dollarPath.p[0].x = x;
   573       inTouch->gestureLast[j].dollarPath.p[0].y = y;
   594       inTouch->gestureLast[j].dollarPath.p[0].y = y;
   574       inTouch->gestureLast[j].dollarPath.numPoints = 1;
   595       inTouch->gestureLast[j].dollarPath.numPoints = 1;
   575     }
   596 #endif
   576   }
   597     }
   577 }  
   598   }
   578   
   599 }
       
   600 
   579   /* vi: set ts=4 sw=4 expandtab: */
   601   /* vi: set ts=4 sw=4 expandtab: */
   580   
   602