2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2008 Blender Foundation.
19 * All rights reserved.
22 * Contributor(s): Blender Foundation
24 * ***** END GPL LICENSE BLOCK *****
27 /** \file blender/windowmanager/intern/wm_gesture.c
32 #include "DNA_screen_types.h"
33 #include "DNA_vec_types.h"
34 #include "DNA_userdef_types.h"
35 #include "DNA_windowmanager_types.h"
37 #include "MEM_guardedalloc.h"
39 #include "BLI_blenlib.h"
41 #include "BLI_scanfill.h" /* lasso tessellation */
42 #include "BLI_utildefines.h"
44 #include "BKE_context.h"
51 #include "wm_event_system.h"
52 #include "wm_subwindow.h"
57 #include "BIF_glutil.h"
60 /* context checked on having screen, window and area */
61 wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type)
63 wmGesture *gesture = MEM_callocN(sizeof(wmGesture), "new gesture");
64 wmWindow *window = CTX_wm_window(C);
65 ARegion *ar = CTX_wm_region(C);
68 BLI_addtail(&window->gesture, gesture);
71 gesture->event_type = event->type;
72 gesture->swinid = ar->swinid; /* means only in area-region context! */
74 wm_subwindow_getorigin(window, gesture->swinid, &sx, &sy);
76 if (ELEM5(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK,
77 WM_GESTURE_CIRCLE, WM_GESTURE_STRAIGHTLINE))
79 rcti *rect = MEM_callocN(sizeof(rcti), "gesture rect new");
81 gesture->customdata = rect;
82 rect->xmin = event->x - sx;
83 rect->ymin = event->y - sy;
84 if (type == WM_GESTURE_CIRCLE) {
86 rect->xmax = circle_select_size;
88 rect->xmax = 25; // XXX temp
92 rect->xmax = event->x - sx;
93 rect->ymax = event->y - sy;
96 else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_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;
102 gesture->size = WM_LASSO_MIN_POINTS;
108 void WM_gesture_end(bContext *C, wmGesture *gesture)
110 wmWindow *win = CTX_wm_window(C);
112 if (win->tweak == gesture)
114 BLI_remlink(&win->gesture, gesture);
115 MEM_freeN(gesture->customdata);
119 void WM_gestures_remove(bContext *C)
121 wmWindow *win = CTX_wm_window(C);
123 while (win->gesture.first)
124 WM_gesture_end(C, win->gesture.first);
128 /* tweak and line gestures */
129 int wm_gesture_evaluate(wmGesture *gesture)
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;
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;
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");
165 /* ******************* gesture draw ******************* */
167 static void wm_gesture_draw_rect(wmGesture *gt)
169 rcti *rect = (rcti *)gt->customdata;
172 glColor4f(1.0, 1.0, 1.0, 0.05);
174 glVertex2s(rect->xmax, rect->ymin);
175 glVertex2s(rect->xmax, rect->ymax);
176 glVertex2s(rect->xmin, rect->ymax);
177 glVertex2s(rect->xmin, rect->ymin);
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);
191 static void wm_gesture_draw_line(wmGesture *gt)
193 rcti *rect = (rcti *)gt->customdata;
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);
203 glDisable(GL_LINE_STIPPLE);
207 static void wm_gesture_draw_circle(wmGesture *gt)
209 rcti *rect = (rcti *)gt->customdata;
211 glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f);
214 glColor4f(1.0, 1.0, 1.0, 0.05);
215 glutil_draw_filled_arc(0.0, M_PI * 2.0, rect->xmax, 40);
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);
226 glDisable(GL_LINE_STIPPLE);
227 glTranslatef((float)-rect->xmin, (float)-rect->ymin, 0.0f);
231 static void draw_filled_lasso(wmGesture *gt)
233 ScanFillContext sf_ctx;
234 ScanFillVert *v = NULL, *lastv = NULL, *firstv = NULL;
236 short *lasso = (short *)gt->customdata;
239 BLI_scanfill_begin(&sf_ctx);
240 for (i = 0; i < gt->points; i++, lasso += 2) {
243 co[0] = (float)lasso[0];
244 co[1] = (float)lasso[1];
247 v = BLI_scanfill_vert_add(&sf_ctx, co);
249 /* e = */ /* UNUSED */ BLI_scanfill_edge_add(&sf_ctx, lastv, v);
251 if (firstv == NULL) firstv = v;
254 /* highly unlikely this will fail, but could crash if (gt->points == 0) */
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);
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);
271 BLI_scanfill_end(&sf_ctx);
275 static void wm_gesture_draw_lasso(wmGesture *gt)
277 short *lasso = (short *)gt->customdata;
280 draw_filled_lasso(gt);
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)
288 if (gt->type == WM_GESTURE_LASSO)
289 glVertex2sv((short *)gt->customdata);
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)
298 if (gt->type == WM_GESTURE_LASSO)
299 glVertex2sv((short *)gt->customdata);
302 glDisable(GL_LINE_STIPPLE);
306 static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
308 rcti *rect = (rcti *)gt->customdata;
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);
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);
323 /* called in wm_draw.c */
324 void wm_gesture_draw(wmWindow *win)
326 wmGesture *gt = (wmGesture *)win->gesture.first;
328 for (; gt; gt = gt->next) {
329 /* all in subwindow space */
330 wmSubWindowSet(win, gt->swinid);
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) {
340 wm_gesture_draw_rect(gt);
342 wm_gesture_draw_cross(win, gt);
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);
353 void wm_gesture_tag_redraw(bContext *C)
355 wmWindow *win = CTX_wm_window(C);
356 bScreen *screen = CTX_wm_screen(C);
357 ARegion *ar = CTX_wm_region(C);
360 screen->do_draw_gesture = 1;
362 wm_tag_redraw_overlay(win, ar);