- replaced G.{edve,eded,edvl} with G.editMesh, atm just a structure to
[blender.git] / source / blender / src / editview.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * cursor/gestures/selecteren
32  */
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <math.h>
37 #include <string.h>
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #ifdef WIN32
44 #include "BLI_winstuff.h"
45 #endif
46
47 #include "IMB_imbuf.h"
48 #include "PIL_time.h"
49
50 #include "DNA_armature_types.h"
51 #include "DNA_meta_types.h"
52 #include "DNA_mesh_types.h"
53 #include "DNA_curve_types.h"
54 #include "DNA_lattice_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_screen_types.h"
58 #include "DNA_view3d_types.h"
59 #include "DNA_userdef_types.h"
60
61 #include "BLI_blenlib.h"
62 #include "BLI_arithb.h"
63 #include "BLI_editVert.h"
64
65 #include "BKE_utildefines.h"
66 #include "BKE_global.h"
67 #include "BKE_armature.h"
68 #include "BKE_lattice.h"
69
70 #include "BIF_gl.h"
71 #include "BIF_mywindow.h"
72 #include "BIF_space.h"
73 #include "BIF_screen.h"
74 #include "BIF_butspace.h"
75 #include "BIF_editgroup.h"
76 #include "BIF_editmesh.h"
77 #include "BIF_editoops.h"
78 #include "BIF_editsima.h"
79 #include "BIF_editview.h"
80 #include "BIF_glutil.h"
81 #include "BIF_editarmature.h"
82 #include "BIF_toolbox.h"
83
84 #include "BDR_editobject.h"     /* For headerprint */
85 #include "BDR_vpaint.h"
86 #include "BDR_editface.h"
87 #include "BDR_drawobject.h"
88 #include "BDR_editcurve.h"
89
90 #include "BSE_edit.h"
91 #include "BSE_view.h"           /* give_cursor() */
92 #include "BSE_editipo.h"
93 #include "BSE_drawview.h"
94 #include "BSE_editaction.h"
95
96 #include "blendef.h"
97 #include "mydevice.h"
98
99 extern ListBase editNurb; /* originally from exports.h, memory from editcurve.c*/
100 /* editmball.c */
101 extern ListBase editelems;
102
103
104
105 void arrows_move_cursor(unsigned short event)
106 {
107         short mval[2];
108
109         getmouseco_sc(mval);
110
111         if(event==UPARROWKEY) {
112                 warp_pointer(mval[0], mval[1]+1);
113         } else if(event==DOWNARROWKEY) {
114                 warp_pointer(mval[0], mval[1]-1);
115         } else if(event==LEFTARROWKEY) {
116                 warp_pointer(mval[0]-1, mval[1]);
117         } else if(event==RIGHTARROWKEY) {
118                 warp_pointer(mval[0]+1, mval[1]);
119         }
120 }
121
122 #define MOVES 50
123
124
125 static char interpret_move(short mcord[][2], int count)
126 {
127         float x1, x2, y1, y2, d1, d2, inp, sq, mouse[MOVES][2];
128         int i, j, dir = 0;
129         
130         if (count <= 10) return ('g');
131
132         /* from short to float (drawing is with shorts) */
133         for(j=0; j<count; j++) {
134                 mouse[j][0]= mcord[j][0];
135                 mouse[j][1]= mcord[j][1];
136         }
137         
138         /* new method:
139          * 
140          * starting from end points, calculate centre with maximum distance
141          * dependant at the angle s / g / r is defined
142          */
143         
144
145         /* filter */
146         
147         for( j = 3 ; j > 0; j--){
148                 x1 = mouse[1][0];
149                 y1 = mouse[1][1];
150                 for (i = 2; i < count; i++){
151                         x2 = mouse[i-1][0];
152                         y2 = mouse[i-1][1];
153                         mouse[i-1][0] = ((x1 + mouse[i][0]) /4.0) + (x2 / 2.0);
154                         mouse[i-1][1] = ((y1 + mouse[i][1]) /4.0) + (y2 / 2.0);
155                         x1 = x2;
156                         y1 = y2;
157                 }
158         }
159
160         /* make overview of directions */
161         for (i = 0; i <= count - 2; i++){
162                 x1 = mouse[i][0] - mouse[i + 1][0];
163                 y1 = mouse[i][1] - mouse[i + 1][1];
164
165                 if (x1 < -0.5){
166                         if (y1 < -0.5) dir |= 32;
167                         else if (y1 > 0.5) dir |= 128;
168                         else dir |= 64;
169                 } else if (x1 > 0.5){
170                         if (y1 < -0.5) dir |= 8;
171                         else if (y1 > 0.5) dir |= 2;
172                         else dir |= 4;
173                 } else{
174                         if (y1 < -0.5) dir |= 16;
175                         else if (y1 > 0.5) dir |= 1;
176                         else dir |= 0;
177                 }
178         }
179         
180         /* move all crosses to the right */
181         for (i = 7; i>=0 ; i--){
182                 if (dir & 128) dir = (dir << 1) + 1;
183                 else break;
184         }
185         dir &= 255;
186         for (i = 7; i>=0 ; i--){
187                 if ((dir & 1) == 0) dir >>= 1;
188                 else break;
189         }
190         
191         /* in theory: 1 direction: straight line
192      * multiple sequential directions: circle
193      * non-sequential, and 1 bit set in upper 4 bits: size
194      */
195         switch(dir){
196         case 1:
197                 return ('g');
198                 break;
199         case 3:
200         case 7:
201                 x1 = mouse[0][0] - mouse[count >> 1][0];
202                 y1 = mouse[0][1] - mouse[count >> 1][1];
203                 x2 = mouse[count >> 1][0] - mouse[count - 1][0];
204                 y2 = mouse[count >> 1][1] - mouse[count - 1][1];
205                 d1 = (x1 * x1) + (y1 * y1);
206                 d2 = (x2 * x2) + (y2 * y2);
207                 sq = sqrt(d1);
208                 x1 /= sq; 
209                 y1 /= sq;
210                 sq = sqrt(d2);
211                 x2 /= sq; 
212                 y2 /= sq;
213                 inp = (x1 * x2) + (y1 * y2);
214                 /*printf("%f\n", inp);*/
215                 if (inp > 0.9) return ('g');
216                 else return ('r');
217                 break;
218         case 15:
219         case 31:
220         case 63:
221         case 127:
222         case 255:
223                 return ('r');
224                 break;
225         default:
226                 /* for size at least one of the higher bits has to be set */
227                 if (dir < 16) return ('r');
228                 else return ('s');
229         }
230
231         return (0);
232 }
233
234 int gesture(void)
235 {
236         short mcords[MOVES][2];
237         int i= 1, end= 0, a;
238         unsigned short event=0;
239         short mval[2], val, timer=0;
240         
241         glDrawBuffer(GL_FRONT);
242         persp(0);       /*  ortho at pixel level */
243         
244         getmouseco_areawin(mval);
245         
246         mcords[0][0] = mval[0];
247         mcords[0][1] = mval[1];
248         
249         while(get_mbut()&L_MOUSE) {
250                 
251                 if(qtest()) event= extern_qread(&val);
252                 else if(i==1) {
253                         /* not drawing yet... check for toolbox */
254                         PIL_sleep_ms(10);
255                         timer++;
256                         if(timer>=10*U.tb_leftmouse) {
257                                 toolbox_n();
258                                 return 1;
259                         }
260                 }
261                 
262                 switch (event) {
263                 case MOUSEY:
264                         getmouseco_areawin(mval);
265                         if( abs(mval[0]-mcords[i-1][0])>3 || abs(mval[1]-mcords[i-1][1])>3 ) {
266                                 mcords[i][0] = mval[0];
267                                 mcords[i][1] = mval[1];
268                                 if(i) {
269                                         sdrawXORline(mcords[i-1][0], mcords[i-1][1], mcords[i][0], mcords[i][1]);
270                                         glFlush();
271                                 }
272                                 i++;
273                         }
274                         break;
275                 case MOUSEX:
276                         break;
277                 case LEFTMOUSE:
278                         break;
279                 default:
280                         if(event) end= 1;       /* blender returns 0 */
281                         break;
282                 }
283                 if (i == MOVES || end == 1) break;
284         }
285
286         for(a=1; a<i; a++) {
287                 sdrawXORline(mcords[a-1][0], mcords[a-1][1], mcords[a][0], mcords[a][1]);
288         }
289         
290         persp(1);
291         glDrawBuffer(GL_BACK);
292         
293         if (i > 2) {
294                 i = interpret_move(mcords, i);
295                 
296                 if(i) {
297                         if(curarea->spacetype==SPACE_IPO) transform_ipo(i);
298                         else if(curarea->spacetype==SPACE_IMAGE) transform_tface_uv(i);
299                         else if(curarea->spacetype==SPACE_OOPS) transform_oops('g');
300                         else transform(i);
301                 }
302                 
303                 return 1;
304         }
305         else return 0;
306 }
307
308 void mouse_cursor(void)
309 {
310         extern float zfac;      /* view.c */
311         float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3];
312         short mval[2], mx, my, lr_click=0;
313         
314         if(gesture()) return;
315         
316         getmouseco_areawin(mval);
317         
318         if(mval[0]!=G.vd->mx || mval[1]!=G.vd->my) {
319
320                 mx= mval[0];
321                 my= mval[1];
322                 
323                 fp= give_cursor();
324                 
325                 if(G.obedit && ((G.qual & LR_CTRLKEY) || get_mbut()&R_MOUSE )) lr_click= 1;
326                 VECCOPY(oldcurs, fp);
327                 
328                 project_short_noclip(fp, mval);
329
330                 initgrabz(fp[0], fp[1], fp[2]);
331                 
332                 if(mval[0]!=3200) {
333                         
334                         window_to_3d(dvec, mval[0]-mx, mval[1]-my);
335                         VecSubf(fp, fp, dvec);
336                         
337                 }
338                 else {
339
340                         dx= ((float)(mx-(curarea->winx/2)))*zfac/(curarea->winx/2);
341                         dy= ((float)(my-(curarea->winy/2)))*zfac/(curarea->winy/2);
342                         
343                         fz= G.vd->persmat[0][3]*fp[0]+ G.vd->persmat[1][3]*fp[1]+ G.vd->persmat[2][3]*fp[2]+ G.vd->persmat[3][3];
344                         fz= fz/zfac;
345                         
346                         fp[0]= (G.vd->persinv[0][0]*dx + G.vd->persinv[1][0]*dy+ G.vd->persinv[2][0]*fz)-G.vd->ofs[0];
347                         fp[1]= (G.vd->persinv[0][1]*dx + G.vd->persinv[1][1]*dy+ G.vd->persinv[2][1]*fz)-G.vd->ofs[1];
348                         fp[2]= (G.vd->persinv[0][2]*dx + G.vd->persinv[1][2]*dy+ G.vd->persinv[2][2]*fz)-G.vd->ofs[2];
349                 }
350                 
351                 allqueue(REDRAWVIEW3D, 1);
352         }
353         
354         if(lr_click) {
355                 if(G.obedit->type==OB_MESH) addvert_mesh();
356                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) addvert_Nurb(0);
357                 else if (G.obedit->type==OB_ARMATURE) addvert_armature();
358                 VECCOPY(fp, oldcurs);
359         }
360         
361 }
362
363 void deselectall(void)  /* is toggle */
364 {
365         Base *base;
366         int a=0;
367
368         base= FIRSTBASE;
369         while(base) {
370                 if TESTBASE(base) {
371                         a= 1;
372                         break;
373                 }
374                 base= base->next;
375         }
376         
377         base= FIRSTBASE;
378         while(base) {
379                 if(base->lay & G.vd->lay) {
380                         if(a) base->flag &= ~SELECT;
381                         else base->flag |= SELECT;
382                         base->object->flag= base->flag;
383                 }
384                 base= base->next;
385         }
386
387         allqueue(REDRAWVIEW3D, 0);
388         allqueue(REDRAWDATASELECT, 0);
389         allqueue(REDRAWNLA, 0);
390         
391         countall();
392
393 }
394
395 /* selects all objects of a particular type, on currently visible layers */
396 void selectall_type(short obtype) 
397 {
398         Base *base;
399         
400         base= FIRSTBASE;
401         while(base) {
402                 if((base->lay & G.vd->lay) && (base->object->type == obtype)) {
403                         base->flag |= SELECT;
404                         base->object->flag= base->flag;
405                 }
406                 base= base->next;
407         }
408
409         allqueue(REDRAWVIEW3D, 0);
410         allqueue(REDRAWDATASELECT, 0);
411         allqueue(REDRAWNLA, 0);
412         
413         countall();
414
415 }
416 /* selects all objects on a particular layer */
417 void selectall_layer(int layernum) 
418 {
419         Base *base;
420         
421         base= FIRSTBASE;
422         while(base) {
423                 if (base->lay == (1<< (layernum -1))) {
424                         base->flag |= SELECT;
425                         base->object->flag= base->flag;
426                 }
427                 base= base->next;
428         }
429
430         allqueue(REDRAWVIEW3D, 0);
431         allqueue(REDRAWDATASELECT, 0);
432         allqueue(REDRAWNLA, 0);
433         
434         countall();
435
436 }
437 static void deselectall_except(Base *b)   /* deselect all except b */
438 {
439         Base *base;
440
441         base= FIRSTBASE;
442         while(base) {
443                 if (base->flag & SELECT) {
444                         if(b!=base) {
445                                 base->flag &= ~SELECT;
446                                 base->object->flag= base->flag;
447                         }
448                 }
449                 base= base->next;
450         }
451 }
452
453 #if 0
454 /* smart function to sample a rect spiralling outside, nice for backbuf selection */
455 static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo)
456 {
457         Base *base;
458         unsigned int *bufmin,*bufmax;
459         int a,b,rc,tel,aantal,dirvec[4][2],maxob;
460         unsigned int retval=0;
461         
462         base= LASTBASE;
463         if(base==0) return 0;
464         maxob= base->selcol;
465
466         aantal= (size-1)/2;
467         rc= 0;
468
469         dirvec[0][0]= 1;
470         dirvec[0][1]= 0;
471         dirvec[1][0]= 0;
472         dirvec[1][1]= -size;
473         dirvec[2][0]= -1;
474         dirvec[2][1]= 0;
475         dirvec[3][0]= 0;
476         dirvec[3][1]= size;
477
478         bufmin= buf;
479         bufmax= buf+ size*size;
480         buf+= aantal*size+ aantal;
481
482         for(tel=1;tel<=size;tel++) {
483
484                 for(a=0;a<2;a++) {
485                         for(b=0;b<tel;b++) {
486
487                                 if(*buf && *buf<=maxob && *buf!=dontdo) return *buf;
488                                 if( *buf==dontdo ) retval= dontdo;      /* if only color dontdo is available, still return dontdo */
489                                 
490                                 buf+= (dirvec[rc][0]+dirvec[rc][1]);
491
492                                 if(buf<bufmin || buf>=bufmax) return retval;
493                         }
494                         rc++;
495                         rc &= 3;
496                 }
497         }
498         return retval;
499 }
500 #endif
501
502 #define SELECTSIZE      51
503
504 void set_active_base(Base *base)
505 {
506         
507         BASACT= base;
508         
509         /* signals to buttons */
510         redraw_test_buttons(base);
511
512         set_active_group();
513         
514         /* signal to ipo */
515
516         if (base) {
517                 allqueue(REDRAWIPO, base->object->ipowin);
518                 allqueue(REDRAWACTION, 0);
519                 allqueue(REDRAWNLA, 0);
520         }
521
522
523 }
524
525 void set_active_object(Object *ob)
526 {
527         Base *base;
528         
529         base= FIRSTBASE;
530         while(base) {
531                 if(base->object==ob) {
532                         set_active_base(base);
533                         return;
534                 }
535                 base= base->next;
536         }
537 }
538
539 void mouse_select(void)
540 {
541         Base *base, *startbase=NULL, *basact=NULL, *oldbasact=NULL;
542         unsigned int buffer[MAXPICKBUF];
543         int temp, a, dist=100;
544         short hits, mval[2];
545
546         /* always start list from basact */
547         startbase=  FIRSTBASE;
548         if(BASACT && BASACT->next) startbase= BASACT->next;
549
550         getmouseco_areawin(mval);
551
552         if(G.obedit==0 && (G.qual & LR_CTRLKEY)) {
553
554                 base= startbase;
555                 while(base) {
556                         
557                         if(base->lay & G.vd->lay) {
558                                 
559                                 project_short(base->object->obmat[3], &base->sx);
560                                 
561                                 temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]);
562                                 if(base==BASACT) temp+=10;
563                                 if(temp<dist ) {
564                                         basact= base;
565                                         dist= temp;
566                                 }
567                         }
568                         base= base->next;
569                         
570                         if(base==0) base= FIRSTBASE;
571                         if(base==startbase) break;
572                 }
573
574                 /* complete redraw when: */
575                 if(G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) allqueue(REDRAWVIEW3D, 0);
576                 
577         }
578         else {
579                 hits= selectprojektie(buffer, mval[0]-7, mval[1]-7, mval[0]+7, mval[1]+7);
580                 if(hits==0) hits= selectprojektie(buffer, mval[0]-21, mval[1]-21, mval[0]+21, mval[1]+21);
581
582                 if(hits>0) {
583
584                         base= startbase;
585                         while(base) {
586                                 if(base->lay & G.vd->lay) {
587                                         for(a=0; a<hits; a++) {
588                                                 /* index was converted */
589                                                 if(base->selcol==buffer[ (4 * a) + 3 ]) basact= base;
590                                         }
591                                 }
592                                 if(basact) break;
593                                 
594                                 base= base->next;
595                                 if(base==0) base= FIRSTBASE;
596                                 if(base==startbase) break;
597                         }
598                 }
599         }
600         
601         if(basact) {
602                 if(G.obedit) {
603                         /* only do select */
604                         deselectall_except(basact);
605                         basact->flag |= SELECT;
606                         draw_object_ext(basact);
607                 }
608                 else {
609                         oldbasact= BASACT;
610                         BASACT= basact;
611                         
612                         if((G.qual & LR_SHIFTKEY)==0) {
613                                 deselectall_except(basact);
614                                 basact->flag |= SELECT;
615                         }
616                         else {
617                                 if(basact->flag & SELECT) {
618                                         if(basact==oldbasact)
619                                                 basact->flag &= ~SELECT;
620                                 }
621                                 else basact->flag |= SELECT;
622                         }
623
624                         // copy
625                         basact->object->flag= basact->flag;
626                         
627                         if(oldbasact != basact) {
628                                 set_active_base(basact);
629                         }
630
631                         // for visual speed
632                         if(oldbasact && oldbasact != basact && (oldbasact->lay & G.vd->lay)) 
633                                 draw_object_ext(oldbasact);
634                         draw_object_ext(basact);
635
636                         if(basact->object->type!=OB_MESH) {
637                                 if(G.f & G_WEIGHTPAINT) {
638                                         set_wpaint();   /* toggle */
639                                 }
640                                 if(G.f & G_VERTEXPAINT) {
641                                         set_vpaint();   /* toggle */
642                                 }
643                                 if(G.f & G_FACESELECT) {
644                                         set_faceselect();       /* toggle */
645                                 }
646                         }
647                         /* also because multiple 3d windows can be open */
648                         allqueue(REDRAWVIEW3D, 0);
649
650                         allqueue(REDRAWBUTSLOGIC, 0);
651                         allqueue(REDRAWDATASELECT, 0);
652                         allqueue(REDRAWBUTSOBJECT, 0);
653                         allqueue(REDRAWACTION, 0);
654                         allqueue(REDRAWNLA, 0);
655                         allqueue(REDRAWHEADERS, 0);     /* To force display update for the posebutton */
656                 }
657                 
658         }
659
660         countall();
661
662         rightmouse_transform();
663 }
664
665 /* ------------------------------------------------------------------------- */
666 /**
667  * Does the 'borderselect' command. (Select verts based on selecting with a 
668  * border: key 'b'). All selecting seems to be done in the get_border part.
669  */
670 void borderselect(void)
671 {
672         EditMesh *em = G.editMesh;
673         rcti rect;
674         Base *base;
675         Nurb *nu;
676         BezTriple *bezt;
677         BPoint *bp;
678         MetaElem *ml;
679         struct EditVert *eve;
680         unsigned int buffer[MAXPICKBUF];
681         int a, index;
682         short hits, val, tel;
683
684         if(G.obedit==0 && (G.f & G_FACESELECT)) {
685                 face_borderselect();
686                 return;
687         }
688
689         val= get_border(&rect, 3);
690         if(val) {
691                 if (G.obpose){
692                         if(G.obpose->type==OB_ARMATURE) {
693                                 Bone    *bone;
694                                 hits= selectprojektie(buffer, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
695                                 base= FIRSTBASE;
696                                 for (a=0; a<hits; a++){
697                                         index = buffer[(4*a)+3];
698                                         if (val==LEFTMOUSE){
699                                                 if (index != -1){
700                                                         bone = get_indexed_bone(G.obpose->data, index &~(BONESEL_TIP|BONESEL_ROOT));
701                                                         bone->flag |= BONE_SELECTED;
702                                                         select_actionchannel_by_name(G.obpose->action, bone->name, 1);
703                                                 }
704                                         }
705                                         else{   
706                                                 if (index != -1){
707                                                         bone = get_indexed_bone(G.obpose->data, index &~(BONESEL_TIP|BONESEL_ROOT));
708                                                         bone->flag &= ~BONE_SELECTED;
709                                                         select_actionchannel_by_name(G.obpose->action, bone->name, 0);
710                                                 }
711                                         }
712                                 }
713                                 
714                                 allqueue(REDRAWBUTSEDIT, 0);
715                                 allqueue(REDRAWBUTSOBJECT, 0);
716                                 allqueue(REDRAWACTION, 0);
717                                 allqueue(REDRAWNLA, 0);
718                                 allqueue(REDRAWVIEW3D, 0);
719                         }
720                 }
721                 else
722                 if(G.obedit) {
723                         /* used to be a bigger test, also included sector and life */
724                         if(G.obedit->type==OB_MESH) {
725                                 
726                                 calc_meshverts_ext();   /* drawobject.c */
727                                 eve= em->verts.first;
728                                 while(eve) {            
729                                         if(eve->h==0 && eve->xs>rect.xmin && eve->xs<rect.xmax) {
730                                                 if(eve->ys>rect.ymin && eve->ys<rect.ymax) {
731                                                         if(val==LEFTMOUSE) eve->f|= 1;
732                                                         else eve->f&= 254;
733                                                 }
734                                         }
735                                         eve= eve->next;
736                                 }
737                                 allqueue(REDRAWVIEW3D, 0);
738                                 
739                         }
740                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
741                                 
742                                 calc_nurbverts_ext();   /* drawobject.c */
743                                 nu= editNurb.first;
744                                 while(nu) {
745                                         if((nu->type & 7)==CU_BEZIER) {
746                                                 bezt= nu->bezt;
747                                                 a= nu->pntsu;
748                                                 while(a--) {
749                                                         if(bezt->hide==0) {
750                                                                 if(bezt->s[0][0]>rect.xmin && bezt->s[0][0]<rect.xmax) {
751                                                                         if(bezt->s[0][1]>rect.ymin && bezt->s[0][1]<rect.ymax) {
752                                                                                 if(val==LEFTMOUSE) bezt->f1|= 1;
753                                                                                 else bezt->f1 &= ~1;
754                                                                         }
755                                                                 }
756                                                                 if(bezt->s[1][0]>rect.xmin && bezt->s[1][0]<rect.xmax) {
757                                                                         if(bezt->s[1][1]>rect.ymin && bezt->s[1][1]<rect.ymax) {
758                                                                                 if(val==LEFTMOUSE) {
759                                                                                         bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
760                                                                                 }
761                                                                                 else {
762                                                                                         bezt->f1 &= ~1; bezt->f2 &= ~1; bezt->f3 &= ~1;
763                                                                                 }
764                                                                         }
765                                                                 }
766                                                                 if(bezt->s[2][0]>rect.xmin && bezt->s[2][0]<rect.xmax) {
767                                                                         if(bezt->s[2][1]>rect.ymin && bezt->s[2][1]<rect.ymax) {
768                                                                                 if(val==LEFTMOUSE) bezt->f3|= 1;
769                                                                                 else bezt->f3 &= ~1;
770                                                                         }
771                                                                 }
772                                                         }
773                                                         bezt++;
774                                                 }
775                                         }
776                                         else {
777                                                 bp= nu->bp;
778                                                 a= nu->pntsu*nu->pntsv;
779                                                 while(a--) {
780                                                         if(bp->hide==0) {
781                                                                 if(bp->s[0]>rect.xmin && bp->s[0]<rect.xmax) {
782                                                                         if(bp->s[1]>rect.ymin && bp->s[1]<rect.ymax) {
783                                                                                 if(val==LEFTMOUSE) bp->f1|= 1;
784                                                                                 else bp->f1 &= ~1;
785                                                                         }
786                                                                 }
787                                                         }
788                                                         bp++;
789                                                 }
790                                         }
791                                         nu= nu->next;
792                                 }
793                                 allqueue(REDRAWVIEW3D, 0);
794                         }
795                         else if(G.obedit->type==OB_MBALL) {
796                                 hits= selectprojektie(buffer, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
797                                 
798                                 ml= editelems.first;
799                                 
800                                 while(ml) {
801                                         for(a=0; a<hits; a++) {
802                                                 if(ml->selcol==buffer[ (4 * a) + 3 ]) {
803                                                         if(val==LEFTMOUSE) ml->flag |= SELECT;
804                                                         else ml->flag &= ~SELECT;
805                                                         break;
806                                                 }
807                                         }
808                                         ml= ml->next;
809                                 }
810                                 allqueue(REDRAWVIEW3D, 0);
811                         }
812                         else if(G.obedit->type==OB_ARMATURE) {
813                                 EditBone *ebone;
814
815                                 hits= selectprojektie(buffer, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
816
817                                 base= FIRSTBASE;
818                                 for (a=0; a<hits; a++){
819                                         index = buffer[(4*a)+3];
820                                         if (val==LEFTMOUSE){
821                                                 if (index!=-1){
822                                                         ebone = BLI_findlink(&G.edbo, index & ~(BONESEL_TIP|BONESEL_ROOT));
823                                                         if (index & BONESEL_TIP)
824                                                                 ebone->flag |= BONE_TIPSEL;
825                                                         if (index & BONESEL_ROOT)
826                                                                 ebone->flag |= BONE_ROOTSEL;
827                                                 }
828                                         }
829                                         else{
830                                                 if (index!=-1){
831                                                         ebone = BLI_findlink(&G.edbo, index & ~(BONESEL_TIP|BONESEL_ROOT));
832                                                         if (index & BONESEL_TIP)
833                                                                 ebone->flag &= ~BONE_TIPSEL;
834                                                         if (index & BONESEL_ROOT)
835                                                                 ebone->flag &= ~BONE_ROOTSEL;
836                                                 }
837                                         }
838                                 }
839                                 
840                                 allqueue(REDRAWBUTSEDIT, 0);
841                                 allqueue(REDRAWBUTSOBJECT, 0);
842                                 allqueue(REDRAWACTION, 0);
843                                 allqueue(REDRAWVIEW3D, 0);
844                         }
845                         else if(G.obedit->type==OB_LATTICE) {
846                                 
847                                 calc_lattverts_ext();
848                                 
849                                 bp= editLatt->def;
850         
851                                 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
852                                 while(a--) {
853                                         if(bp->hide==0) {
854                                                 if(bp->s[0]>rect.xmin && bp->s[0]<rect.xmax) {
855                                                         if(bp->s[1]>rect.ymin && bp->s[1]<rect.ymax) {
856                                                                 if(val==LEFTMOUSE) bp->f1|= 1;
857                                                                 else bp->f1 &= ~1;
858                                                         }
859                                                 }
860                                         }
861                                         bp++;
862                                 }
863                                 allqueue(REDRAWVIEW3D, 0);
864                         }
865
866                 }
867                 else {
868                         
869                         hits= selectprojektie(buffer, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
870
871                         base= FIRSTBASE;
872                         while(base) {
873                                 if(base->lay & G.vd->lay) {
874                                         for(a=0; a<hits; a++) {
875                                                 /* converted index */
876                                                 if(base->selcol==buffer[ (4 * a) + 3 ]) {
877                                                         if(val==LEFTMOUSE) base->flag |= SELECT;
878                                                         else base->flag &= ~SELECT;
879                                                         base->object->flag= base->flag;
880
881                                                         draw_object_ext(base);
882                                                         break;
883                                                 }
884                                         }
885                                 }
886                                 
887                                 base= base->next;
888                         }
889                         /* frontbuffer flush */
890                         glFinish();
891                         
892                         allqueue(REDRAWDATASELECT, 0);
893                         
894                         /* because backbuf drawing */
895                         tel= 1;
896                         base= FIRSTBASE;
897                         while(base) {
898                                 /* each base because of multiple windows */
899                                 base->selcol = ((tel & 0xF00)<<12) 
900                                         + ((tel & 0xF0)<<8) 
901                                         + ((tel & 0xF)<<4);
902                                 tel++;
903                                 base= base->next;
904                         }
905                         /* new */
906                         allqueue(REDRAWBUTSLOGIC, 0);
907                         allqueue(REDRAWNLA, 0);
908                 }
909                 countall();
910                 
911                 allqueue(REDRAWINFO, 0);
912         }
913 } /* end of borderselect() */
914
915 /* ------------------------------------------------------------------------- */
916
917 /** The following functions are quick & dirty callback functions called
918   * on the Circle select function (press B twice in Editmode)
919   * They were torn out of the circle_select to make the latter more reusable
920   * The callback version of circle_select (called circle_selectCB) was moved
921   * to edit.c because of it's (wanted) generality.
922
923         XXX These callback functions are still dirty, because they call globals... 
924   */
925
926 void mesh_selectionCB(int selecting, Object *editobj, short *mval, float rad)
927 {
928         EditMesh *em = G.editMesh;
929         EditVert *eve;
930         float x, y, r;
931
932         calc_meshverts_ext();   /* drawobject.c */
933         eve= em->verts.first;
934         while(eve) {
935                 if(eve->h==0) {
936                         x= eve->xs-mval[0];
937                         y= eve->ys-mval[1];
938                         r= sqrt(x*x+y*y);
939                         if(r<=rad) {
940                                 if(selecting==LEFTMOUSE) eve->f|= 1;
941                                 else eve->f&= 254;
942                         }
943                 }
944                 eve= eve->next;
945         }
946
947         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
948         force_draw();
949
950 }
951
952
953 void nurbscurve_selectionCB(int selecting, Object *editobj, short *mval, float rad)
954 {
955         Nurb *nu;
956         BPoint *bp;
957         BezTriple *bezt;
958         float x, y, r;
959         int a;
960
961         calc_nurbverts_ext();   /* drawobject.c */
962         nu= editNurb.first;
963         while(nu) {
964                 if((nu->type & 7)==CU_BEZIER) {
965                         bezt= nu->bezt;
966                         a= nu->pntsu;
967                         while(a--) {
968                                 if(bezt->hide==0) {
969                                         x= bezt->s[0][0]-mval[0];
970                                         y= bezt->s[0][1]-mval[1];
971                                         r= sqrt(x*x+y*y);
972                                         if(r<=rad) {
973                                                 if(selecting==LEFTMOUSE) bezt->f1|= 1;
974                                                 else bezt->f1 &= ~1;
975                                         }
976                                         x= bezt->s[1][0]-mval[0];
977                                         y= bezt->s[1][1]-mval[1];
978                                         r= sqrt(x*x+y*y);
979                                         if(r<=rad) {
980                                                 if(selecting==LEFTMOUSE) bezt->f2|= 1;
981                                                 else bezt->f2 &= ~1;
982                                         }
983                                         x= bezt->s[2][0]-mval[0];
984                                         y= bezt->s[2][1]-mval[1];
985                                         r= sqrt(x*x+y*y);
986                                         if(r<=rad) {
987                                                 if(selecting==LEFTMOUSE) bezt->f3|= 1;
988                                                 else bezt->f3 &= ~1;
989                                         }
990                                         
991                                 }
992                                 bezt++;
993                         }
994                 }
995                 else {
996                         bp= nu->bp;
997                         a= nu->pntsu*nu->pntsv;
998                         while(a--) {
999                                 if(bp->hide==0) {
1000                                         x= bp->s[0]-mval[0];
1001                                         y= bp->s[1]-mval[1];
1002                                         r= sqrt(x*x+y*y);
1003                                         if(r<=rad) {
1004                                                 if(selecting==LEFTMOUSE) bp->f1|= 1;
1005                                                 else bp->f1 &= ~1;
1006                                         }
1007                                 }
1008                                 bp++;
1009                         }
1010                 }
1011                 nu= nu->next;
1012         }
1013         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
1014         force_draw();
1015
1016
1017 }
1018
1019 void lattice_selectionCB(int selecting, Object *editobj, short *mval, float rad)
1020 {
1021         BPoint *bp;
1022         float x, y, r;
1023         int a;
1024
1025         calc_lattverts_ext();
1026         
1027         bp= editLatt->def;
1028
1029         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1030         while(a--) {
1031                 if(bp->hide==0) {
1032                         x= bp->s[0]-mval[0];
1033                         y= bp->s[1]-mval[1];
1034                         r= sqrt(x*x+y*y);
1035                         if(r<=rad) {
1036                                 if(selecting==LEFTMOUSE) bp->f1|= 1;
1037                                 else bp->f1 &= ~1;
1038                         }
1039                 }
1040                 bp++;
1041         }
1042         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
1043         force_draw();
1044 }
1045
1046 /** Callbacks for selection in Editmode */
1047
1048 void obedit_selectionCB(short selecting, Object *editobj, short *mval, float rad) 
1049 {
1050         switch(editobj->type) {         
1051         case OB_MESH:
1052                 mesh_selectionCB(selecting, editobj, mval, rad);
1053                 break;
1054         case OB_CURVE:
1055         case OB_SURF:
1056                 nurbscurve_selectionCB(selecting, editobj, mval, rad);
1057                 break;
1058         case OB_LATTICE:
1059                 lattice_selectionCB(selecting, editobj, mval, rad);
1060                 break;
1061         }
1062 }
1063
1064 /** The circle select function - should be replaced by the callback 
1065   * version circle_selectCB(). Why ? Because it's not nice as it is!
1066   * 
1067   */
1068
1069 void circle_select(void)
1070 {
1071         EditMesh *em = G.editMesh;
1072         Nurb *nu;
1073         BPoint *bp;
1074         BezTriple *bezt;
1075         EditVert *eve;
1076         static float rad= 40.0;
1077         float rado, x, y, trad;
1078         int a, firsttime=1;
1079         unsigned short event;
1080         short mvalo[2], mval[2], val;
1081         short selecting=0;
1082         
1083         if(G.obedit==0) return;
1084         
1085         getmouseco_areawin(mvalo);
1086         draw_sel_circle(mvalo, 0, rad, 0.0, selecting);
1087         
1088         rado= rad;
1089         
1090         while(TRUE) {
1091                 
1092                 /* when a renderwindow is open and mouse enters it (activates sometimes) */
1093
1094                 mywinset(curarea->win);
1095
1096                 getmouseco_areawin(mval);
1097                 
1098                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || rado!=rad || firsttime) {
1099                         firsttime= 0;
1100                         
1101                         draw_sel_circle(mval, mvalo, rad, rado, selecting);
1102                 
1103                         mvalo[0]= mval[0];
1104                         mvalo[1]= mval[1];
1105                         rado= rad;
1106
1107                         if(selecting) {
1108                                 
1109                                 if(G.obedit->type==OB_MESH) {
1110                                         
1111                                         calc_meshverts_ext();   /* drawobject.c */
1112                                         eve= em->verts.first;
1113                                         while(eve) {
1114                                                 if(eve->h==0) {
1115                                                         x= eve->xs-mval[0];
1116                                                         y= eve->ys-mval[1];
1117                                                         trad= sqrt(x*x+y*y);
1118                                                         if(trad<=rad) {
1119                                                                 if(selecting==LEFTMOUSE) eve->f|= 1;
1120                                                                 else eve->f&= 254;
1121                                                         }
1122                                                 }
1123                                                 eve= eve->next;
1124                                         }
1125                                         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
1126                                         force_draw();
1127                                 }
1128                                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1129                                         
1130                                         calc_nurbverts_ext();   /* drawobject.c */
1131                                         nu= editNurb.first;
1132                                         while(nu) {
1133                                                 if((nu->type & 7)==CU_BEZIER) {
1134                                                         bezt= nu->bezt;
1135                                                         a= nu->pntsu;
1136                                                         while(a--) {
1137                                                                 if(bezt->hide==0) {
1138                                                                         x= bezt->s[0][0]-mval[0];
1139                                                                         y= bezt->s[0][1]-mval[1];
1140                                                                         trad= sqrt(x*x+y*y);
1141                                                                         if(trad<=rad) {
1142                                                                                 if(selecting==LEFTMOUSE) bezt->f1|= 1;
1143                                                                                 else bezt->f1 &= ~1;
1144                                                                         }
1145                                                                         x= bezt->s[1][0]-mval[0];
1146                                                                         y= bezt->s[1][1]-mval[1];
1147                                                                         trad= sqrt(x*x+y*y);
1148                                                                         if(trad<=rad) {
1149                                                                                 if(selecting==LEFTMOUSE) bezt->f2|= 1;
1150                                                                                 else bezt->f2 &= ~1;
1151                                                                         }
1152                                                                         x= bezt->s[2][0]-mval[0];
1153                                                                         y= bezt->s[2][1]-mval[1];
1154                                                                         trad= sqrt(x*x+y*y);
1155                                                                         if(trad<=rad) {
1156                                                                                 if(selecting==LEFTMOUSE) bezt->f3|= 1;
1157                                                                                 else bezt->f3 &= ~1;
1158                                                                         }
1159                                                                         
1160                                                                 }
1161                                                                 bezt++;
1162                                                         }
1163                                                 }
1164                                                 else {
1165                                                         bp= nu->bp;
1166                                                         a= nu->pntsu*nu->pntsv;
1167                                                         while(a--) {
1168                                                                 if(bp->hide==0) {
1169                                                                         x= bp->s[0]-mval[0];
1170                                                                         y= bp->s[1]-mval[1];
1171                                                                         trad= sqrt(x*x+y*y);
1172                                                                         if(trad<=rad) {
1173                                                                                 if(selecting==LEFTMOUSE) bp->f1|= 1;
1174                                                                                 else bp->f1 &= ~1;
1175                                                                         }
1176                                                                 }
1177                                                                 bp++;
1178                                                         }
1179                                                 }
1180                                                 nu= nu->next;
1181                                         }
1182                                         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
1183                                         force_draw();
1184                                 }
1185                                 else if(G.obedit->type==OB_LATTICE) {
1186                                         calc_lattverts_ext();
1187                                         
1188                                         bp= editLatt->def;
1189                 
1190                                         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1191                                         while(a--) {
1192                                                 if(bp->hide==0) {
1193                                                         x= bp->s[0]-mval[0];
1194                                                         y= bp->s[1]-mval[1];
1195                                                         trad= sqrt(x*x+y*y);
1196                                                         if(trad<=rad) {
1197                                                                 if(selecting==LEFTMOUSE) bp->f1|= 1;
1198                                                                 else bp->f1 &= ~1;
1199                                                         }
1200                                                 }
1201                                                 bp++;
1202                                         }
1203                                         draw_sel_circle(0, 0, 0, 0, 0); /* signal */
1204                                         force_draw();
1205                                 }
1206                         }
1207                 }
1208
1209                 event= extern_qread(&val);
1210                 if (event) {
1211                         int afbreek= 0;
1212                         
1213                         switch(event) {
1214                         case LEFTMOUSE:
1215                         case MIDDLEMOUSE:
1216                                 if(val) selecting= event;
1217                                 else selecting= 0;
1218                                 firsttime= 1;
1219                                 
1220                                 break;
1221                         case PADPLUSKEY:
1222                                 if(val) if(rad<200.0) rad*= 1.2;
1223                                 break;
1224                         case PADMINUS:
1225                                 if(val) if(rad>5.0) rad/= 1.2;
1226                                 break;
1227                         
1228                         case ESCKEY: case SPACEKEY: case RIGHTMOUSE:
1229                         case GKEY: case SKEY: case RKEY: case XKEY: case EKEY: case TABKEY:
1230                                 afbreek= 1;
1231                                 break;
1232
1233                         }
1234                         
1235                         if(afbreek) break;
1236                 }
1237         }
1238         
1239         /* clear circle */
1240         draw_sel_circle(0, mvalo, 0, rad, 1);
1241
1242         countall();
1243         allqueue(REDRAWINFO, 0);
1244 }
1245
1246 void set_render_border(void)
1247 {
1248         rcti rect;
1249         short val;
1250
1251         if(G.vd->persp!=2) return;
1252         
1253         val= get_border(&rect, 2);
1254         if(val) {
1255                 rcti vb;
1256
1257                 calc_viewborder(G.vd, &vb);
1258
1259                 G.scene->r.border.xmin= (float) (rect.xmin-vb.xmin)/(vb.xmax-vb.xmin);
1260                 G.scene->r.border.ymin= (float) (rect.ymin-vb.ymin)/(vb.ymax-vb.ymin);
1261                 G.scene->r.border.xmax= (float) (rect.xmax-vb.xmin)/(vb.xmax-vb.xmin);
1262                 G.scene->r.border.ymax= (float) (rect.ymax-vb.ymin)/(vb.ymax-vb.ymin);
1263                 
1264                 CLAMP(G.scene->r.border.xmin, 0.0, 1.0);
1265                 CLAMP(G.scene->r.border.ymin, 0.0, 1.0);
1266                 CLAMP(G.scene->r.border.xmax, 0.0, 1.0);
1267                 CLAMP(G.scene->r.border.ymax, 0.0, 1.0);
1268                 
1269                 allqueue(REDRAWVIEWCAM, 1);
1270                 // if it was not set, we do this
1271                 G.scene->r.mode |= R_BORDER;
1272                 allqueue(REDRAWBUTSSCENE, 1);
1273         }
1274 }
1275
1276
1277
1278 void fly(void)
1279 {
1280         float speed=0.0, speedo=1.0, zspeed=0.0, dvec[3], *quat, mat[3][3];
1281         float oldvec[3], oldrot[3];
1282         int loop=1;
1283         unsigned short toets;
1284         short val, cent[2];
1285         short mval[2];
1286         
1287         if(curarea->spacetype!=SPACE_VIEW3D) return;
1288         if(G.vd->camera == 0) return;
1289         if(G.vd->persp<2) return;
1290         
1291         VECCOPY(oldvec, G.vd->camera->loc);
1292         VECCOPY(oldrot, G.vd->camera->rot);
1293         
1294         cent[0]= curarea->winrct.xmin+(curarea->winx)/2;
1295         cent[1]= curarea->winrct.ymin+(curarea->winy)/2;
1296         
1297         warp_pointer(cent[0], cent[1]);
1298         
1299         cent[0]=  (curarea->winx)/2;
1300         cent[1]=  (curarea->winy)/2;
1301         
1302         headerprint("Fly");
1303         
1304         while(loop) {
1305                 getmouseco_areawin(mval);
1306
1307                 while(qtest()) {
1308                         
1309                         toets= extern_qread(&val);
1310                         
1311                         if(val) {
1312                                 if(toets==ESCKEY) {
1313                                         VECCOPY(G.vd->camera->loc, oldvec);
1314                                         VECCOPY(G.vd->camera->rot, oldrot);
1315                                         loop= 0;
1316                                         break;
1317                                 }
1318                                 else if(toets==SPACEKEY) {
1319                                         loop= 0;
1320                                         break;
1321                                 }
1322                                 else if(toets==LEFTMOUSE) {
1323                                         speed+= G.vd->grid/75.0;
1324                                         if(get_mbut()&M_MOUSE) speed= 0.0;
1325                                 }
1326                                 else if(toets==MIDDLEMOUSE) {
1327                                         speed-= G.vd->grid/75.0;
1328                                         if(get_mbut()&L_MOUSE) speed= 0.0;
1329                                 }
1330                         }
1331                 }
1332                 if(loop==0) break;
1333                 
1334                 /* define dvec */
1335                 val= mval[0]-cent[0];
1336                 if(val>20) val-= 20; else if(val< -20) val+= 20; else val= 0;
1337                 dvec[0]= 0.000001*val*val;
1338                 if(val>0) dvec[0]= -dvec[0];
1339                 
1340                 val= mval[1]-cent[1];
1341                 if(val>20) val-= 20; else if(val< -20) val+= 20; else val= 0;
1342                 dvec[1]= 0.000001*val*val;
1343                 if(val>0) dvec[1]= -dvec[1];
1344                 
1345                 dvec[2]= 1.0;
1346                 
1347                 zspeed= 0.0;
1348                 if(get_qual()&LR_CTRLKEY) zspeed= -G.vd->grid/25.0;
1349                 if(get_qual()&LR_ALTKEY) zspeed= G.vd->grid/25.0;
1350                 
1351                 if(speedo!=0.0 || zspeed!=0.0 || dvec[0]!=0.0 || dvec[1]!=0.0) {
1352                 
1353                         Normalise(dvec);
1354                         
1355                         Mat3CpyMat4(mat, G.vd->viewinv);
1356                         Mat3MulVecfl(mat, dvec);
1357                         quat= vectoquat(dvec, 5, 1);    /* track and upflag, not from the base: camera view calculation does not use that */
1358                         
1359                         QuatToEul(quat, G.vd->camera->rot);
1360                         
1361                         compatible_eul(G.vd->camera->rot, oldrot);
1362                         
1363                         VecMulf(dvec, speed);
1364                         G.vd->camera->loc[0]-= dvec[0];
1365                         G.vd->camera->loc[1]-= dvec[1];
1366                         G.vd->camera->loc[2]-= (dvec[2]-zspeed);
1367                         
1368                         scrarea_do_windraw(curarea);
1369                         screen_swapbuffers();
1370                 }
1371                 speedo= speed;
1372         }
1373         
1374         allqueue(REDRAWVIEW3D, 0);
1375         scrarea_queue_headredraw(curarea);
1376         
1377 }
1378