First version of fields panel.
[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., 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_userdef_types.h"
35 #include "DNA_windowmanager_types.h"
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
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                         rect->xmax= 25; // XXX temp
81                 else {
82                         rect->xmax= event->x - sx;
83                         rect->ymax= event->y - sy;
84                 }
85         }
86         else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) {
87                 short *lasso;
88                 gesture->customdata= lasso= MEM_callocN(2*sizeof(short)*WM_LASSO_MAX_POINTS, "lasso points");
89                 lasso[0] = event->x - sx;
90                 lasso[1] = event->y - sy;
91                 gesture->points= 1;
92         }
93         
94         return gesture;
95 }
96
97 void WM_gesture_end(bContext *C, wmGesture *gesture)
98 {
99         BLI_remlink(&CTX_wm_window(C)->gesture, gesture);
100         MEM_freeN(gesture->customdata);
101         MEM_freeN(gesture);
102 }
103
104 /* tweak and line gestures */
105 #define TWEAK_THRESHOLD         10
106 int wm_gesture_evaluate(bContext *C, wmGesture *gesture)
107 {
108         if(gesture->type==WM_GESTURE_TWEAK) {
109                 rcti *rect= gesture->customdata;
110                 int dx= rect->xmax - rect->xmin;
111                 int dy= rect->ymax - rect->ymin;
112                 if(ABS(dx)+ABS(dy) > TWEAK_THRESHOLD) {
113                         int theta= (int)floor(4.0f*atan2((float)dy, (float)dx)/M_PI + 0.5);
114                         int val= EVT_GESTURE_W;
115                         
116                         if(theta==0) val= EVT_GESTURE_E;
117                         else if(theta==1) val= EVT_GESTURE_NE;
118                         else if(theta==2) val= EVT_GESTURE_N;
119                         else if(theta==3) val= EVT_GESTURE_NW;
120                         else if(theta==-1) val= EVT_GESTURE_SE;
121                         else if(theta==-2) val= EVT_GESTURE_S;
122                         else if(theta==-3) val= EVT_GESTURE_SW;
123                         
124 #if 0
125                         /* debug */
126                         if(val==1) printf("tweak north\n");
127                         if(val==2) printf("tweak north-east\n");
128                         if(val==3) printf("tweak east\n");
129                         if(val==4) printf("tweak south-east\n");
130                         if(val==5) printf("tweak south\n");
131                         if(val==6) printf("tweak south-west\n");
132                         if(val==7) printf("tweak west\n");
133                         if(val==8) printf("tweak north-west\n");
134 #endif                  
135                         return val;
136                 }
137         }
138         return 0;
139 }
140
141
142 /* ******************* gesture draw ******************* */
143
144 static void wm_gesture_draw_rect(wmWindow *win, wmGesture *gt)
145 {
146         rcti *rect= (rcti *)gt->customdata;
147         
148         glEnable(GL_LINE_STIPPLE);
149         glColor3ub(0, 0, 0);
150         glLineStipple(1, 0xCCCC);
151         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
152         glColor3ub(255, 255, 255);
153         glLineStipple(1, 0x3333);
154         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
155         glDisable(GL_LINE_STIPPLE);
156 }
157
158 static void wm_gesture_draw_line(wmWindow *win, wmGesture *gt)
159 {
160         rcti *rect= (rcti *)gt->customdata;
161         
162         glEnable(GL_LINE_STIPPLE);
163         glColor3ub(0, 0, 0);
164         glLineStipple(1, 0xAAAA);
165         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
166         glColor3ub(255, 255, 255);
167         glLineStipple(1, 0x5555);
168         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
169
170         glDisable(GL_LINE_STIPPLE);
171         
172 }
173
174 static void wm_gesture_draw_circle(wmWindow *win, wmGesture *gt)
175 {
176         rcti *rect= (rcti *)gt->customdata;
177
178         glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f);
179
180         glEnable(GL_LINE_STIPPLE);
181         glColor3ub(0, 0, 0);
182         glLineStipple(1, 0xAAAA);
183         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
184         glColor3ub(255, 255, 255);
185         glLineStipple(1, 0x5555);
186         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
187         
188         glDisable(GL_LINE_STIPPLE);
189         glTranslatef((float)-rect->xmin, (float)-rect->ymin, 0.0f);
190         
191 }
192
193 static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt)
194 {
195         short *lasso= (short *)gt->customdata;
196         int i;
197         
198         glEnable(GL_LINE_STIPPLE);
199         glColor3ub(0, 0, 0);
200         glLineStipple(1, 0xAAAA);
201         glBegin(GL_LINE_STRIP);
202         for(i=0; i<gt->points; i++, lasso+=2)
203                 glVertex2sv(lasso);
204         if(gt->type==WM_GESTURE_LASSO)
205                 glVertex2sv((short *)gt->customdata);
206         glEnd();
207         
208         glColor3ub(255, 255, 255);
209         glLineStipple(1, 0x5555);
210         glBegin(GL_LINE_STRIP);
211         lasso= (short *)gt->customdata;
212         for(i=0; i<gt->points; i++, lasso+=2)
213                 glVertex2sv(lasso);
214         if(gt->type==WM_GESTURE_LASSO)
215                 glVertex2sv((short *)gt->customdata);
216         glEnd();
217         
218         glDisable(GL_LINE_STIPPLE);
219         
220 }
221
222 static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
223 {
224         rcti *rect= (rcti *)gt->customdata;
225         
226         glEnable(GL_LINE_STIPPLE);
227         glColor3ub(0, 0, 0);
228         glLineStipple(1, 0xCCCC);
229         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
230         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
231         
232         glColor3ub(255, 255, 255);
233         glLineStipple(1, 0x3333);
234         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
235         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
236         glDisable(GL_LINE_STIPPLE);
237 }
238
239 /* called in wm_event_system.c */
240 void wm_gesture_draw(wmWindow *win)
241 {
242         wmGesture *gt= (wmGesture *)win->gesture.first;
243         
244         for(; gt; gt= gt->next) {
245                 /* all in subwindow space */
246                 wmSubWindowSet(win, gt->swinid);
247                 
248                 if(gt->type==WM_GESTURE_RECT)
249                         wm_gesture_draw_rect(win, gt);
250                 else if(gt->type==WM_GESTURE_TWEAK)
251                         wm_gesture_draw_line(win, gt);
252                 else if(gt->type==WM_GESTURE_CIRCLE)
253                         wm_gesture_draw_circle(win, gt);
254                 else if(gt->type==WM_GESTURE_CROSS_RECT) {
255                         if(gt->mode==1)
256                                 wm_gesture_draw_rect(win, gt);
257                         else
258                                 wm_gesture_draw_cross(win, gt);
259                 }
260                 else if(gt->type==WM_GESTURE_LINES) 
261                         wm_gesture_draw_lasso(win, gt);
262                 else if(gt->type==WM_GESTURE_LASSO) 
263                         wm_gesture_draw_lasso(win, gt);
264         }
265 }
266
267 void wm_gesture_tag_redraw(bContext *C)
268 {
269         wmWindow *win= CTX_wm_window(C);
270         bScreen *screen= CTX_wm_screen(C);
271         ARegion *ar= CTX_wm_region(C);
272         
273         if(screen)
274                 screen->do_draw_gesture= 1;
275         if(ar && win->drawmethod != USER_DRAW_TRIPLE)
276                 ED_region_tag_redraw(ar);
277 }
278