Blender  V2.59
wm_gesture.c
Go to the documentation of this file.
00001 /*
00002  * $Id: wm_gesture.c 35953 2011-04-02 02:08:33Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2008 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  *
00024  * Contributor(s): Blender Foundation
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include "DNA_screen_types.h"
00035 #include "DNA_vec_types.h"
00036 #include "DNA_userdef_types.h"
00037 #include "DNA_windowmanager_types.h"
00038 
00039 #include "MEM_guardedalloc.h"
00040 
00041 #include "BLI_blenlib.h"
00042 #include "BLI_editVert.h"       /* lasso tessellation */
00043 #include "BLI_math.h"
00044 #include "BLI_scanfill.h"       /* lasso tessellation */
00045 #include "BLI_utildefines.h"
00046 
00047 #include "BKE_context.h"
00048 
00049 
00050 #include "WM_api.h"
00051 #include "WM_types.h"
00052 
00053 #include "wm.h"
00054 #include "wm_event_system.h"
00055 #include "wm_subwindow.h"
00056 #include "wm_draw.h"
00057 
00058 
00059 #include "BIF_gl.h"
00060 #include "BIF_glutil.h"
00061 
00062 
00063 /* context checked on having screen, window and area */
00064 wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type)
00065 {
00066         wmGesture *gesture= MEM_callocN(sizeof(wmGesture), "new gesture");
00067         wmWindow *window= CTX_wm_window(C);
00068         ARegion *ar= CTX_wm_region(C);
00069         int sx, sy;
00070         
00071         BLI_addtail(&window->gesture, gesture);
00072         
00073         gesture->type= type;
00074         gesture->event_type= event->type;
00075         gesture->swinid= ar->swinid;    /* means only in area-region context! */
00076         
00077         wm_subwindow_getorigin(window, gesture->swinid, &sx, &sy);
00078         
00079         if( ELEM5(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK, WM_GESTURE_CIRCLE, WM_GESTURE_STRAIGHTLINE)) {
00080                 rcti *rect= MEM_callocN(sizeof(rcti), "gesture rect new");
00081                 
00082                 gesture->customdata= rect;
00083                 rect->xmin= event->x - sx;
00084                 rect->ymin= event->y - sy;
00085                 if(type==WM_GESTURE_CIRCLE) {
00086 #ifdef GESTURE_MEMORY
00087                         rect->xmax= circle_select_size;
00088 #else
00089                         rect->xmax= 25; // XXX temp
00090 #endif
00091                 } else {
00092                         rect->xmax= event->x - sx;
00093                         rect->ymax= event->y - sy;
00094                 }
00095         }
00096         else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) {
00097                 short *lasso;
00098                 gesture->customdata= lasso= MEM_callocN(2*sizeof(short)*WM_LASSO_MIN_POINTS, "lasso points");
00099                 lasso[0] = event->x - sx;
00100                 lasso[1] = event->y - sy;
00101                 gesture->points= 1;
00102                 gesture->size = WM_LASSO_MIN_POINTS;
00103         }
00104         
00105         return gesture;
00106 }
00107 
00108 void WM_gesture_end(bContext *C, wmGesture *gesture)
00109 {
00110         wmWindow *win= CTX_wm_window(C);
00111         
00112         if(win->tweak==gesture)
00113                 win->tweak= NULL;
00114         BLI_remlink(&win->gesture, gesture);
00115         MEM_freeN(gesture->customdata);
00116         MEM_freeN(gesture);
00117 }
00118 
00119 void WM_gestures_remove(bContext *C)
00120 {
00121         wmWindow *win= CTX_wm_window(C);
00122         
00123         while(win->gesture.first)
00124                 WM_gesture_end(C, win->gesture.first);
00125 }
00126 
00127 
00128 /* tweak and line gestures */
00129 #define TWEAK_THRESHOLD         10
00130 int wm_gesture_evaluate(wmGesture *gesture)
00131 {
00132         if(gesture->type==WM_GESTURE_TWEAK) {
00133                 rcti *rect= gesture->customdata;
00134                 int dx= rect->xmax - rect->xmin;
00135                 int dy= rect->ymax - rect->ymin;
00136                 if(ABS(dx)+ABS(dy) > TWEAK_THRESHOLD) {
00137                         int theta= (int)floor(4.0f*atan2f((float)dy, (float)dx)/(float)M_PI + 0.5f);
00138                         int val= EVT_GESTURE_W;
00139                         
00140                         if(theta==0) val= EVT_GESTURE_E;
00141                         else if(theta==1) val= EVT_GESTURE_NE;
00142                         else if(theta==2) val= EVT_GESTURE_N;
00143                         else if(theta==3) val= EVT_GESTURE_NW;
00144                         else if(theta==-1) val= EVT_GESTURE_SE;
00145                         else if(theta==-2) val= EVT_GESTURE_S;
00146                         else if(theta==-3) val= EVT_GESTURE_SW;
00147                         
00148 #if 0
00149                         /* debug */
00150                         if(val==1) printf("tweak north\n");
00151                         if(val==2) printf("tweak north-east\n");
00152                         if(val==3) printf("tweak east\n");
00153                         if(val==4) printf("tweak south-east\n");
00154                         if(val==5) printf("tweak south\n");
00155                         if(val==6) printf("tweak south-west\n");
00156                         if(val==7) printf("tweak west\n");
00157                         if(val==8) printf("tweak north-west\n");
00158 #endif                  
00159                         return val;
00160                 }
00161         }
00162         return 0;
00163 }
00164 
00165 
00166 /* ******************* gesture draw ******************* */
00167 
00168 static void wm_gesture_draw_rect(wmGesture *gt)
00169 {
00170         rcti *rect= (rcti *)gt->customdata;
00171         
00172         glEnable(GL_BLEND);
00173         glColor4f(1.0, 1.0, 1.0, 0.05);
00174         glBegin(GL_QUADS);
00175         glVertex2s(rect->xmax, rect->ymin);
00176         glVertex2s(rect->xmax, rect->ymax);
00177         glVertex2s(rect->xmin, rect->ymax);
00178         glVertex2s(rect->xmin, rect->ymin);
00179         glEnd();
00180         glDisable(GL_BLEND);
00181         
00182         glEnable(GL_LINE_STIPPLE);
00183         glColor3ub(96, 96, 96);
00184         glLineStipple(1, 0xCCCC);
00185         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
00186         glColor3ub(255, 255, 255);
00187         glLineStipple(1, 0x3333);
00188         sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
00189         glDisable(GL_LINE_STIPPLE);
00190 }
00191 
00192 static void wm_gesture_draw_line(wmGesture *gt)
00193 {
00194         rcti *rect= (rcti *)gt->customdata;
00195         
00196         glEnable(GL_LINE_STIPPLE);
00197         glColor3ub(96, 96, 96);
00198         glLineStipple(1, 0xAAAA);
00199         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
00200         glColor3ub(255, 255, 255);
00201         glLineStipple(1, 0x5555);
00202         sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
00203 
00204         glDisable(GL_LINE_STIPPLE);
00205         
00206 }
00207 
00208 static void wm_gesture_draw_circle(wmGesture *gt)
00209 {
00210         rcti *rect= (rcti *)gt->customdata;
00211 
00212         glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f);
00213 
00214         glEnable(GL_BLEND);
00215         glColor4f(1.0, 1.0, 1.0, 0.05);
00216         glutil_draw_filled_arc(0.0, M_PI*2.0, rect->xmax, 40);
00217         glDisable(GL_BLEND);
00218         
00219         glEnable(GL_LINE_STIPPLE);
00220         glColor3ub(96, 96, 96);
00221         glLineStipple(1, 0xAAAA);
00222         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
00223         glColor3ub(255, 255, 255);
00224         glLineStipple(1, 0x5555);
00225         glutil_draw_lined_arc(0.0, M_PI*2.0, rect->xmax, 40);
00226         
00227         glDisable(GL_LINE_STIPPLE);
00228         glTranslatef((float)-rect->xmin, (float)-rect->ymin, 0.0f);
00229         
00230 }
00231 
00232 static void draw_filled_lasso(wmGesture *gt)
00233 {
00234         EditVert *v=NULL, *lastv=NULL, *firstv=NULL;
00235         EditEdge *e;
00236         EditFace *efa;
00237         short *lasso= (short *)gt->customdata;
00238         int i;
00239         
00240         for (i=0; i<gt->points; i++, lasso+=2) {
00241                 float co[3];
00242 
00243                 co[0]= (float)lasso[0];
00244                 co[1]= (float)lasso[1];
00245                 co[2]= 0.0f;
00246 
00247                 v = BLI_addfillvert(co);
00248                 if (lastv)
00249                         e = BLI_addfilledge(lastv, v);
00250                 lastv = v;
00251                 if (firstv==NULL) firstv = v;
00252         }
00253         
00254         /* highly unlikely this will fail, but could crash if (gt->points == 0) */
00255         if(firstv) {
00256                 BLI_addfilledge(firstv, v);
00257                 BLI_edgefill(0);
00258         
00259                 glEnable(GL_BLEND);
00260                 glColor4f(1.0, 1.0, 1.0, 0.05);
00261                 glBegin(GL_TRIANGLES);
00262                 for (efa = fillfacebase.first; efa; efa=efa->next) {
00263                         glVertex2f(efa->v1->co[0], efa->v1->co[1]);
00264                         glVertex2f(efa->v2->co[0], efa->v2->co[1]);
00265                         glVertex2f(efa->v3->co[0], efa->v3->co[1]);
00266                 }
00267                 glEnd();
00268                 glDisable(GL_BLEND);
00269         
00270                 BLI_end_edgefill();
00271         }
00272 }
00273 
00274 static void wm_gesture_draw_lasso(wmGesture *gt)
00275 {
00276         short *lasso= (short *)gt->customdata;
00277         int i;
00278 
00279         draw_filled_lasso(gt);
00280         
00281         glEnable(GL_LINE_STIPPLE);
00282         glColor3ub(96, 96, 96);
00283         glLineStipple(1, 0xAAAA);
00284         glBegin(GL_LINE_STRIP);
00285         for(i=0; i<gt->points; i++, lasso+=2)
00286                 glVertex2sv(lasso);
00287         if(gt->type==WM_GESTURE_LASSO)
00288                 glVertex2sv((short *)gt->customdata);
00289         glEnd();
00290         
00291         glColor3ub(255, 255, 255);
00292         glLineStipple(1, 0x5555);
00293         glBegin(GL_LINE_STRIP);
00294         lasso= (short *)gt->customdata;
00295         for(i=0; i<gt->points; i++, lasso+=2)
00296                 glVertex2sv(lasso);
00297         if(gt->type==WM_GESTURE_LASSO)
00298                 glVertex2sv((short *)gt->customdata);
00299         glEnd();
00300         
00301         glDisable(GL_LINE_STIPPLE);
00302         
00303 }
00304 
00305 static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
00306 {
00307         rcti *rect= (rcti *)gt->customdata;
00308         
00309         glEnable(GL_LINE_STIPPLE);
00310         glColor3ub(96, 96, 96);
00311         glLineStipple(1, 0xCCCC);
00312         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
00313         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
00314         
00315         glColor3ub(255, 255, 255);
00316         glLineStipple(1, 0x3333);
00317         sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
00318         sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
00319         glDisable(GL_LINE_STIPPLE);
00320 }
00321 
00322 /* called in wm_draw.c */
00323 void wm_gesture_draw(wmWindow *win)
00324 {
00325         wmGesture *gt= (wmGesture *)win->gesture.first;
00326         
00327         for(; gt; gt= gt->next) {
00328                 /* all in subwindow space */
00329                 wmSubWindowSet(win, gt->swinid);
00330                 
00331                 if(gt->type==WM_GESTURE_RECT)
00332                         wm_gesture_draw_rect(gt);
00333 //              else if(gt->type==WM_GESTURE_TWEAK)
00334 //                      wm_gesture_draw_line(gt);
00335                 else if(gt->type==WM_GESTURE_CIRCLE)
00336                         wm_gesture_draw_circle(gt);
00337                 else if(gt->type==WM_GESTURE_CROSS_RECT) {
00338                         if(gt->mode==1)
00339                                 wm_gesture_draw_rect(gt);
00340                         else
00341                                 wm_gesture_draw_cross(win, gt);
00342                 }
00343                 else if(gt->type==WM_GESTURE_LINES) 
00344                         wm_gesture_draw_lasso(gt);
00345                 else if(gt->type==WM_GESTURE_LASSO) 
00346                         wm_gesture_draw_lasso(gt);
00347                 else if(gt->type==WM_GESTURE_STRAIGHTLINE)
00348                         wm_gesture_draw_line(gt);
00349         }
00350 }
00351 
00352 void wm_gesture_tag_redraw(bContext *C)
00353 {
00354         wmWindow *win= CTX_wm_window(C);
00355         bScreen *screen= CTX_wm_screen(C);
00356         ARegion *ar= CTX_wm_region(C);
00357         
00358         if(screen)
00359                 screen->do_draw_gesture= 1;
00360 
00361         wm_tag_redraw_overlay(win, ar);
00362 }