Merging r39251 through r39311 from trunk into soc-2011-tomato
[blender-staging.git] / source / blender / windowmanager / intern / wm_gesture.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  *
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/windowmanager/intern/wm_gesture.c
30  *  \ingroup wm
31  */
32
33
34 #include "DNA_screen_types.h"
35 #include "DNA_vec_types.h"
36 #include "DNA_userdef_types.h"
37 #include "DNA_windowmanager_types.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_editVert.h"       /* lasso tessellation */
43 #include "BLI_math.h"
44 #include "BLI_scanfill.h"       /* lasso tessellation */
45 #include "BLI_utildefines.h"
46
47 #include "BKE_context.h"
48
49
50 #include "WM_api.h"
51 #include "WM_types.h"
52
53 #include "wm.h"
54 #include "wm_event_system.h"
55 #include "wm_subwindow.h"
56 #include "wm_draw.h"
57
58
59 #include "BIF_gl.h"
60 #include "BIF_glutil.h"
61
62
63 /* context checked on having screen, window and area */
64 wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type)
65 {
66         wmGesture *gesture= MEM_callocN(sizeof(wmGesture), "new gesture");
67         wmWindow *window= CTX_wm_window(C);
68         ARegion *ar= CTX_wm_region(C);
69         int sx, sy;
70         
71         BLI_addtail(&window->gesture, gesture);
72         
73         gesture->type= type;
74         gesture->event_type= event->type;
75         gesture->swinid= ar->swinid;    /* means only in area-region context! */
76         
77         wm_subwindow_getorigin(window, gesture->swinid, &sx, &sy);
78         
79         if( ELEM5(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK, WM_GESTURE_CIRCLE, WM_GESTURE_STRAIGHTLINE)) {
80                 rcti *rect= MEM_callocN(sizeof(rcti), "gesture rect new");
81                 
82                 gesture->customdata= rect;
83                 rect->xmin= event->x - sx;
84                 rect->ymin= event->y - sy;
85                 if(type==WM_GESTURE_CIRCLE) {
86 #ifdef GESTURE_MEMORY
87                         rect->xmax= circle_select_size;
88 #else
89                         rect->xmax= 25; // XXX temp
90 #endif
91                 } else {
92                         rect->xmax= event->x - sx;
93                         rect->ymax= event->y - sy;
94                 }
95         }
96         else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) {
97                 short *lasso;
98                 gesture->customdata= lasso= MEM_callocN(2*sizeof(short)*WM_LASSO_MIN_POINTS, "lasso points");
99                 lasso[0] = event->x - sx;
100                 lasso[1] = event->y - sy;
101                 gesture->points= 1;
102                 gesture->size = WM_LASSO_MIN_POINTS;
103         }
104         
105         return gesture;
106 }
107
108 void WM_gesture_end(bContext *C, wmGesture *gesture)
109 {
110         wmWindow *win= CTX_wm_window(C);
111         
112         if(win->tweak==gesture)
113                 win->tweak= NULL;
114         BLI_remlink(&win->gesture, gesture);
115         MEM_freeN(gesture->customdata);
116         MEM_freeN(gesture);
117 }
118
119 void WM_gestures_remove(bContext *C)
120 {
121         wmWindow *win= CTX_wm_window(C);
122         
123         while(win->gesture.first)
124                 WM_gesture_end(C, win->gesture.first);
125 }
126
127
128 /* tweak and line gestures */
129 #define TWEAK_THRESHOLD         10
130 int wm_gesture_evaluate(wmGesture *gesture)
131 {
132         if(gesture->type==WM_GESTURE_TWEAK) {
133                 rcti *rect= gesture->customdata;
134                 int dx= rect->xmax - rect->xmin;
135                 int dy= rect->ymax - rect->ymin;
136                 if(ABS(dx)+ABS(dy) > TWEAK_THRESHOLD) {
137                         int theta= (int)floor(4.0f*atan2f((float)dy, (float)dx)/(float)M_PI + 0.5f);
138                         int val= EVT_GESTURE_W;
139                         
140                         if(theta==0) val= EVT_GESTURE_E;
141                         else if(theta==1) val= EVT_GESTURE_NE;
142                         else if(theta==2) val= EVT_GESTURE_N;
143                         else if(theta==3) val= EVT_GESTURE_NW;
144                         else if(theta==-1) val= EVT_GESTURE_SE;
145                         else if(theta==-2) val= EVT_GESTURE_S;
146                         else if(theta==-3) val= EVT_GESTURE_SW;
147                         
148 #if 0
149                         /* debug */
150                         if(val==1) printf("tweak north\n");
151                         if(val==2) printf("tweak north-east\n");
152                         if(val==3) printf("tweak east\n");
153                         if(val==4) printf("tweak south-east\n");
154                         if(val==5) printf("tweak south\n");
155                         if(val==6) printf("tweak south-west\n");
156                         if(val==7) printf("tweak west\n");
157                         if(val==8) printf("tweak north-west\n");
158 #endif                  
159                         return val;
160                 }
161         }
162         return 0;
163 }
164
165
166 /* ******************* gesture draw ******************* */
167
168 static void wm_gesture_draw_rect(wmGesture *gt)
169 {
170         rcti *rect= (rcti *)gt->customdata;
171         
172         glEnable(GL_BLEND);
173         glColor4f(1.0, 1.0, 1.0, 0.05);
174         glBegin(GL_QUADS);
175         glVertex2s(rect->xmax, rect->ymin);
176         glVertex2s(rect->xmax, rect->ymax);
177         glVertex2s(rect->xmin, rect->ymax);
178         glVertex2s(rect->xmin, rect->ymin);
179         glEnd();
180         glDisable(GL_BLEND);
181         
182         glEnable(GL_LINE_STIPPLE);
183         glColor3ub(96, 96, 96);
184         glLineStipple(1, 0xCCCC);
185         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
186         glColor3ub(255, 255, 255);
187         glLineStipple(1, 0x3333);
188         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
189         glDisable(GL_LINE_STIPPLE);
190 }
191
192 static void wm_gesture_draw_line(wmGesture *gt)
193 {
194         rcti *rect= (rcti *)gt->customdata;
195         
196         glEnable(GL_LINE_STIPPLE);
197         glColor3ub(96, 96, 96);
198         glLineStipple(1, 0xAAAA);
199         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
200         glColor3ub(255, 255, 255);
201         glLineStipple(1, 0x5555);
202         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
203
204         glDisable(GL_LINE_STIPPLE);
205         
206 }
207
208 static void wm_gesture_draw_circle(wmGesture *gt)
209 {
210         rcti *rect= (rcti *)gt->customdata;
211
212         glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f);
213
214         glEnable(GL_BLEND);
215         glColor4f(1.0, 1.0, 1.0, 0.05);
216         glutil_draw_filled_arc(0.0, M_PI*2.0, rect->xmax, 40);
217         glDisable(GL_BLEND);
218         
219         glEnable(GL_LINE_STIPPLE);
220         glColor3ub(96, 96, 96);
221         glLineStipple(1, 0xAAAA);
222         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
223         glColor3ub(255, 255, 255);
224         glLineStipple(1, 0x5555);
225         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
226         
227         glDisable(GL_LINE_STIPPLE);
228         glTranslatef((float)-rect->xmin, (float)-rect->ymin, 0.0f);
229         
230 }
231
232 static void draw_filled_lasso(wmGesture *gt)
233 {
234         EditVert *v=NULL, *lastv=NULL, *firstv=NULL;
235         EditEdge *e;
236         EditFace *efa;
237         short *lasso= (short *)gt->customdata;
238         int i;
239         
240         for (i=0; i<gt->points; i++, lasso+=2) {
241                 float co[3];
242
243                 co[0]= (float)lasso[0];
244                 co[1]= (float)lasso[1];
245                 co[2]= 0.0f;
246
247                 v = BLI_addfillvert(co);
248                 if (lastv)
249                         e = BLI_addfilledge(lastv, v);
250                 lastv = v;
251                 if (firstv==NULL) firstv = v;
252         }
253         
254         /* highly unlikely this will fail, but could crash if (gt->points == 0) */
255         if(firstv) {
256                 BLI_addfilledge(firstv, v);
257                 BLI_edgefill(0);
258         
259                 glEnable(GL_BLEND);
260                 glColor4f(1.0, 1.0, 1.0, 0.05);
261                 glBegin(GL_TRIANGLES);
262                 for (efa = fillfacebase.first; efa; efa=efa->next) {
263                         glVertex2f(efa->v1->co[0], efa->v1->co[1]);
264                         glVertex2f(efa->v2->co[0], efa->v2->co[1]);
265                         glVertex2f(efa->v3->co[0], efa->v3->co[1]);
266                 }
267                 glEnd();
268                 glDisable(GL_BLEND);
269         
270                 BLI_end_edgefill();
271         }
272 }
273
274 static void wm_gesture_draw_lasso(wmGesture *gt)
275 {
276         short *lasso= (short *)gt->customdata;
277         int i;
278
279         draw_filled_lasso(gt);
280         
281         glEnable(GL_LINE_STIPPLE);
282         glColor3ub(96, 96, 96);
283         glLineStipple(1, 0xAAAA);
284         glBegin(GL_LINE_STRIP);
285         for(i=0; i<gt->points; i++, lasso+=2)
286                 glVertex2sv(lasso);
287         if(gt->type==WM_GESTURE_LASSO)
288                 glVertex2sv((short *)gt->customdata);
289         glEnd();
290         
291         glColor3ub(255, 255, 255);
292         glLineStipple(1, 0x5555);
293         glBegin(GL_LINE_STRIP);
294         lasso= (short *)gt->customdata;
295         for(i=0; i<gt->points; i++, lasso+=2)
296                 glVertex2sv(lasso);
297         if(gt->type==WM_GESTURE_LASSO)
298                 glVertex2sv((short *)gt->customdata);
299         glEnd();
300         
301         glDisable(GL_LINE_STIPPLE);
302         
303 }
304
305 static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
306 {
307         rcti *rect= (rcti *)gt->customdata;
308         
309         glEnable(GL_LINE_STIPPLE);
310         glColor3ub(96, 96, 96);
311         glLineStipple(1, 0xCCCC);
312         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
313         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
314         
315         glColor3ub(255, 255, 255);
316         glLineStipple(1, 0x3333);
317         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
318         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
319         glDisable(GL_LINE_STIPPLE);
320 }
321
322 /* called in wm_draw.c */
323 void wm_gesture_draw(wmWindow *win)
324 {
325         wmGesture *gt= (wmGesture *)win->gesture.first;
326         
327         for(; gt; gt= gt->next) {
328                 /* all in subwindow space */
329                 wmSubWindowSet(win, gt->swinid);
330                 
331                 if(gt->type==WM_GESTURE_RECT)
332                         wm_gesture_draw_rect(gt);
333 //              else if(gt->type==WM_GESTURE_TWEAK)
334 //                      wm_gesture_draw_line(gt);
335                 else if(gt->type==WM_GESTURE_CIRCLE)
336                         wm_gesture_draw_circle(gt);
337                 else if(gt->type==WM_GESTURE_CROSS_RECT) {
338                         if(gt->mode==1)
339                                 wm_gesture_draw_rect(gt);
340                         else
341                                 wm_gesture_draw_cross(win, gt);
342                 }
343                 else if(gt->type==WM_GESTURE_LINES) 
344                         wm_gesture_draw_lasso(gt);
345                 else if(gt->type==WM_GESTURE_LASSO) 
346                         wm_gesture_draw_lasso(gt);
347                 else if(gt->type==WM_GESTURE_STRAIGHTLINE)
348                         wm_gesture_draw_line(gt);
349         }
350 }
351
352 void wm_gesture_tag_redraw(bContext *C)
353 {
354         wmWindow *win= CTX_wm_window(C);
355         bScreen *screen= CTX_wm_screen(C);
356         ARegion *ar= CTX_wm_region(C);
357         
358         if(screen)
359                 screen->do_draw_gesture= 1;
360
361         wm_tag_redraw_overlay(win, ar);
362 }