2.5
[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_global.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 "BIF_gl.h"
50 #include "BIF_glutil.h"
51
52
53 /* context checked on having screen, window and area */
54 wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type)
55 {
56         wmGesture *gesture= MEM_callocN(sizeof(wmGesture), "new gesture");
57         int sx, sy;
58         
59         BLI_addtail(&C->window->gesture, gesture);
60         
61         gesture->type= type;
62         gesture->event_type= event->type;
63         gesture->swinid= C->screen->subwinactive;       /* means only in area-region context! */
64         
65         wm_subwindow_getorigin(C->window, gesture->swinid, &sx, &sy);
66         
67         if( ELEM3(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK)) {
68                 rcti *rect= MEM_callocN(sizeof(rcti), "gesture rect new");
69                 
70                 gesture->customdata= rect;
71                 rect->xmin= event->x - sx;
72                 rect->ymin= event->y - sy;
73                 rect->xmax= event->x - sx;
74                 rect->ymax= event->y - sy;
75         }
76         
77         return gesture;
78 }
79
80 void WM_gesture_end(bContext *C, wmGesture *gesture)
81 {
82         BLI_remlink(&C->window->gesture, gesture);
83         MEM_freeN(gesture->customdata);
84         MEM_freeN(gesture);
85 }
86
87 /* for line, lasso, ... */
88 void wm_gesture_point_add(bContext *C, wmGesture *gesture)
89 {
90         
91 }
92
93 /* tweak and line gestures */
94 #define TWEAK_THRESHOLD         10
95 int wm_gesture_evaluate(bContext *C, wmGesture *gesture)
96 {
97         if(gesture->type==WM_GESTURE_TWEAK) {
98                 rcti *rect= gesture->customdata;
99                 int dx= rect->xmax - rect->xmin;
100                 int dy= rect->ymax - rect->ymin;
101                 if(ABS(dx)+ABS(dy) > TWEAK_THRESHOLD) {
102                         int theta= (int)floor(4.0f*atan2((float)dy, (float)dx)/M_PI + 0.5);
103                         int val= EVT_GESTURE_W;
104                         
105                         if(theta==0) val= EVT_GESTURE_E;
106                         else if(theta==1) val= EVT_GESTURE_NE;
107                         else if(theta==2) val= EVT_GESTURE_N;
108                         else if(theta==3) val= EVT_GESTURE_NW;
109                         else if(theta==-1) val= EVT_GESTURE_SE;
110                         else if(theta==-2) val= EVT_GESTURE_S;
111                         else if(theta==-3) val= EVT_GESTURE_SW;
112                         
113 #if 0
114                         /* debug */
115                         if(val==1) printf("tweak north\n");
116                         if(val==2) printf("tweak north-east\n");
117                         if(val==3) printf("tweak east\n");
118                         if(val==4) printf("tweak south-east\n");
119                         if(val==5) printf("tweak south\n");
120                         if(val==6) printf("tweak south-west\n");
121                         if(val==7) printf("tweak west\n");
122                         if(val==8) printf("tweak north-west\n");
123 #endif                  
124                         return val;
125                 }
126         }
127         return 0;
128 }
129
130
131 /* ******************* gesture draw ******************* */
132
133 static void wm_gesture_draw_rect(wmWindow *win, wmGesture *gt)
134 {
135         rcti *rect= (rcti *)gt->customdata;
136         
137         glEnable(GL_LINE_STIPPLE);
138         glColor3ub(0, 0, 0);
139         glLineStipple(1, 0xCCCC);
140         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
141         glColor3ub(255, 255, 255);
142         glLineStipple(1, 0x3333);
143         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
144         glDisable(GL_LINE_STIPPLE);
145 }
146
147 static void wm_gesture_draw_line(wmWindow *win, wmGesture *gt)
148 {
149         rcti *rect= (rcti *)gt->customdata;
150         
151         glEnable(GL_LINE_STIPPLE);
152         glColor3ub(0, 0, 0);
153         glLineStipple(1, 0xAAAA);
154         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
155         glColor3ub(255, 255, 255);
156         glLineStipple(1, 0x5555);
157         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
158
159         glDisable(GL_LINE_STIPPLE);
160         
161 }
162
163 static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
164 {
165         rcti *rect= (rcti *)gt->customdata;
166         
167         glEnable(GL_LINE_STIPPLE);
168         glColor3ub(0, 0, 0);
169         glLineStipple(1, 0xCCCC);
170         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
171         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
172         
173         glColor3ub(255, 255, 255);
174         glLineStipple(1, 0x3333);
175         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
176         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
177         glDisable(GL_LINE_STIPPLE);
178 }
179
180 /* called in wm_event_system.c */
181 void wm_gesture_draw(wmWindow *win)
182 {
183         wmGesture *gt= (wmGesture *)win->gesture.first;
184         
185         for(; gt; gt= gt->next) {
186                 /* all in subwindow space */
187                 wm_subwindow_set(win, gt->swinid);
188                 
189                 if(gt->type==WM_GESTURE_RECT)
190                         wm_gesture_draw_rect(win, gt);
191                 else if(gt->type==WM_GESTURE_TWEAK)
192                         wm_gesture_draw_line(win, gt);
193                 else if(gt->type==WM_GESTURE_CROSS_RECT) {
194                         if(gt->mode==1)
195                                 wm_gesture_draw_rect(win, gt);
196                         else
197                                 wm_gesture_draw_cross(win, gt);
198                 }
199         }
200 }
201
202