RNA
[blender.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #define _USE_MATH_DEFINES
30 #include <math.h>
31
32 #include "DNA_screen_types.h"
33 #include "DNA_vec_types.h"
34 #include "DNA_windowmanager_types.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39
40 #include "BKE_context.h"
41 #include "BKE_utildefines.h"
42
43 #include "WM_api.h"
44 #include "WM_types.h"
45
46 #include "wm_event_system.h"
47 #include "wm_subwindow.h"
48
49 #include "ED_screen.h"
50
51 #include "BIF_gl.h"
52 #include "BIF_glutil.h"
53
54
55 /* context checked on having screen, window and area */
56 wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type)
57 {
58         wmGesture *gesture= MEM_callocN(sizeof(wmGesture), "new gesture");
59         wmWindow *window= CTX_wm_window(C);
60         bScreen *screen= CTX_wm_screen(C);
61         int sx, sy;
62         
63         BLI_addtail(&window->gesture, gesture);
64         
65         gesture->type= type;
66         gesture->event_type= event->type;
67         gesture->swinid= screen->subwinactive;  /* means only in area-region context! */
68         
69         wm_subwindow_getorigin(window, gesture->swinid, &sx, &sy);
70         
71         if( ELEM4(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK, WM_GESTURE_CIRCLE)) {
72                 rcti *rect= MEM_callocN(sizeof(rcti), "gesture rect new");
73                 
74                 gesture->customdata= rect;
75                 rect->xmin= event->x - sx;
76                 rect->ymin= event->y - sy;
77                 if(type==WM_GESTURE_CIRCLE)
78                         rect->xmax= 25; // XXX temp
79                 else {
80                         rect->xmax= event->x - sx;
81                         rect->ymax= event->y - sy;
82                 }
83         }
84         
85         return gesture;
86 }
87
88 void WM_gesture_end(bContext *C, wmGesture *gesture)
89 {
90         BLI_remlink(&CTX_wm_window(C)->gesture, gesture);
91         MEM_freeN(gesture->customdata);
92         MEM_freeN(gesture);
93 }
94
95 /* for line, lasso, ... */
96 void wm_gesture_point_add(bContext *C, wmGesture *gesture)
97 {
98         
99 }
100
101 /* tweak and line gestures */
102 #define TWEAK_THRESHOLD         10
103 int wm_gesture_evaluate(bContext *C, wmGesture *gesture)
104 {
105         if(gesture->type==WM_GESTURE_TWEAK) {
106                 rcti *rect= gesture->customdata;
107                 int dx= rect->xmax - rect->xmin;
108                 int dy= rect->ymax - rect->ymin;
109                 if(ABS(dx)+ABS(dy) > TWEAK_THRESHOLD) {
110                         int theta= (int)floor(4.0f*atan2((float)dy, (float)dx)/M_PI + 0.5);
111                         int val= EVT_GESTURE_W;
112                         
113                         if(theta==0) val= EVT_GESTURE_E;
114                         else if(theta==1) val= EVT_GESTURE_NE;
115                         else if(theta==2) val= EVT_GESTURE_N;
116                         else if(theta==3) val= EVT_GESTURE_NW;
117                         else if(theta==-1) val= EVT_GESTURE_SE;
118                         else if(theta==-2) val= EVT_GESTURE_S;
119                         else if(theta==-3) val= EVT_GESTURE_SW;
120                         
121 #if 0
122                         /* debug */
123                         if(val==1) printf("tweak north\n");
124                         if(val==2) printf("tweak north-east\n");
125                         if(val==3) printf("tweak east\n");
126                         if(val==4) printf("tweak south-east\n");
127                         if(val==5) printf("tweak south\n");
128                         if(val==6) printf("tweak south-west\n");
129                         if(val==7) printf("tweak west\n");
130                         if(val==8) printf("tweak north-west\n");
131 #endif                  
132                         return val;
133                 }
134         }
135         return 0;
136 }
137
138
139 /* ******************* gesture draw ******************* */
140
141 static void wm_gesture_draw_rect(wmWindow *win, wmGesture *gt)
142 {
143         rcti *rect= (rcti *)gt->customdata;
144         
145         glEnable(GL_LINE_STIPPLE);
146         glColor3ub(0, 0, 0);
147         glLineStipple(1, 0xCCCC);
148         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
149         glColor3ub(255, 255, 255);
150         glLineStipple(1, 0x3333);
151         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
152         glDisable(GL_LINE_STIPPLE);
153 }
154
155 static void wm_gesture_draw_line(wmWindow *win, wmGesture *gt)
156 {
157         rcti *rect= (rcti *)gt->customdata;
158         
159         glEnable(GL_LINE_STIPPLE);
160         glColor3ub(0, 0, 0);
161         glLineStipple(1, 0xAAAA);
162         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
163         glColor3ub(255, 255, 255);
164         glLineStipple(1, 0x5555);
165         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
166
167         glDisable(GL_LINE_STIPPLE);
168         
169 }
170
171 static void wm_gesture_draw_circle(wmWindow *win, wmGesture *gt)
172 {
173         rcti *rect= (rcti *)gt->customdata;
174
175         glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f);
176
177         glEnable(GL_LINE_STIPPLE);
178         glColor3ub(0, 0, 0);
179         glLineStipple(1, 0xAAAA);
180         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
181         glColor3ub(255, 255, 255);
182         glLineStipple(1, 0x5555);
183         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
184         
185         glDisable(GL_LINE_STIPPLE);
186         glTranslatef((float)-rect->xmin, (float)-rect->ymin, 0.0f);
187         
188 }
189
190
191 static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
192 {
193         rcti *rect= (rcti *)gt->customdata;
194         
195         glEnable(GL_LINE_STIPPLE);
196         glColor3ub(0, 0, 0);
197         glLineStipple(1, 0xCCCC);
198         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
199         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
200         
201         glColor3ub(255, 255, 255);
202         glLineStipple(1, 0x3333);
203         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
204         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
205         glDisable(GL_LINE_STIPPLE);
206 }
207
208 /* called in wm_event_system.c */
209 void wm_gesture_draw(wmWindow *win)
210 {
211         wmGesture *gt= (wmGesture *)win->gesture.first;
212         
213         for(; gt; gt= gt->next) {
214                 /* all in subwindow space */
215                 wmSubWindowSet(win, gt->swinid);
216                 
217                 if(gt->type==WM_GESTURE_RECT)
218                         wm_gesture_draw_rect(win, gt);
219                 else if(gt->type==WM_GESTURE_TWEAK)
220                         wm_gesture_draw_line(win, gt);
221                 else if(gt->type==WM_GESTURE_CIRCLE)
222                         wm_gesture_draw_circle(win, gt);
223                 else if(gt->type==WM_GESTURE_CROSS_RECT) {
224                         if(gt->mode==1)
225                                 wm_gesture_draw_rect(win, gt);
226                         else
227                                 wm_gesture_draw_cross(win, gt);
228                 }
229         }
230 }
231
232 void wm_gesture_tag_redraw(bContext *C)
233 {
234         bScreen *screen= CTX_wm_screen(C);
235         ARegion *ar= CTX_wm_region(C);
236         
237         if(screen)
238                 screen->do_gesture= 1;
239         if(ar)
240                 ED_region_tag_redraw(ar);
241 }