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