comparison src/events/SDL_gesture.c @ 4657:eed063a0bf5b

Moved Multi finger gesture recognition into the library.
author Jim Grandpre <jim.tla@gmail.com>
date Wed, 07 Jul 2010 04:13:08 -0700
parents
children 454385d76845
comparison
equal deleted inserted replaced
4656:b5007b7995c6 4657:eed063a0bf5b
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2010 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 /* General mouse handling code for SDL */
25
26 #include "SDL_events.h"
27 #include "SDL_events_c.h"
28 #include "SDL_gesture_c.h"
29
30 //TODO: Replace with malloc
31 #define MAXFINGERS 3
32 #define MAXTOUCHES 2
33
34 typedef struct {
35 float x,y;
36 } Point;
37
38
39 typedef struct {
40 Point p;
41 float pressure;
42 int id;
43 } Finger;
44
45 typedef struct {
46 Finger f;
47 Point cv;
48 float dtheta,dDist;
49 } TouchPoint;
50
51
52 typedef struct {
53 int id;
54 Point res;
55 Point centroid;
56 TouchPoint gestureLast[MAXFINGERS];
57 int numDownFingers;
58 } GestureTouch;
59
60 GestureTouch gestureTouch[MAXTOUCHES];
61 int numGestureTouches = 0;
62 int SDL_GestureAddTouch(SDL_Touch* touch) {
63 if(numGestureTouches >= MAXTOUCHES) return -1;
64
65 gestureTouch[numGestureTouches].res.x = touch->xres;
66 gestureTouch[numGestureTouches].res.y = touch->yres;
67 gestureTouch[numGestureTouches].numDownFingers = 0;
68
69 gestureTouch[numGestureTouches].res.x = touch->xres;
70 gestureTouch[numGestureTouches].id = touch->id;
71
72 numGestureTouches++;
73 return 0;
74 }
75
76 GestureTouch * SDL_GetGestureTouch(int id) {
77 int i;
78 for(i = 0;i < numGestureTouches; i++) {
79 //printf("%i ?= %i\n",gestureTouch[i].id,id);
80 if(gestureTouch[i].id == id) return &gestureTouch[i];
81 }
82 return NULL;
83 }
84
85 int SDL_SendGestureMulti(GestureTouch* touch,float dTheta,float dDist) {
86 SDL_Event event;
87 event.mgesture.type = SDL_MULTIGESTURE;
88 event.mgesture.touchId = touch->id;
89 event.mgesture.x = touch->centroid.x;
90 event.mgesture.y = touch->centroid.y;
91 event.mgesture.dTheta = dTheta;
92 event.mgesture.dDist = dDist;
93 return SDL_PushEvent(&event) > 0;
94 }
95
96 void SDL_GestureProcessEvent(SDL_Event* event)
97 {
98 if(event->type == SDL_FINGERMOTION ||
99 event->type == SDL_FINGERDOWN ||
100 event->type == SDL_FINGERUP) {
101 GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
102
103
104 //Shouldn't be possible
105 if(inTouch == NULL) return;
106
107
108 float x = ((float)event->tfinger.x)/inTouch->res.x;
109 float y = ((float)event->tfinger.y)/inTouch->res.y;
110 int j,empty = -1;
111
112 for(j = 0;j<inTouch->numDownFingers;j++) {
113 if(inTouch->gestureLast[j].f.id != event->tfinger.fingerId) continue;
114
115 if(event->type == SDL_FINGERUP) {
116 inTouch->numDownFingers--;
117 inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
118 break;
119 }
120 else {
121 float dx = x - inTouch->gestureLast[j].f.p.x;
122 float dy = y - inTouch->gestureLast[j].f.p.y;
123 inTouch->centroid.x += dx/inTouch->numDownFingers;
124 inTouch->centroid.y += dy/inTouch->numDownFingers;
125 if(inTouch->numDownFingers > 1) {
126 Point lv; //Vector from centroid to last x,y position
127 Point v; //Vector from centroid to current x,y position
128 lv = inTouch->gestureLast[j].cv;
129 float lDist = sqrt(lv.x*lv.x + lv.y*lv.y);
130 //printf("lDist = %f\n",lDist);
131 v.x = x - inTouch->centroid.x;
132 v.y = y - inTouch->centroid.y;
133 inTouch->gestureLast[j].cv = v;
134 float Dist = sqrt(v.x*v.x+v.y*v.y);
135 // cos(dTheta) = (v . lv)/(|v| * |lv|)
136
137 //Normalize Vectors to simplify angle calculation
138 lv.x/=lDist;
139 lv.y/=lDist;
140 v.x/=Dist;
141 v.y/=Dist;
142 float dtheta = atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
143
144 float dDist = (Dist - lDist);
145 if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
146 inTouch->gestureLast[j].dDist = dDist;
147 inTouch->gestureLast[j].dtheta = dtheta;
148
149 //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
150 //gdtheta = gdtheta*.9 + dtheta*.1;
151 //gdDist = gdDist*.9 + dDist*.1
152 //knob.r += dDist/numDownFingers;
153 //knob.ang += dtheta;
154 //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
155 //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
156 SDL_SendGestureMulti(inTouch,dtheta,dDist);
157 }
158 else {
159 inTouch->gestureLast[j].dDist = 0;
160 inTouch->gestureLast[j].dtheta = 0;
161 inTouch->gestureLast[j].cv.x = 0;
162 inTouch->gestureLast[j].cv.y = 0;
163 }
164 inTouch->gestureLast[j].f.p.x = x;
165 inTouch->gestureLast[j].f.p.y = y;
166 break;
167 //pressure?
168 }
169 }
170
171 if(j == inTouch->numDownFingers) {
172 //printf("Finger Down!!!\n");
173 inTouch->numDownFingers++;
174 inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+
175 x)/inTouch->numDownFingers;
176 inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
177 y)/inTouch->numDownFingers;
178
179 inTouch->gestureLast[j].f.id = event->tfinger.fingerId;
180 inTouch->gestureLast[j].f.p.x = x;
181 inTouch->gestureLast[j].f.p.y = y;
182 inTouch->gestureLast[j].cv.x = 0;
183 inTouch->gestureLast[j].cv.y = 0;
184 }
185 }
186 }
187
188 /* vi: set ts=4 sw=4 expandtab: */
189