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