From 34902088074c643b840aef10fe050d72d76b0197 Mon Sep 17 00:00:00 2001 From: Jim Grandpre Date: Wed, 4 Aug 2010 23:17:30 -0400 Subject: [PATCH] Fixed gestureMulti. Disabled dollar gesture temporarily. --- include/SDL_events.h | 5 +- src/events/SDL_gesture.c | 250 ++++++++++++++++++--------------- src/events/SDL_touch.c | 34 +++-- src/video/x11/SDL_eventtouch.c | 8 ++ src/video/x11/SDL_x11events.c | 22 +-- touchTest/gestureSDLTest.c | 9 +- 6 files changed, 188 insertions(+), 140 deletions(-) diff --git a/include/SDL_events.h b/include/SDL_events.h index 032bed438..f6603c1f1 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -296,6 +296,8 @@ typedef struct SDL_TouchFingerEvent Uint8 padding3; Uint16 x; Uint16 y; + Sint16 dx; + Sint16 dy; Uint16 pressure; } SDL_TouchFingerEvent; @@ -328,7 +330,8 @@ typedef struct SDL_MultiGestureEvent float dDist; float x; //currently 0...1. Change to screen coords? float y; - + Uint16 numFingers; + Uint16 padding; } SDL_MultiGestureEvent; typedef struct SDL_DollarGestureEvent diff --git a/src/events/SDL_gesture.c b/src/events/SDL_gesture.c index de5a0ea83..6d057585f 100644 --- a/src/events/SDL_gesture.c +++ b/src/events/SDL_gesture.c @@ -75,7 +75,7 @@ typedef struct { Point res; Point centroid; TouchPoint gestureLast[MAXFINGERS]; - int numDownFingers; + Uint16 numDownFingers; int numDollarTemplates; DollarTemplate dollarTemplate[MAXTEMPLATES]; @@ -406,6 +406,7 @@ int SDL_SendGestureMulti(GestureTouch* touch,float dTheta,float dDist) { event.mgesture.y = touch->centroid.y; event.mgesture.dTheta = dTheta; event.mgesture.dDist = dDist; + event.mgesture.numFingers = touch->numDownFingers; return SDL_PushEvent(&event) > 0; } @@ -441,140 +442,161 @@ void SDL_GestureProcessEvent(SDL_Event* event) event->type == SDL_FINGERDOWN || event->type == SDL_FINGERUP) { GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId); - + //Shouldn't be possible if(inTouch == NULL) return; + //printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x, + // (int)event->tfinger.y, + // (int)inTouch->res.x,(int)inTouch->res.y); + - float x = ((float)event->tfinger.x)/inTouch->res.x; - float y = ((float)event->tfinger.y)/inTouch->res.y; - int j,empty = -1; - - for(j = 0;jnumDownFingers;j++) { - if(inTouch->gestureLast[j].f.id != event->tfinger.fingerId) continue; - //Finger Up - if(event->type == SDL_FINGERUP) { - inTouch->numDownFingers--; - - if(inTouch->recording) { - inTouch->recording = SDL_FALSE; - Point path[DOLLARNPOINTS]; - dollarNormalize(inTouch->gestureLast[j].dollarPath,path); - int index; - if(recordAll) { - index = SDL_AddDollarGesture(NULL,path); - int i; - for(i = 0;i < numGestureTouches; i++) - gestureTouch[i].recording = SDL_FALSE; - } - else { - index = SDL_AddDollarGesture(inTouch,path); - } - - if(index >= 0) { - SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash); - } - else { - SDL_SendDollarRecord(inTouch,-1); - } - } - else { - int bestTempl; - float error; - error = dollarRecognize(inTouch->gestureLast[j].dollarPath, - &bestTempl,inTouch); - if(bestTempl >= 0){ - //Send Event - unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash; - SDL_SendGestureDollar(inTouch,gestureId,error); - printf("Dollar error: %f\n",error); - } - } - inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers]; - j = -1; - break; - } - else if(event->type == SDL_FINGERMOTION) { - float dx = x - inTouch->gestureLast[j].f.p.x; - float dy = y - inTouch->gestureLast[j].f.p.y; - DollarPath* path = &inTouch->gestureLast[j].dollarPath; - if(path->numPoints < MAXPATHSIZE) { - path->p[path->numPoints].x = x; - path->p[path->numPoints].y = y; - path->length += sqrt(dx*dx + dy*dy); - path->numPoints++; - } + float x = ((float)event->tfinger.x)/(float)inTouch->res.x; + float y = ((float)event->tfinger.y)/(float)inTouch->res.y; - inTouch->centroid.x += dx/inTouch->numDownFingers; - inTouch->centroid.y += dy/inTouch->numDownFingers; - if(inTouch->numDownFingers > 1) { - Point lv; //Vector from centroid to last x,y position - Point v; //Vector from centroid to current x,y position - lv = inTouch->gestureLast[j].cv; - float lDist = sqrt(lv.x*lv.x + lv.y*lv.y); - //printf("lDist = %f\n",lDist); - v.x = x - inTouch->centroid.x; - v.y = y - inTouch->centroid.y; - inTouch->gestureLast[j].cv = v; - float Dist = sqrt(v.x*v.x+v.y*v.y); - // cos(dTheta) = (v . lv)/(|v| * |lv|) - - //Normalize Vectors to simplify angle calculation - lv.x/=lDist; - lv.y/=lDist; - v.x/=Dist; - v.y/=Dist; - float dtheta = atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y); - - float dDist = (Dist - lDist); - if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values - inTouch->gestureLast[j].dDist = dDist; - inTouch->gestureLast[j].dtheta = dtheta; - - //printf("dDist = %f, dTheta = %f\n",dDist,dtheta); - //gdtheta = gdtheta*.9 + dtheta*.1; - //gdDist = gdDist*.9 + dDist*.1 - //knob.r += dDist/numDownFingers; - //knob.ang += dtheta; - //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist); - //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist); - SDL_SendGestureMulti(inTouch,dtheta,dDist); + //Finger Up + if(event->type == SDL_FINGERUP) { + inTouch->numDownFingers--; + +#ifdef ENABLE_DOLLAR + if(inTouch->recording) { + inTouch->recording = SDL_FALSE; + Point path[DOLLARNPOINTS]; + dollarNormalize(inTouch->gestureLast[j].dollarPath,path); + int index; + if(recordAll) { + index = SDL_AddDollarGesture(NULL,path); + int i; + for(i = 0;i < numGestureTouches; i++) + gestureTouch[i].recording = SDL_FALSE; } else { - inTouch->gestureLast[j].dDist = 0; - inTouch->gestureLast[j].dtheta = 0; - inTouch->gestureLast[j].cv.x = 0; - inTouch->gestureLast[j].cv.y = 0; + index = SDL_AddDollarGesture(inTouch,path); } - inTouch->gestureLast[j].f.p.x = x; - inTouch->gestureLast[j].f.p.y = y; - break; - //pressure? - } + + if(index >= 0) { + SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash); + } + else { + SDL_SendDollarRecord(inTouch,-1); + } + } + else { + int bestTempl; + float error; + error = dollarRecognize(inTouch->gestureLast[j].dollarPath, + &bestTempl,inTouch); + if(bestTempl >= 0){ + //Send Event + unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash; + SDL_SendGestureDollar(inTouch,gestureId,error); + printf ("%s\n",);("Dollar error: %f\n",error); + } + } +#endif + //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers]; + if(inTouch->numDownFingers > 0) { + inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)- + x)/inTouch->numDownFingers; + inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)- + y)/inTouch->numDownFingers; + } + } + else if(event->type == SDL_FINGERMOTION) { + float dx = ((float)event->tfinger.dx)/(float)inTouch->res.x; + float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y; + //printf("dx,dy: (%f,%f)\n",dx,dy); +#ifdef ENABLE_DOLLAR + DollarPath* path = &inTouch->gestureLast[j].dollarPath; + if(path->numPoints < MAXPATHSIZE) { + path->p[path->numPoints].x = x; + path->p[path->numPoints].y = y; + path->length += sqrt(dx*dx + dy*dy); + path->numPoints++; + } +#endif + Point lastP; + lastP.x = x - dx; + lastP.y = y - dy; + Point lastCentroid; + lastCentroid = inTouch->centroid; + + inTouch->centroid.x += dx/inTouch->numDownFingers; + inTouch->centroid.y += dy/inTouch->numDownFingers; + if(inTouch->numDownFingers > 1) { + Point lv; //Vector from centroid to last x,y position + Point 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; + float lDist = sqrt(lv.x*lv.x + lv.y*lv.y); + //printf("lDist = %f\n",lDist); + v.x = x - inTouch->centroid.x; + v.y = y - inTouch->centroid.y; + //inTouch->gestureLast[j].cv = v; + float Dist = sqrt(v.x*v.x+v.y*v.y); + // cos(dTheta) = (v . lv)/(|v| * |lv|) + + //Normalize Vectors to simplify angle calculation + lv.x/=lDist; + lv.y/=lDist; + v.x/=Dist; + v.y/=Dist; + float dtheta = atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y); + + float dDist = (Dist - lDist); + if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values + + //inTouch->gestureLast[j].dDist = dDist; + //inTouch->gestureLast[j].dtheta = dtheta; + + //printf("dDist = %f, dTheta = %f\n",dDist,dtheta); + //gdtheta = gdtheta*.9 + dtheta*.1; + //gdDist = gdDist*.9 + dDist*.1 + //knob.r += dDist/numDownFingers; + //knob.ang += dtheta; + //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist); + //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist); + SDL_SendGestureMulti(inTouch,dtheta,dDist); + } + else { + //inTouch->gestureLast[j].dDist = 0; + //inTouch->gestureLast[j].dtheta = 0; + //inTouch->gestureLast[j].cv.x = 0; + //inTouch->gestureLast[j].cv.y = 0; + } + //inTouch->gestureLast[j].f.p.x = x; + //inTouch->gestureLast[j].f.p.y = y; + //break; + //pressure? } - if(j == inTouch->numDownFingers) { - //printf("Finger Down!!!\n"); + if(event->type == SDL_FINGERDOWN) { + inTouch->numDownFingers++; inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+ x)/inTouch->numDownFingers; inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+ y)/inTouch->numDownFingers; - - 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); + /* + 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; + */ +#ifdef ENABlE_DOLLAR inTouch->gestureLast[j].dollarPath.length = 0; inTouch->gestureLast[j].dollarPath.p[0].x = x; inTouch->gestureLast[j].dollarPath.p[0].y = y; inTouch->gestureLast[j].dollarPath.numPoints = 1; +#endif } } -} - +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index 71426f1bf..56158142e 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -318,15 +318,17 @@ SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, if(!touch) { return SDL_TouchNotFoundError(id); } + + //scale to Integer coordinates Uint16 x = (xin+touch->x_min)*(touch->xres)/(touch->native_xres); Uint16 y = (yin+touch->y_min)*(touch->yres)/(touch->native_yres); - Uint16 pressure = (yin+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres); + Uint16 pressure = (yin+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres); + + SDL_Finger *finger = SDL_GetFinger(touch,fingerid); if(down) { - SDL_Finger *finger = SDL_GetFinger(touch,fingerid); - SDL_Finger nf; if(finger == NULL) { - + SDL_Finger nf; nf.id = fingerid; nf.x = x; nf.y = y; @@ -337,8 +339,8 @@ SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, nf.last_y = y; nf.last_pressure = pressure; nf.down = SDL_FALSE; - SDL_AddFinger(touch,&nf); - finger = &nf; + if(SDL_AddFinger(touch,&nf) < 0) return 0; + finger = SDL_GetFinger(touch,fingerid); } else if(finger->down) return 0; if(xin < touch->x_min || yin < touch->y_min) return 0; //should defer if only a partial input @@ -358,7 +360,7 @@ SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, return posted; } else { - if(SDL_DelFinger(touch,fingerid) < 0) return 0; + if(finger == NULL) {printf("Finger not found...\n");return 0;} posted = 0; if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) { SDL_Event event; @@ -367,8 +369,15 @@ SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, event.tfinger.state = touch->buttonstate; event.tfinger.windowID = touch->focus ? touch->focus->id : 0; event.tfinger.fingerId = fingerid; + //I don't trust the coordinates passed on fingerUp + event.tfinger.x = finger->x; + event.tfinger.y = finger->y; + event.tfinger.dx = 0; + event.tfinger.dy = 0; + + if(SDL_DelFinger(touch,fingerid) < 0) return 0; posted = (SDL_PushEvent(&event) > 0); - } + } return posted; } } @@ -381,8 +390,7 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative, SDL_Touch *touch = SDL_GetTouch(id); SDL_Finger *finger = SDL_GetFinger(touch,fingerid); int posted; - float xrel; - float yrel; + Sint16 xrel, yrel; float x_max = 0, y_max = 0; if (!touch) { @@ -398,7 +406,7 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative, } if(finger == NULL || !finger->down) { - return SDL_SendFingerDown(id,fingerid,SDL_TRUE,x,y,pressure); + return SDL_SendFingerDown(id,fingerid,SDL_TRUE,xin,yin,pressurein); } else { /* the relative motion is calculated regarding the last position */ if (relative) { @@ -412,6 +420,7 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative, if(pressurein < touch->pressure_min) pressure = finger->last_pressure; xrel = x - finger->last_x; yrel = y - finger->last_y; + //printf("xrel,yrel (%i,%i)\n",(int)xrel,(int)yrel); } /* Drop events that don't change state */ @@ -460,6 +469,9 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative, event.tfinger.fingerId = fingerid; event.tfinger.x = x; event.tfinger.y = y; + event.tfinger.dx = xrel; + event.tfinger.dy = yrel; + event.tfinger.pressure = pressure; event.tfinger.state = touch->buttonstate; diff --git a/src/video/x11/SDL_eventtouch.c b/src/video/x11/SDL_eventtouch.c index 85e5f12af..976dfdd4c 100644 --- a/src/video/x11/SDL_eventtouch.c +++ b/src/video/x11/SDL_eventtouch.c @@ -61,6 +61,14 @@ X11_InitTouch(_THIS) touch.driverdata = SDL_malloc(sizeof(EventTouchData)); EventTouchData* data = (EventTouchData*)(touch.driverdata); + + data->x = -1; + data->y = -1; + data->pressure = -1; + data->finger = 0; + data->up = SDL_FALSE; + + printf("Opening device...\n"); //printf("New Touch - DataPtr: %i\n",data); data->eventStream = open(tstr, diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 9069ab55b..5c52a5f90 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -439,8 +439,8 @@ X11_PumpEvents(_THIS) if(data->pressure < 0) data->pressure = 0; break; case ABS_MISC: - data->up = SDL_TRUE; - data->finger = ev[i].value; + if(ev[i].value == 0) + data->up = SDL_TRUE; break; } break; @@ -453,22 +453,22 @@ X11_PumpEvents(_THIS) if(data->up) { SDL_SendFingerDown(touch->id,data->finger, SDL_FALSE,data->x,data->y, - data->pressure); + data->pressure); } else if(data->x >= 0 || data->y >= 0) - SDL_SendTouchMotion(touch->id,data->finger, + SDL_SendTouchMotion(touch->id,data->finger, SDL_FALSE,data->x,data->y, - data->pressure); + data->pressure); //printf("Synched: %i tx: %i, ty: %i\n", // data->finger,data->x,data->y); - data->x = -1; - data->y = -1; - data->pressure = -1; - data->finger = 0; - data->up = SDL_FALSE; + data->x = -1; + data->y = -1; + data->pressure = -1; + data->finger = 0; + data->up = SDL_FALSE; - break; + break; } } } diff --git a/touchTest/gestureSDLTest.c b/touchTest/gestureSDLTest.c index d1bc798f5..0496b74d1 100644 --- a/touchTest/gestureSDLTest.c +++ b/touchTest/gestureSDLTest.c @@ -414,11 +414,14 @@ int main(int argc, char* argv[]) */ break; case SDL_MULTIGESTURE: + /* printf("Multi Gesture: x = %f, y = %f, dAng = %f, dR = %f\n", event.mgesture.x, event.mgesture.y, event.mgesture.dTheta, event.mgesture.dDist); + printf("MG: numDownTouch = %i\n",event.mgesture.numFingers); + */ knob.p.x = event.mgesture.x; knob.p.y = event.mgesture.y; knob.ang += event.mgesture.dTheta; @@ -435,9 +438,9 @@ int main(int argc, char* argv[]) } } DrawScreen(screen,h); - for(i = 0; i < 256; i++) - if(keystat[i]) - printf("Key %i down\n",i); + //for(i = 0; i < 256; i++) + // if(keystat[i]) + // printf("Key %i down\n",i); } SDL_Quit();