Fix syntax for ID keyword.
[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 #include "DNA_screen_types.h"
30 #include "DNA_vec_types.h"
31 #include "DNA_userdef_types.h"
32 #include "DNA_windowmanager_types.h"
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_blenlib.h"
37 #include "BLI_editVert.h"       /* lasso tessellation */
38 #include "BLI_math.h"
39 #include "BLI_scanfill.h"       /* lasso tessellation */
40
41 #include "BKE_context.h"
42 #include "BKE_utildefines.h"
43
44 #include "WM_api.h"
45 #include "WM_types.h"
46
47 #include "wm.h"
48 #include "wm_event_system.h"
49 #include "wm_subwindow.h"
50
51 #include "ED_screen.h"
52
53 #include "BIF_gl.h"
54 #include "BIF_glutil.h"
55
56
57 /* context checked on having screen, window and area */
58 wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type)
59 {
60         wmGesture *gesture= MEM_callocN(sizeof(wmGesture), "new gesture");
61         wmWindow *window= CTX_wm_window(C);
62         ARegion *ar= CTX_wm_region(C);
63         int sx, sy;
64         
65         BLI_addtail(&window->gesture, gesture);
66         
67         gesture->type= type;
68         gesture->event_type= event->type;
69         gesture->swinid= ar->swinid;    /* means only in area-region context! */
70         
71         wm_subwindow_getorigin(window, gesture->swinid, &sx, &sy);
72         
73         if( ELEM4(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK, WM_GESTURE_CIRCLE)) {
74                 rcti *rect= MEM_callocN(sizeof(rcti), "gesture rect new");
75                 
76                 gesture->customdata= rect;
77                 rect->xmin= event->x - sx;
78                 rect->ymin= event->y - sy;
79                 if(type==WM_GESTURE_CIRCLE) {
80 #ifdef GESTURE_MEMORY
81                         rect->xmax= circle_select_size;
82 #else
83                         rect->xmax= 25; // XXX temp
84 #endif
85                 } else {
86                         rect->xmax= event->x - sx;
87                         rect->ymax= event->y - sy;
88                 }
89         }
90         else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) {
91                 short *lasso;
92                 gesture->customdata= lasso= MEM_callocN(2*sizeof(short)*WM_LASSO_MIN_POINTS, "lasso points");
93                 lasso[0] = event->x - sx;
94                 lasso[1] = event->y - sy;
95                 gesture->points= 1;
96                 gesture->size = WM_LASSO_MIN_POINTS;
97         }
98         
99         return gesture;
100 }
101
102 void WM_gesture_end(bContext *C, wmGesture *gesture)
103 {
104         wmWindow *win= CTX_wm_window(C);
105         
106         if(win->tweak==gesture)
107                 win->tweak= NULL;
108         BLI_remlink(&win->gesture, gesture);
109         MEM_freeN(gesture->customdata);
110         MEM_freeN(gesture);
111 }
112
113 void WM_gestures_remove(bContext *C)
114 {
115         wmWindow *win= CTX_wm_window(C);
116         
117         while(win->gesture.first)
118                 WM_gesture_end(C, win->gesture.first);
119 }
120
121
122 /* tweak and line gestures */
123 #define TWEAK_THRESHOLD         10
124 int wm_gesture_evaluate(bContext *C, wmGesture *gesture)
125 {
126         if(gesture->type==WM_GESTURE_TWEAK) {
127                 rcti *rect= gesture->customdata;
128                 int dx= rect->xmax - rect->xmin;
129                 int dy= rect->ymax - rect->ymin;
130                 if(ABS(dx)+ABS(dy) > TWEAK_THRESHOLD) {
131                         int theta= (int)floor(4.0f*atan2((float)dy, (float)dx)/M_PI + 0.5);
132                         int val= EVT_GESTURE_W;
133                         
134                         if(theta==0) val= EVT_GESTURE_E;
135                         else if(theta==1) val= EVT_GESTURE_NE;
136                         else if(theta==2) val= EVT_GESTURE_N;
137                         else if(theta==3) val= EVT_GESTURE_NW;
138                         else if(theta==-1) val= EVT_GESTURE_SE;
139                         else if(theta==-2) val= EVT_GESTURE_S;
140                         else if(theta==-3) val= EVT_GESTURE_SW;
141                         
142 #if 0
143                         /* debug */
144                         if(val==1) printf("tweak north\n");
145                         if(val==2) printf("tweak north-east\n");
146                         if(val==3) printf("tweak east\n");
147                         if(val==4) printf("tweak south-east\n");
148                         if(val==5) printf("tweak south\n");
149                         if(val==6) printf("tweak south-west\n");
150                         if(val==7) printf("tweak west\n");
151                         if(val==8) printf("tweak north-west\n");
152 #endif                  
153                         return val;
154                 }
155         }
156         return 0;
157 }
158
159
160 /* ******************* gesture draw ******************* */
161
162 static void wm_gesture_draw_rect(wmWindow *win, wmGesture *gt)
163 {
164         rcti *rect= (rcti *)gt->customdata;
165         
166         glEnable(GL_BLEND);
167         glColor4f(1.0, 1.0, 1.0, 0.05);
168         glBegin(GL_QUADS);
169         glVertex2s(rect->xmax, rect->ymin);
170         glVertex2s(rect->xmax, rect->ymax);
171         glVertex2s(rect->xmin, rect->ymax);
172         glVertex2s(rect->xmin, rect->ymin);
173         glEnd();
174         glDisable(GL_BLEND);
175         
176         glEnable(GL_LINE_STIPPLE);
177         glColor3ub(96, 96, 96);
178         glLineStipple(1, 0xCCCC);
179         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
180         glColor3ub(255, 255, 255);
181         glLineStipple(1, 0x3333);
182         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
183         glDisable(GL_LINE_STIPPLE);
184 }
185
186 static void wm_gesture_draw_line(wmWindow *win, wmGesture *gt)
187 {
188         rcti *rect= (rcti *)gt->customdata;
189         
190         glEnable(GL_LINE_STIPPLE);
191         glColor3ub(96, 96, 96);
192         glLineStipple(1, 0xAAAA);
193         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
194         glColor3ub(255, 255, 255);
195         glLineStipple(1, 0x5555);
196         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
197
198         glDisable(GL_LINE_STIPPLE);
199         
200 }
201
202 static void wm_gesture_draw_circle(wmWindow *win, wmGesture *gt)
203 {
204         rcti *rect= (rcti *)gt->customdata;
205
206         glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f);
207
208         glEnable(GL_BLEND);
209         glColor4f(1.0, 1.0, 1.0, 0.05);
210         glutil_draw_filled_arc(0.0, M_PI*2.0, rect->xmax, 40);
211         glDisable(GL_BLEND);
212         
213         glEnable(GL_LINE_STIPPLE);
214         glColor3ub(96, 96, 96);
215         glLineStipple(1, 0xAAAA);
216         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
217         glColor3ub(255, 255, 255);
218         glLineStipple(1, 0x5555);
219         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
220         
221         glDisable(GL_LINE_STIPPLE);
222         glTranslatef((float)-rect->xmin, (float)-rect->ymin, 0.0f);
223         
224 }
225
226 static void draw_filled_lasso(wmGesture *gt)
227 {
228         EditVert *v=NULL, *lastv=NULL, *firstv=NULL;
229         EditEdge *e;
230         EditFace *efa;
231         short *lasso= (short *)gt->customdata;
232         int i;
233         
234         for (i=0; i<gt->points; i++, lasso+=2) {
235                 float co[3] = {(float)lasso[0], (float)lasso[1], 0.f};
236                 
237                 v = BLI_addfillvert(co);
238                 if (lastv)
239                         e = BLI_addfilledge(lastv, v);
240                 lastv = v;
241         if (firstv==NULL) firstv = v;
242         }
243         
244         /* highly unlikely this will fail, but could crash if (gt->points == 0) */
245         if(firstv) {
246                 BLI_addfilledge(firstv, v);
247                 BLI_edgefill(0, 0);
248         
249                 glEnable(GL_BLEND);
250                 glColor4f(1.0, 1.0, 1.0, 0.05);
251                 glBegin(GL_TRIANGLES);
252                 for (efa = fillfacebase.first; efa; efa=efa->next) {
253                         glVertex2f(efa->v1->co[0], efa->v1->co[1]);
254                         glVertex2f(efa->v2->co[0], efa->v2->co[1]);
255                         glVertex2f(efa->v3->co[0], efa->v3->co[1]);
256                 }
257                 glEnd();
258                 glDisable(GL_BLEND);
259         
260                 BLI_end_edgefill();
261         }
262 }
263
264 static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt)
265 {
266         short *lasso= (short *)gt->customdata;
267         int i;
268
269         draw_filled_lasso(gt);
270         
271         glEnable(GL_LINE_STIPPLE);
272         glColor3ub(96, 96, 96);
273         glLineStipple(1, 0xAAAA);
274         glBegin(GL_LINE_STRIP);
275         lasso= (short *)gt->customdata;
276         for(i=0; i<gt->points; i++, lasso+=2)
277                 glVertex2sv(lasso);
278         if(gt->type==WM_GESTURE_LASSO)
279                 glVertex2sv((short *)gt->customdata);
280         glEnd();
281         
282         glColor3ub(255, 255, 255);
283         glLineStipple(1, 0x5555);
284         glBegin(GL_LINE_STRIP);
285         lasso= (short *)gt->customdata;
286         for(i=0; i<gt->points; i++, lasso+=2)
287                 glVertex2sv(lasso);
288         if(gt->type==WM_GESTURE_LASSO)
289                 glVertex2sv((short *)gt->customdata);
290         glEnd();
291         
292         glDisable(GL_LINE_STIPPLE);
293         
294 }
295
296 static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
297 {
298         rcti *rect= (rcti *)gt->customdata;
299         
300         glEnable(GL_LINE_STIPPLE);
301         glColor3ub(96, 96, 96);
302         glLineStipple(1, 0xCCCC);
303         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
304         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
305         
306         glColor3ub(255, 255, 255);
307         glLineStipple(1, 0x3333);
308         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
309         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
310         glDisable(GL_LINE_STIPPLE);
311 }
312
313 /* called in wm_draw.c */
314 void wm_gesture_draw(wmWindow *win)
315 {
316         wmGesture *gt= (wmGesture *)win->gesture.first;
317         
318         for(; gt; gt= gt->next) {
319                 /* all in subwindow space */
320                 wmSubWindowSet(win, gt->swinid);
321                 
322                 if(gt->type==WM_GESTURE_RECT)
323                         wm_gesture_draw_rect(win, gt);
324                 else if(gt->type==WM_GESTURE_TWEAK)
325                         wm_gesture_draw_line(win, gt);
326                 else if(gt->type==WM_GESTURE_CIRCLE)
327                         wm_gesture_draw_circle(win, gt);
328                 else if(gt->type==WM_GESTURE_CROSS_RECT) {
329                         if(gt->mode==1)
330                                 wm_gesture_draw_rect(win, gt);
331                         else
332                                 wm_gesture_draw_cross(win, gt);
333                 }
334                 else if(gt->type==WM_GESTURE_LINES) 
335                         wm_gesture_draw_lasso(win, gt);
336                 else if(gt->type==WM_GESTURE_LASSO) 
337                         wm_gesture_draw_lasso(win, gt);
338         }
339 }
340
341 void wm_gesture_tag_redraw(bContext *C)
342 {
343         wmWindow *win= CTX_wm_window(C);
344         bScreen *screen= CTX_wm_screen(C);
345         ARegion *ar= CTX_wm_region(C);
346         
347         if(screen)
348                 screen->do_draw_gesture= 1;
349         if(ar && win->drawmethod != USER_DRAW_TRIPLE)
350                 ED_region_tag_redraw(ar);
351 }
352
353