svn merge -r 22423:22450 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[blender.git] / source / blender / editors / space_view3d / view3d_draw.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <math.h>
32
33 #include "DNA_action_types.h"
34 #include "DNA_armature_types.h"
35 #include "DNA_camera_types.h"
36 #include "DNA_customdata_types.h"
37 #include "DNA_group_types.h"
38 #include "DNA_key_types.h"
39 #include "DNA_lamp_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_userdef_types.h"
45 #include "DNA_view3d_types.h"
46 #include "DNA_world_types.h"
47
48 #include "MEM_guardedalloc.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52 #include "BLI_rand.h"
53
54 #include "BKE_anim.h"
55 #include "BKE_context.h"
56 #include "BKE_customdata.h"
57 #include "BKE_image.h"
58 #include "BKE_ipo.h"
59 #include "BKE_key.h"
60 #include "BKE_object.h"
61 #include "BKE_global.h"
62 #include "BKE_scene.h"
63 #include "BKE_screen.h"
64 #include "BKE_utildefines.h"
65 #include "BKE_unit.h"
66
67 #include "RE_pipeline.h"        // make_stars
68
69 #include "IMB_imbuf_types.h"
70 #include "IMB_imbuf.h"
71
72 #include "BIF_gl.h"
73 #include "BIF_glutil.h"
74
75 #include "WM_api.h"
76 #include "BLF_api.h"
77
78 #include "ED_armature.h"
79 #include "ED_keyframing.h"
80 #include "ED_mesh.h"
81 #include "ED_screen.h"
82 #include "ED_space_api.h"
83 #include "ED_util.h"
84 #include "ED_transform.h"
85 #include "ED_types.h"
86
87 #include "UI_interface.h"
88 #include "UI_interface_icons.h"
89 #include "UI_resources.h"
90 #include "UI_view2d.h"
91
92 #include "GPU_draw.h"
93 #include "GPU_material.h"
94
95 #include "view3d_intern.h"      // own include
96
97
98
99 static void star_stuff_init_func(void)
100 {
101         cpack(-1);
102         glPointSize(1.0);
103         glBegin(GL_POINTS);
104 }
105 static void star_stuff_vertex_func(float* i)
106 {
107         glVertex3fv(i);
108 }
109 static void star_stuff_term_func(void)
110 {
111         glEnd();
112 }
113
114 void circf(float x, float y, float rad)
115 {
116         GLUquadricObj *qobj = gluNewQuadric(); 
117         
118         gluQuadricDrawStyle(qobj, GLU_FILL); 
119         
120         glPushMatrix(); 
121         
122         glTranslatef(x,  y, 0.); 
123         
124         gluDisk( qobj, 0.0,  rad, 32, 1); 
125         
126         glPopMatrix(); 
127         
128         gluDeleteQuadric(qobj);
129 }
130
131 void circ(float x, float y, float rad)
132 {
133         GLUquadricObj *qobj = gluNewQuadric(); 
134         
135         gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
136         
137         glPushMatrix(); 
138         
139         glTranslatef(x,  y, 0.); 
140         
141         gluDisk( qobj, 0.0,  rad, 32, 1); 
142         
143         glPopMatrix(); 
144         
145         gluDeleteQuadric(qobj);
146 }
147
148
149 /* ********* custom clipping *********** */
150
151 static void view3d_draw_clipping(RegionView3D *rv3d)
152 {
153         BoundBox *bb= rv3d->clipbb;
154         
155         if(bb) {
156                 UI_ThemeColorShade(TH_BACK, -8);
157                 
158                 glBegin(GL_QUADS);
159                 
160                 glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[3]);
161                 glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[1]);
162                 glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[5]);
163                 glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[3]); glVertex3fv(bb->vec[2]); glVertex3fv(bb->vec[6]);
164                 glVertex3fv(bb->vec[1]); glVertex3fv(bb->vec[5]); glVertex3fv(bb->vec[6]); glVertex3fv(bb->vec[2]);
165                 glVertex3fv(bb->vec[7]); glVertex3fv(bb->vec[4]); glVertex3fv(bb->vec[0]); glVertex3fv(bb->vec[3]);
166                 
167                 glEnd();
168         }
169 }
170
171 void view3d_set_clipping(RegionView3D *rv3d)
172 {
173         double plane[4];
174         int a, tot=4;
175         
176         if(rv3d->viewlock) tot= 6;
177         
178         for(a=0; a<tot; a++) {
179                 QUATCOPY(plane, rv3d->clip[a]);
180                 glClipPlane(GL_CLIP_PLANE0+a, plane);
181                 glEnable(GL_CLIP_PLANE0+a);
182         }
183 }
184
185 void view3d_clr_clipping(void)
186 {
187         int a;
188         
189         for(a=0; a<6; a++) {
190                 glDisable(GL_CLIP_PLANE0+a);
191         }
192 }
193
194 int view3d_test_clipping(RegionView3D *rv3d, float *vec)
195 {
196         /* vec in world coordinates, returns 1 if clipped */
197         float view[3];
198         
199         VECCOPY(view, vec);
200         
201         if(0.0f < rv3d->clip[0][3] + INPR(view, rv3d->clip[0]))
202                 if(0.0f < rv3d->clip[1][3] + INPR(view, rv3d->clip[1]))
203                         if(0.0f < rv3d->clip[2][3] + INPR(view, rv3d->clip[2]))
204                                 if(0.0f < rv3d->clip[3][3] + INPR(view, rv3d->clip[3]))
205                                         return 0;
206         
207         return 1;
208 }
209
210 /* ********* end custom clipping *********** */
211
212
213 static void drawgrid_draw(ARegion *ar, float wx, float wy, float x, float y, float dx)
214 {
215         float fx, fy;
216         
217         x+= (wx); 
218         y+= (wy);
219         fx= x/dx;
220         fx= x-dx*floor(fx);
221         
222         while(fx< ar->winx) {
223                 fdrawline(fx,  0.0,  fx,  (float)ar->winy); 
224                 fx+= dx; 
225         }
226
227         fy= y/dx;
228         fy= y-dx*floor(fy);
229         
230
231         while(fy< ar->winy) {
232                 fdrawline(0.0,  fy,  (float)ar->winx,  fy); 
233                 fy+= dx;
234         }
235
236 }
237
238 #define GRID_MIN_PX 6.0f
239
240 static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, char **grid_unit)
241 {
242         /* extern short bgpicmode; */
243         RegionView3D *rv3d= ar->regiondata;
244         float wx, wy, x, y, fw, fx, fy, dx;
245         float vec4[4];
246         char col[3], col2[3];
247         
248         *grid_unit= NULL;
249
250         vec4[0]=vec4[1]=vec4[2]=0.0; 
251         vec4[3]= 1.0;
252         Mat4MulVec4fl(rv3d->persmat, vec4);
253         fx= vec4[0]; 
254         fy= vec4[1]; 
255         fw= vec4[3];
256
257         wx= (ar->winx/2.0);     /* because of rounding errors, grid at wrong location */
258         wy= (ar->winy/2.0);
259
260         x= (wx)*fx/fw;
261         y= (wy)*fy/fw;
262
263         vec4[0]=vec4[1]= (unit->system) ? 1.0 : v3d->grid;
264
265         vec4[2]= 0.0;
266         vec4[3]= 1.0;
267         Mat4MulVec4fl(rv3d->persmat, vec4);
268         fx= vec4[0]; 
269         fy= vec4[1]; 
270         fw= vec4[3];
271
272         dx= fabs(x-(wx)*fx/fw);
273         if(dx==0) dx= fabs(y-(wy)*fy/fw);
274         
275         glDepthMask(0);         // disable write in zbuffer
276
277         /* check zoom out */
278         UI_ThemeColor(TH_GRID);
279         
280         if(unit->system) {
281                 /* Use GRID_MIN_PX*2 for units because very very small grid
282                  * items are less useful when dealing with units */
283                 void *usys;
284                 int len, i;
285                 double scalar;
286                 float dx_scalar;
287                 float blend_fac;
288
289                 bUnit_GetSystem(&usys, &len, unit->system, B_UNIT_LENGTH);
290
291                 if(usys) {
292                         i= len;
293                         while(i--) {
294                                 scalar= bUnit_GetScaler(usys, i);
295
296                                 dx_scalar = dx * scalar * unit->scale_length;
297                                 if (dx_scalar < (GRID_MIN_PX*2))
298                                         continue;
299
300                                 /* Store the smallest drawn grid size units name so users know how big each grid cell is */
301                                 if(*grid_unit==NULL) {
302                                         *grid_unit= bUnit_GetNamePlural(usys, i);
303                                         v3d->gridview= (scalar * unit->scale_length);
304                                 }
305                                 blend_fac= 1-((GRID_MIN_PX*2)/dx_scalar);
306
307                                 /* tweak to have the fade a bit nicer */
308                                 blend_fac= (blend_fac * blend_fac) * 2.0f;
309                                 CLAMP(blend_fac, 0.3f, 1.0f);
310
311
312                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, blend_fac);
313
314                                 drawgrid_draw(ar, wx, wy, x, y, dx_scalar);
315                         }
316                 }
317         }
318         else {
319                 short sublines = v3d->gridsubdiv;
320
321                 if(dx<GRID_MIN_PX) {
322                         v3d->gridview*= sublines;
323                         dx*= sublines;
324                         
325                         if(dx<GRID_MIN_PX) {
326                                 v3d->gridview*= sublines;
327                                 dx*= sublines;
328
329                                 if(dx<GRID_MIN_PX) {
330                                         v3d->gridview*= sublines;
331                                         dx*=sublines;
332                                         if(dx<GRID_MIN_PX);
333                                         else {
334                                                 UI_ThemeColor(TH_GRID);
335                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
336                                         }
337                                 }
338                                 else {  // start blending out
339                                         UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*10));
340                                         drawgrid_draw(ar, wx, wy, x, y, dx);
341
342                                         UI_ThemeColor(TH_GRID);
343                                         drawgrid_draw(ar, wx, wy, x, y, sublines*dx);
344                                 }
345                         }
346                         else {  // start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX*10))
347                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*10));
348                                 drawgrid_draw(ar, wx, wy, x, y, dx);
349
350                                 UI_ThemeColor(TH_GRID);
351                                 drawgrid_draw(ar, wx, wy, x, y, sublines*dx);
352                         }
353                 }
354                 else {
355                         if(dx>(GRID_MIN_PX*10)) {               // start blending in
356                                 v3d->gridview/= sublines;
357                                 dx/= sublines;
358                                 if(dx>(GRID_MIN_PX*10)) {               // start blending in
359                                         v3d->gridview/= sublines;
360                                         dx/= sublines;
361                                         if(dx>(GRID_MIN_PX*10)) {
362                                                 UI_ThemeColor(TH_GRID);
363                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
364                                         }
365                                         else {
366                                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*10));
367                                                 drawgrid_draw(ar, wx, wy, x, y, dx);
368                                                 UI_ThemeColor(TH_GRID);
369                                                 drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
370                                         }
371                                 }
372                                 else {
373                                         UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*10));
374                                         drawgrid_draw(ar, wx, wy, x, y, dx);
375                                         UI_ThemeColor(TH_GRID);
376                                         drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
377                                 }
378                         }
379                         else {
380                                 UI_ThemeColorBlend(TH_BACK, TH_GRID, dx/(GRID_MIN_PX*10));
381                                 drawgrid_draw(ar, wx, wy, x, y, dx);
382                                 UI_ThemeColor(TH_GRID);
383                                 drawgrid_draw(ar, wx, wy, x, y, dx*sublines);
384                         }
385                 }
386         }
387
388
389         x+= (wx); 
390         y+= (wy);
391         UI_GetThemeColor3ubv(TH_GRID, col);
392
393         setlinestyle(0);
394         
395         /* center cross */
396         if( ELEM(rv3d->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT)) 
397                 UI_make_axis_color(col, col2, 'y');
398         else UI_make_axis_color(col, col2, 'x');
399         glColor3ubv((GLubyte *)col2);
400         
401         fdrawline(0.0,  y,  (float)ar->winx,  y); 
402         
403         if( ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM)) 
404                 UI_make_axis_color(col, col2, 'y');
405         else UI_make_axis_color(col, col2, 'z');
406         glColor3ubv((GLubyte *)col2);
407
408         fdrawline(x, 0.0, x, (float)ar->winy); 
409
410         glDepthMask(1);         // enable write in zbuffer
411 }
412 #undef GRID_MIN_PX
413
414 static void drawfloor(Scene *scene, View3D *v3d)
415 {
416         float vert[3], grid;
417         int a, gridlines, emphasise;
418         char col[3], col2[3];
419         short draw_line = 0;
420         
421         vert[2]= 0.0;
422         
423         if(v3d->gridlines<3) return;
424         
425         if(v3d->zbuf && scene->obedit) glDepthMask(0);  // for zbuffer-select
426         
427         gridlines= v3d->gridlines/2;
428         grid= gridlines*v3d->grid;
429         
430         UI_GetThemeColor3ubv(TH_GRID, col);
431         UI_GetThemeColor3ubv(TH_BACK, col2);
432         
433         /* emphasise division lines lighter instead of darker, if background is darker than grid */
434         if ( ((col[0]+col[1]+col[2])/3+10) > (col2[0]+col2[1]+col2[2])/3 )
435                 emphasise = 20;
436         else
437                 emphasise = -10;
438         
439         /* draw the Y axis and/or grid lines */
440         for(a= -gridlines;a<=gridlines;a++) {
441                 if(a==0) {
442                         /* check for the 'show Y axis' preference */
443                         if (v3d->gridflag & V3D_SHOW_Y) { 
444                                 UI_make_axis_color(col, col2, 'y');
445                                 glColor3ubv((GLubyte *)col2);
446                                 
447                                 draw_line = 1;
448                         } else if (v3d->gridflag & V3D_SHOW_FLOOR) {
449                                 UI_ThemeColorShade(TH_GRID, emphasise);
450                         } else {
451                                 draw_line = 0;
452                         }
453                 } else {
454                         /* check for the 'show grid floor' preference */
455                         if (v3d->gridflag & V3D_SHOW_FLOOR) {
456                                 if( (a % 10)==0) {
457                                         UI_ThemeColorShade(TH_GRID, emphasise);
458                                 }
459                                 else UI_ThemeColorShade(TH_GRID, 10);
460                                 
461                                 draw_line = 1;
462                         } else {
463                                 draw_line = 0;
464                         }
465                 }
466                 
467                 if (draw_line) {
468                         glBegin(GL_LINE_STRIP);
469                 vert[0]= a*v3d->grid;
470                 vert[1]= grid;
471                 glVertex3fv(vert);
472                 vert[1]= -grid;
473                 glVertex3fv(vert);
474                         glEnd();
475                 }
476         }
477         
478         /* draw the X axis and/or grid lines */
479         for(a= -gridlines;a<=gridlines;a++) {
480                 if(a==0) {
481                         /* check for the 'show X axis' preference */
482                         if (v3d->gridflag & V3D_SHOW_X) { 
483                                 UI_make_axis_color(col, col2, 'x');
484                                 glColor3ubv((GLubyte *)col2);
485                                 
486                                 draw_line = 1;
487                         } else if (v3d->gridflag & V3D_SHOW_FLOOR) {
488                                 UI_ThemeColorShade(TH_GRID, emphasise);
489                         } else {
490                                 draw_line = 0;
491                         }
492                 } else {
493                         /* check for the 'show grid floor' preference */
494                         if (v3d->gridflag & V3D_SHOW_FLOOR) {
495                                 if( (a % 10)==0) {
496                                         UI_ThemeColorShade(TH_GRID, emphasise);
497                                 }
498                                 else UI_ThemeColorShade(TH_GRID, 10);
499                                 
500                                 draw_line = 1;
501                         } else {
502                                 draw_line = 0;
503                         }
504                 }
505                 
506                 if (draw_line) {
507                         glBegin(GL_LINE_STRIP);
508                 vert[1]= a*v3d->grid;
509                 vert[0]= grid;
510                 glVertex3fv(vert );
511                 vert[0]= -grid;
512                 glVertex3fv(vert);
513                         glEnd();
514                 }
515         }
516         
517         /* draw the Z axis line */      
518         /* check for the 'show Z axis' preference */
519         if (v3d->gridflag & V3D_SHOW_Z) {
520                 UI_make_axis_color(col, col2, 'z');
521                 glColor3ubv((GLubyte *)col2);
522                 
523                 glBegin(GL_LINE_STRIP);
524                 vert[0]= 0;
525                 vert[1]= 0;
526                 vert[2]= grid;
527                 glVertex3fv(vert );
528                 vert[2]= -grid;
529                 glVertex3fv(vert);
530                 glEnd();
531         }
532         
533         if(v3d->zbuf && scene->obedit) glDepthMask(1);  
534         
535 }
536
537 static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
538 {
539         short mx,my,co[2];
540         int flag;
541         
542         /* we dont want the clipping for cursor */
543         flag= v3d->flag;
544         v3d->flag= 0;
545         project_short(ar, give_cursor(scene, v3d), co);
546         v3d->flag= flag;
547         
548         mx = co[0];
549         my = co[1];
550         
551         if(mx!=IS_CLIPPED) {
552                 setlinestyle(0); 
553                 cpack(0xFF);
554                 circ((float)mx, (float)my, 10.0);
555                 setlinestyle(4); 
556                 cpack(0xFFFFFF);
557                 circ((float)mx, (float)my, 10.0);
558                 setlinestyle(0);
559                 cpack(0x0);
560                 
561                 sdrawline(mx-20, my, mx-5, my);
562                 sdrawline(mx+5, my, mx+20, my);
563                 sdrawline(mx, my-20, mx, my-5);
564                 sdrawline(mx, my+5, mx, my+20);
565         }
566 }
567
568 /* Draw a live substitute of the view icon, which is always shown */
569 static void draw_view_axis(RegionView3D *rv3d)
570 {
571         const float k = U.rvisize;   /* axis size */
572         const float toll = 0.5;      /* used to see when view is quasi-orthogonal */
573         const float start = k + 1.0; /* axis center in screen coordinates, x=y */
574         float ydisp = 0.0;          /* vertical displacement to allow obj info text */
575         
576         /* rvibright ranges approx. from original axis icon color to gizmo color */
577         float bright = U.rvibright / 15.0f;
578         
579         unsigned char col[3];
580         unsigned char gridcol[3];
581         float colf[3];
582         
583         float vec[4];
584         float dx, dy;
585         float h, s, v;
586         
587         /* thickness of lines is proportional to k */
588         /*      (log(k)-1) gives a more suitable thickness, but fps decreased by about 3 fps */
589         glLineWidth(k / 10);
590         //glLineWidth(log(k)-1); // a bit slow
591         
592         UI_GetThemeColor3ubv(TH_GRID, (char *)gridcol);
593         
594         /* X */
595         vec[0] = vec[3] = 1;
596         vec[1] = vec[2] = 0;
597         QuatMulVecf(rv3d->viewquat, vec);
598         
599         UI_make_axis_color((char *)gridcol, (char *)col, 'x');
600         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
601         s = s<0.5 ? s+0.5 : 1.0;
602         v = 0.3;
603         v = (v<1.0-(bright) ? v+bright : 1.0);
604         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
605         glColor3fv(colf);
606         
607         dx = vec[0] * k;
608         dy = vec[1] * k;
609         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
610         if (fabs(dx) > toll || fabs(dy) > toll) {
611                 BLF_draw_default(start + dx + 2, start + dy + ydisp + 2, 0.0f, "x");
612         }
613         
614         /* Y */
615         vec[1] = vec[3] = 1;
616         vec[0] = vec[2] = 0;
617         QuatMulVecf(rv3d->viewquat, vec);
618         
619         UI_make_axis_color((char *)gridcol, (char *)col, 'y');
620         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
621         s = s<0.5 ? s+0.5 : 1.0;
622         v = 0.3;
623         v = (v<1.0-(bright) ? v+bright : 1.0);
624         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
625         glColor3fv(colf);
626         
627         dx = vec[0] * k;
628         dy = vec[1] * k;
629         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
630         if (fabs(dx) > toll || fabs(dy) > toll) {
631                 BLF_draw_default(start + dx + 2, start + dy + ydisp + 2, 0.0f, "y");
632         }
633         
634         /* Z */
635         vec[2] = vec[3] = 1;
636         vec[1] = vec[0] = 0;
637         QuatMulVecf(rv3d->viewquat, vec);
638         
639         UI_make_axis_color((char *)gridcol, (char *)col, 'z');
640         rgb_to_hsv(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, &h, &s, &v);
641         s = s<0.5 ? s+0.5 : 1.0;
642         v = 0.5;
643         v = (v<1.0-(bright) ? v+bright : 1.0);
644         hsv_to_rgb(h, s, v, colf, colf+1, colf+2);
645         glColor3fv(colf);
646         
647         dx = vec[0] * k;
648         dy = vec[1] * k;
649         fdrawline(start, start + ydisp, start + dx, start + dy + ydisp);
650         if (fabs(dx) > toll || fabs(dy) > toll) {
651                 BLF_draw_default(start + dx + 2, start + dy + ydisp + 2, 0.0f, "z");
652         }
653         
654         /* restore line-width */
655         glLineWidth(1.0);
656 }
657
658
659 static void draw_view_icon(RegionView3D *rv3d)
660 {
661         BIFIconID icon;
662         
663         if( ELEM(rv3d->view, V3D_VIEW_TOP, V3D_VIEW_BOTTOM)) 
664                 icon= ICON_AXIS_TOP;
665         else if( ELEM(rv3d->view, V3D_VIEW_FRONT, V3D_VIEW_BACK)) 
666                 icon= ICON_AXIS_FRONT;
667         else if( ELEM(rv3d->view, V3D_VIEW_RIGHT, V3D_VIEW_LEFT)) 
668                 icon= ICON_AXIS_SIDE;
669         else return ;
670         
671         glEnable(GL_BLEND);
672         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
673         
674         UI_icon_draw(5.0, 5.0, icon);
675         
676         glDisable(GL_BLEND);
677 }
678
679 static char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
680 {
681         char *name = NULL;
682         
683         switch (rv3d->view) {
684                 case V3D_VIEW_FRONT:
685                         if (rv3d->persp == V3D_ORTHO) name = "Front Ortho";
686                         else name = "Front Persp";
687                         break;
688                 case V3D_VIEW_BACK:
689                         if (rv3d->persp == V3D_ORTHO) name = "Back Ortho";
690                         else name = "Back Persp";
691                         break;
692                 case V3D_VIEW_TOP:
693                         if (rv3d->persp == V3D_ORTHO) name = "Top Ortho";
694                         else name = "Top Persp";
695                         break;
696                 case V3D_VIEW_BOTTOM:
697                         if (rv3d->persp == V3D_ORTHO) name = "Bottom Ortho";
698                         else name = "Bottom Persp";
699                         break;
700                 case V3D_VIEW_RIGHT:
701                         if (rv3d->persp == V3D_ORTHO) name = "Right Ortho";
702                         else name = "Right Persp";
703                         break;
704                 case V3D_VIEW_LEFT:
705                         if (rv3d->persp == V3D_ORTHO) name = "Left Ortho";
706                         else name = "Left Persp";
707                         break;
708                         
709                 default:
710                         if (rv3d->persp==V3D_CAMOB) {
711                                 if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
712                                         Camera *cam;
713                                         cam = v3d->camera->data;
714                                         name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho";
715                                 } else {
716                                         name = "Object as Camera";
717                                 }
718                         } else { 
719                                 name = (rv3d->persp == V3D_ORTHO) ? "User Ortho" : "User Persp";
720                         }
721                         break;
722         }
723         
724         return name;
725 }
726
727 static void draw_viewport_name(ARegion *ar, View3D *v3d)
728 {
729         RegionView3D *rv3d= ar->regiondata;
730         char *name = view3d_get_name(v3d, rv3d);
731         char *printable = NULL;
732         
733         if (v3d->localview) {
734                 printable = malloc(strlen(name) + strlen(" (Local)_")); /* '_' gives space for '\0' */
735                                                                                                  strcpy(printable, name);
736                                                                                                  strcat(printable, " (Local)");
737         } else {
738                 printable = name;
739         }
740
741         if (printable) {
742                 UI_ThemeColor(TH_TEXT_HI);
743                 BLF_draw_default(10,  ar->winy-20, 0.0f, printable);
744         }
745
746         if (v3d->localview) {
747                 free(printable);
748         }
749 }
750
751
752 static char *get_cfra_marker_name(Scene *scene)
753 {
754         ListBase *markers= &scene->markers;
755         TimeMarker *m1, *m2;
756         
757         /* search through markers for match */
758         for (m1=markers->first, m2=markers->last; m1 && m2; m1=m1->next, m2=m2->prev) {
759                 if (m1->frame==CFRA)
760                         return m1->name;
761                 
762                 if (m1 == m2)
763                         break;          
764                 
765                 if (m2->frame==CFRA)
766                         return m2->name;
767         }
768         
769         return NULL;
770 }
771
772 /* draw info beside axes in bottom left-corner: 
773 *       framenum, object name, bone name (if available), marker name (if available)
774 */
775 static void draw_selected_name(Scene *scene, Object *ob, View3D *v3d)
776 {
777         char info[256], *markern;
778         short offset=30;
779         
780         /* get name of marker on current frame (if available) */
781         markern= get_cfra_marker_name(scene);
782         
783         /* check if there is an object */
784         if(ob) {
785                 /* name(s) to display depends on type of object */
786                 if(ob->type==OB_ARMATURE) {
787                         bArmature *arm= ob->data;
788                         char *name= NULL;
789                         
790                         /* show name of active bone too (if possible) */
791                         if(arm->edbo) {
792                                 EditBone *ebo;
793                                 for (ebo=arm->edbo->first; ebo; ebo=ebo->next){
794                                         if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) {
795                                                 name= ebo->name;
796                                                 break;
797                                         }
798                                 }
799                         }
800                         else if(ob->pose && (ob->flag & OB_POSEMODE)) {
801                                 bPoseChannel *pchan;
802                                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
803                                         if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) {
804                                                 name= pchan->name;
805                                                 break;
806                                         }
807                                 }
808                         }
809                         if(name && markern)
810                                 sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern);
811                         else if(name)
812                                 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name);
813                         else
814                                 sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
815                 }
816                 else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
817                         Key *key= NULL;
818                         KeyBlock *kb = NULL;
819                         char shapes[75];
820                         
821                         /* try to display active shapekey too */
822                         shapes[0] = 0;
823                         key = ob_get_key(ob);
824                         if(key){
825                                 kb = BLI_findlink(&key->block, ob->shapenr-1);
826                                 if(kb){
827                                         sprintf(shapes, ": %s ", kb->name);             
828                                         if(ob->shapeflag == OB_SHAPE_LOCK){
829                                                 sprintf(shapes, "%s (Pinned)",shapes);
830                                         }
831                                 }
832                         }
833                         
834                         if(markern)
835                                 sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern);
836                         else
837                                 sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes);
838                 }
839                 else {
840                         /* standard object */
841                         if (markern)
842                                 sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern);
843                         else
844                                 sprintf(info, "(%d) %s", CFRA, ob->id.name+2);
845                 }
846                 
847                 /* colour depends on whether there is a keyframe */
848                 if (id_frame_has_keyframe((ID *)ob, /*frame_to_float(scene, CFRA)*/(float)(CFRA), v3d->keyflags))
849                         UI_ThemeColor(TH_VERTEX_SELECT);
850                 else
851                         UI_ThemeColor(TH_TEXT_HI);
852         }
853         else {
854                 /* no object */
855                 if (markern)
856                         sprintf(info, "(%d) <%s>", CFRA, markern);
857                 else
858                         sprintf(info, "(%d)", CFRA);
859                 
860                 /* colour is always white */
861                 UI_ThemeColor(TH_TEXT_HI);
862         }
863         
864         if (U.uiflag & USER_SHOW_ROTVIEWICON)
865                 offset = 14 + (U.rvisize * 2);
866
867         BLF_draw_default(offset,  10, 0.0f, info);
868 }
869
870 static void view3d_get_viewborder_size(Scene *scene, ARegion *ar, float size_r[2])
871 {
872         float winmax= MAX2(ar->winx, ar->winy);
873         float aspect= (float) (scene->r.xsch*scene->r.xasp)/(scene->r.ysch*scene->r.yasp);
874         
875         if(aspect>1.0) {
876                 size_r[0]= winmax;
877                 size_r[1]= winmax/aspect;
878         } else {
879                 size_r[0]= winmax*aspect;
880                 size_r[1]= winmax;
881         }
882 }
883
884 void calc_viewborder(Scene *scene, ARegion *ar, View3D *v3d, rctf *viewborder_r)
885 {
886         RegionView3D *rv3d= ar->regiondata;
887         float zoomfac, size[2];
888         float dx= 0.0f, dy= 0.0f;
889         
890         view3d_get_viewborder_size(scene, ar, size);
891         
892         /* magic zoom calculation, no idea what
893                 * it signifies, if you find out, tell me! -zr
894                 */
895         /* simple, its magic dude!
896                 * well, to be honest, this gives a natural feeling zooming
897                 * with multiple keypad presses (ton)
898                 */
899         
900         zoomfac= (M_SQRT2 + rv3d->camzoom/50.0);
901         zoomfac= (zoomfac*zoomfac)*0.25;
902         
903         size[0]= size[0]*zoomfac;
904         size[1]= size[1]*zoomfac;
905         
906         /* center in window */
907         viewborder_r->xmin= 0.5*ar->winx - 0.5*size[0];
908         viewborder_r->ymin= 0.5*ar->winy - 0.5*size[1];
909         viewborder_r->xmax= viewborder_r->xmin + size[0];
910         viewborder_r->ymax= viewborder_r->ymin + size[1];
911         
912         dx= ar->winx*rv3d->camdx*zoomfac*2.0f;
913         dy= ar->winy*rv3d->camdy*zoomfac*2.0f;
914         
915         /* apply offset */
916         viewborder_r->xmin-= dx;
917         viewborder_r->ymin-= dy;
918         viewborder_r->xmax-= dx;
919         viewborder_r->ymax-= dy;
920         
921         if(v3d->camera && v3d->camera->type==OB_CAMERA) {
922                 Camera *cam= v3d->camera->data;
923                 float w = viewborder_r->xmax - viewborder_r->xmin;
924                 float h = viewborder_r->ymax - viewborder_r->ymin;
925                 float side = MAX2(w, h);
926                 
927                 viewborder_r->xmin+= cam->shiftx*side;
928                 viewborder_r->xmax+= cam->shiftx*side;
929                 viewborder_r->ymin+= cam->shifty*side;
930                 viewborder_r->ymax+= cam->shifty*side;
931         }
932 }
933
934 void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar)
935 {
936         RegionView3D *rv3d= ar->regiondata;
937         float size[2];
938         int im_width= (scene->r.size*scene->r.xsch)/100;
939         
940         view3d_get_viewborder_size(scene, ar, size);
941         
942         rv3d->camzoom= (sqrt(4.0*im_width/size[0]) - M_SQRT2)*50.0;
943         rv3d->camzoom= CLAMPIS(rv3d->camzoom, -30, 300);
944 }
945
946
947 static void drawviewborder_flymode(ARegion *ar) 
948 {
949         /* draws 4 edge brackets that frame the safe area where the
950         mouse can move during fly mode without spinning the view */
951         float x1, x2, y1, y2;
952         
953         x1= 0.45*(float)ar->winx;
954         y1= 0.45*(float)ar->winy;
955         x2= 0.55*(float)ar->winx;
956         y2= 0.55*(float)ar->winy;
957         cpack(0);
958         
959         
960         glBegin(GL_LINES);
961         /* bottom left */
962         glVertex2f(x1,y1); 
963         glVertex2f(x1,y1+5);
964         
965         glVertex2f(x1,y1); 
966         glVertex2f(x1+5,y1);
967         
968         /* top right */
969         glVertex2f(x2,y2); 
970         glVertex2f(x2,y2-5);
971         
972         glVertex2f(x2,y2); 
973         glVertex2f(x2-5,y2);
974         
975         /* top left */
976         glVertex2f(x1,y2); 
977         glVertex2f(x1,y2-5);
978         
979         glVertex2f(x1,y2); 
980         glVertex2f(x1+5,y2);
981         
982         /* bottom right */
983         glVertex2f(x2,y1); 
984         glVertex2f(x2,y1+5);
985         
986         glVertex2f(x2,y1); 
987         glVertex2f(x2-5,y1);
988         glEnd();        
989 }
990
991
992 static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
993 {
994         extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);          // interface_panel.c
995         float fac, a;
996         float x1, x2, y1, y2;
997         float x3, y3, x4, y4;
998         rctf viewborder;
999         Camera *ca= NULL;
1000         
1001         if(v3d->camera==NULL)
1002                 return;
1003         if(v3d->camera->type==OB_CAMERA)
1004                 ca = v3d->camera->data;
1005         
1006         calc_viewborder(scene, ar, v3d, &viewborder);
1007         x1= viewborder.xmin;
1008         y1= viewborder.ymin;
1009         x2= viewborder.xmax;
1010         y2= viewborder.ymax;
1011         
1012         /* passepartout, specified in camera edit buttons */
1013         if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001) {
1014                 if (ca->passepartalpha == 1.0) {
1015                         glColor3f(0, 0, 0);
1016                 } else {
1017                         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1018                         glEnable(GL_BLEND);
1019                         glColor4f(0, 0, 0, ca->passepartalpha);
1020                 }
1021                 if (x1 > 0.0)
1022                         glRectf(0.0, (float)ar->winy, x1, 0.0);
1023                 if (x2 < (float)ar->winx)
1024                         glRectf(x2, (float)ar->winy, (float)ar->winx, 0.0);
1025                 if (y2 < (float)ar->winy)
1026                         glRectf(x1, (float)ar->winy, x2, y2);
1027                 if (y2 > 0.0) 
1028                         glRectf(x1, y1, x2, 0.0);
1029                 
1030                 glDisable(GL_BLEND);
1031         }
1032         
1033         /* edge */
1034         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
1035         
1036         setlinestyle(0);
1037         UI_ThemeColor(TH_BACK);
1038         glRectf(x1, y1, x2, y2);
1039         
1040         setlinestyle(3);
1041         UI_ThemeColor(TH_WIRE);
1042         glRectf(x1, y1, x2, y2);
1043         
1044         /* camera name - draw in highlighted text color */
1045         if (ca && (ca->flag & CAM_SHOWNAME)) {
1046                 UI_ThemeColor(TH_TEXT_HI);
1047                 BLF_draw_default(x1, y1-15, 0.0f, v3d->camera->id.name+2);
1048                 UI_ThemeColor(TH_WIRE);
1049         }
1050         
1051         
1052         /* border */
1053         if(scene->r.mode & R_BORDER) {
1054                 
1055                 cpack(0);
1056                 x3= x1+ scene->r.border.xmin*(x2-x1);
1057                 y3= y1+ scene->r.border.ymin*(y2-y1);
1058                 x4= x1+ scene->r.border.xmax*(x2-x1);
1059                 y4= y1+ scene->r.border.ymax*(y2-y1);
1060                 
1061                 cpack(0x4040FF);
1062                 glRectf(x3,  y3,  x4,  y4); 
1063         }
1064         
1065         /* safety border */
1066         if (ca && (ca->flag & CAM_SHOWTITLESAFE)) {
1067                 fac= 0.1;
1068                 
1069                 a= fac*(x2-x1);
1070                 x1+= a; 
1071                 x2-= a;
1072                 
1073                 a= fac*(y2-y1);
1074                 y1+= a;
1075                 y2-= a;
1076                 
1077                 UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0);
1078                 
1079                 uiSetRoundBox(15);
1080                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
1081         }
1082         
1083         setlinestyle(0);
1084         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1085         
1086 }
1087
1088 /* *********************** backdraw for selection *************** */
1089
1090 void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
1091 {
1092         RegionView3D *rv3d= ar->regiondata;
1093         struct Base *base;
1094
1095 /*for 2.43 release, don't use glext and just define the constant.
1096   this to avoid possibly breaking platforms before release.*/
1097 #ifndef GL_MULTISAMPLE_ARB
1098         #define GL_MULTISAMPLE_ARB      0x809D
1099 #endif
1100
1101 #ifdef GL_MULTISAMPLE_ARB
1102         int m;
1103 #endif
1104
1105         if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || (FACESEL_PAINT_TEST));
1106         else if((G.f & G_TEXTUREPAINT) && scene->toolsettings && (scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE));
1107         else if((G.f & G_PARTICLEEDIT) && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT));
1108         else if(scene->obedit && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT));
1109         else {
1110                 v3d->flag &= ~V3D_NEEDBACKBUFDRAW;
1111                 return;
1112         }
1113
1114         if( !(v3d->flag & V3D_NEEDBACKBUFDRAW) ) return;
1115
1116 //      if(test) {
1117 //              if(qtest()) {
1118 //                      addafterqueue(ar->win, BACKBUFDRAW, 1);
1119 //                      return;
1120 //              }
1121 //      }
1122
1123         /* Disable FSAA for backbuffer selection.  
1124         
1125         Only works if GL_MULTISAMPLE_ARB is defined by the header
1126         file, which is should be for every OS that supports FSAA.*/
1127
1128 #ifdef GL_MULTISAMPLE_ARB
1129         m = glIsEnabled(GL_MULTISAMPLE_ARB);
1130         if (m) glDisable(GL_MULTISAMPLE_ARB);
1131 #endif
1132
1133         if(v3d->drawtype > OB_WIRE) v3d->zbuf= TRUE;
1134         
1135         glDisable(GL_DITHER);
1136
1137         glClearColor(0.0, 0.0, 0.0, 0.0); 
1138         if(v3d->zbuf) {
1139                 glEnable(GL_DEPTH_TEST);
1140                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1141         }
1142         else {
1143                 glClear(GL_COLOR_BUFFER_BIT);
1144                 glDisable(GL_DEPTH_TEST);
1145         }
1146         
1147         if(rv3d->rflag & RV3D_CLIPPING)
1148                 view3d_set_clipping(rv3d);
1149         
1150         G.f |= G_BACKBUFSEL;
1151         
1152         base= (scene->basact);
1153         if(base && (base->lay & v3d->lay)) {
1154                 draw_object_backbufsel(scene, v3d, rv3d, base->object);
1155         }
1156
1157         v3d->flag &= ~V3D_NEEDBACKBUFDRAW;
1158
1159         G.f &= ~G_BACKBUFSEL;
1160         v3d->zbuf= FALSE; 
1161         glDisable(GL_DEPTH_TEST);
1162         glEnable(GL_DITHER);
1163
1164         if(rv3d->rflag & RV3D_CLIPPING)
1165                 view3d_clr_clipping();
1166
1167 #ifdef GL_MULTISAMPLE_ARB
1168         if (m) glEnable(GL_MULTISAMPLE_ARB);
1169 #endif
1170
1171         /* it is important to end a view in a transform compatible with buttons */
1172 //      persp(PERSP_WIN);  // set ortho
1173
1174 }
1175
1176 void view3d_validate_backbuf(ViewContext *vc)
1177 {
1178         if(vc->v3d->flag & V3D_NEEDBACKBUFDRAW)
1179                 backdrawview3d(vc->scene, vc->ar, vc->v3d);
1180 }
1181
1182 /* samples a single pixel (copied from vpaint) */
1183 unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
1184 {
1185         unsigned int col;
1186         
1187         if(x >= vc->ar->winx || y >= vc->ar->winy) return 0;
1188         x+= vc->ar->winrct.xmin;
1189         y+= vc->ar->winrct.ymin;
1190         
1191         view3d_validate_backbuf(vc);
1192
1193         glReadPixels(x,  y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,  &col);
1194         glReadBuffer(GL_BACK);  
1195         
1196         if(ENDIAN_ORDER==B_ENDIAN) SWITCH_INT(col);
1197         
1198         return WM_framebuffer_to_index(col);
1199 }
1200
1201 /* reads full rect, converts indices */
1202 ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
1203 {
1204         unsigned int *dr, *rd;
1205         struct ImBuf *ibuf, *ibuf1;
1206         int a;
1207         short xminc, yminc, xmaxc, ymaxc, xs, ys;
1208         
1209         /* clip */
1210         if(xmin<0) xminc= 0; else xminc= xmin;
1211         if(xmax >= vc->ar->winx) xmaxc= vc->ar->winx-1; else xmaxc= xmax;
1212         if(xminc > xmaxc) return NULL;
1213
1214         if(ymin<0) yminc= 0; else yminc= ymin;
1215         if(ymax >= vc->ar->winy) ymaxc= vc->ar->winy-1; else ymaxc= ymax;
1216         if(yminc > ymaxc) return NULL;
1217         
1218         ibuf= IMB_allocImBuf((xmaxc-xminc+1), (ymaxc-yminc+1), 32, IB_rect,0);
1219
1220         view3d_validate_backbuf(vc); 
1221         
1222         glReadPixels(vc->ar->winrct.xmin+xminc, vc->ar->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
1223         glReadBuffer(GL_BACK);  
1224
1225         if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
1226
1227         a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
1228         dr= ibuf->rect;
1229         while(a--) {
1230                 if(*dr) *dr= WM_framebuffer_to_index(*dr);
1231                 dr++;
1232         }
1233         
1234         /* put clipped result back, if needed */
1235         if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) 
1236                 return ibuf;
1237         
1238         ibuf1= IMB_allocImBuf( (xmax-xmin+1),(ymax-ymin+1),32,IB_rect,0);
1239         rd= ibuf->rect;
1240         dr= ibuf1->rect;
1241                 
1242         for(ys= ymin; ys<=ymax; ys++) {
1243                 for(xs= xmin; xs<=xmax; xs++, dr++) {
1244                         if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
1245                                 *dr= *rd;
1246                                 rd++;
1247                         }
1248                 }
1249         }
1250         IMB_freeImBuf(ibuf);
1251         return ibuf1;
1252 }
1253
1254 /* smart function to sample a rect spiralling outside, nice for backbuf selection */
1255 unsigned int view3d_sample_backbuf_rect(ViewContext *vc, short mval[2], int size, 
1256                                                                                 unsigned int min, unsigned int max, int *dist, short strict, 
1257                                                                                 void *handle, unsigned int (*indextest)(void *handle, unsigned int index))
1258 {
1259         struct ImBuf *buf;
1260         unsigned int *bufmin, *bufmax, *tbuf;
1261         int minx, miny;
1262         int a, b, rc, nr, amount, dirvec[4][2];
1263         int distance=0;
1264         unsigned int index = 0;
1265         short indexok = 0;      
1266
1267         amount= (size-1)/2;
1268
1269         minx = mval[0]-(amount+1);
1270         miny = mval[1]-(amount+1);
1271         buf = view3d_read_backbuf(vc, minx, miny, minx+size-1, miny+size-1);
1272         if (!buf) return 0;
1273
1274         rc= 0;
1275         
1276         dirvec[0][0]= 1; dirvec[0][1]= 0;
1277         dirvec[1][0]= 0; dirvec[1][1]= -size;
1278         dirvec[2][0]= -1; dirvec[2][1]= 0;
1279         dirvec[3][0]= 0; dirvec[3][1]= size;
1280         
1281         bufmin = buf->rect;
1282         tbuf = buf->rect;
1283         bufmax = buf->rect + size*size;
1284         tbuf+= amount*size+ amount;
1285         
1286         for(nr=1; nr<=size; nr++) {
1287                 
1288                 for(a=0; a<2; a++) {
1289                         for(b=0; b<nr; b++, distance++) {
1290                                 if (*tbuf && *tbuf>=min && *tbuf<max) { //we got a hit
1291                                         if(strict){
1292                                                 indexok =  indextest(handle, *tbuf - min+1);
1293                                                 if(indexok){
1294                                                         *dist= (short) sqrt( (float)distance   );
1295                                                         index = *tbuf - min+1;
1296                                                         goto exit; 
1297                                                 }                                               
1298                                         }
1299                                         else{
1300                                                 *dist= (short) sqrt( (float)distance ); // XXX, this distance is wrong - 
1301                                                 index = *tbuf - min+1; // messy yah, but indices start at 1
1302                                                 goto exit;
1303                                         }                       
1304                                 }
1305                                 
1306                                 tbuf+= (dirvec[rc][0]+dirvec[rc][1]);
1307                                 
1308                                 if(tbuf<bufmin || tbuf>=bufmax) {
1309                                         goto exit;
1310                                 }
1311                         }
1312                         rc++;
1313                         rc &= 3;
1314                 }
1315         }
1316
1317 exit:
1318         IMB_freeImBuf(buf);
1319         return index;
1320 }
1321
1322
1323 /* ************************************************************* */
1324
1325 static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d)
1326 {
1327         RegionView3D *rv3d= ar->regiondata;
1328         BGpic *bgpic;
1329         Image *ima;
1330         ImBuf *ibuf= NULL;
1331         float vec[4], fac, asp, zoomx, zoomy;
1332         float x1, y1, x2, y2, cx, cy;
1333         
1334         bgpic= v3d->bgpic;
1335         if(bgpic==NULL) return;
1336         
1337         ima= bgpic->ima;
1338         
1339         if(ima)
1340                 ibuf= BKE_image_get_ibuf(ima, &bgpic->iuser);
1341         if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL) ) 
1342                 return;
1343         if(ibuf->channels!=4)
1344                 return;
1345         if(ibuf->rect==NULL)
1346                 IMB_rect_from_float(ibuf);
1347         
1348         if(rv3d->persp==2) {
1349                 rctf vb;
1350                 
1351                 calc_viewborder(scene, ar, v3d, &vb);
1352                 
1353                 x1= vb.xmin;
1354                 y1= vb.ymin;
1355                 x2= vb.xmax;
1356                 y2= vb.ymax;
1357         }
1358         else {
1359                 float sco[2];
1360                 
1361                 /* calc window coord */
1362                 initgrabz(rv3d, 0.0, 0.0, 0.0);
1363                 window_to_3d_delta(ar, vec, 1, 0);
1364                 fac= MAX3( fabs(vec[0]), fabs(vec[1]), fabs(vec[1]) );
1365                 fac= 1.0/fac;
1366                 
1367                 asp= ( (float)ibuf->y)/(float)ibuf->x;
1368                 
1369                 vec[0] = vec[1] = vec[2] = 0.0;
1370                 view3d_project_float(ar, vec, sco, rv3d->persmat);
1371                 cx = sco[0];
1372                 cy = sco[1];
1373                 
1374                 x1=  cx+ fac*(bgpic->xof-bgpic->size);
1375                 y1=  cy+ asp*fac*(bgpic->yof-bgpic->size);
1376                 x2=  cx+ fac*(bgpic->xof+bgpic->size);
1377                 y2=  cy+ asp*fac*(bgpic->yof+bgpic->size);
1378         }
1379         
1380         /* complete clip? */
1381         
1382         if(x2 < 0 ) return;
1383         if(y2 < 0 ) return;
1384         if(x1 > ar->winx ) return;
1385         if(y1 > ar->winy ) return;
1386         
1387         zoomx= (x2-x1)/ibuf->x;
1388         zoomy= (y2-y1)/ibuf->y;
1389         
1390         /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
1391         if(zoomx < 1.0f || zoomy < 1.0f) {
1392                 float tzoom= MIN2(zoomx, zoomy);
1393                 int mip= 0;
1394                 
1395                 if(ibuf->mipmap[0]==NULL)
1396                         IMB_makemipmap(ibuf, 0, 0);
1397                 
1398                 while(tzoom < 1.0f && mip<8 && ibuf->mipmap[mip]) {
1399                         tzoom*= 2.0f;
1400                         zoomx*= 2.0f;
1401                         zoomy*= 2.0f;
1402                         mip++;
1403                 }
1404                 if(mip>0)
1405                         ibuf= ibuf->mipmap[mip-1];
1406         }
1407         
1408         if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
1409         
1410         glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
1411         
1412         glMatrixMode(GL_PROJECTION);
1413         glPushMatrix();
1414         glMatrixMode(GL_MODELVIEW);
1415         glPushMatrix();
1416         
1417         glaDefine2DArea(&ar->winrct);
1418         
1419         glEnable(GL_BLEND);
1420         
1421         glPixelZoom(zoomx, zoomy);
1422         glColor4f(1.0, 1.0, 1.0, 1.0-bgpic->blend);
1423         glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
1424         
1425         glPixelZoom(1.0, 1.0);
1426         glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
1427         
1428         glMatrixMode(GL_PROJECTION);
1429         glPopMatrix();
1430         glMatrixMode(GL_MODELVIEW);
1431         glPopMatrix();
1432         
1433         glDisable(GL_BLEND);
1434         if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
1435 }
1436
1437 /* ****************** View3d afterdraw *************** */
1438
1439 typedef struct View3DAfter {
1440         struct View3DAfter *next, *prev;
1441         struct Base *base;
1442         int type, flag;
1443 } View3DAfter;
1444
1445 /* temp storage of Objects that need to be drawn as last */
1446 void add_view3d_after(View3D *v3d, Base *base, int type, int flag)
1447 {
1448         View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after");
1449         
1450         BLI_addtail(&v3d->afterdraw, v3da);
1451         v3da->base= base;
1452         v3da->type= type;
1453         v3da->flag= flag;
1454 }
1455
1456 /* clears zbuffer and draws it over */
1457 static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, int clear)
1458 {
1459         View3DAfter *v3da, *next;
1460         int doit= 0;
1461         
1462         for(v3da= v3d->afterdraw.first; v3da; v3da= v3da->next)
1463                 if(v3da->type==V3D_XRAY) doit= 1;
1464         
1465         if(doit) {
1466                 if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT);
1467                 v3d->xray= TRUE;
1468                 
1469                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
1470                         next= v3da->next;
1471                         if(v3da->type==V3D_XRAY) {
1472                                 draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1473                                 BLI_remlink(&v3d->afterdraw, v3da);
1474                                 MEM_freeN(v3da);
1475                         }
1476                 }
1477                 v3d->xray= FALSE;
1478         }
1479 }
1480
1481 /* disables write in zbuffer and draws it over */
1482 static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
1483 {
1484         View3DAfter *v3da, *next;
1485         
1486         glDepthMask(0);
1487         v3d->transp= TRUE;
1488         
1489         for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
1490                 next= v3da->next;
1491                 if(v3da->type==V3D_TRANSP) {
1492                         draw_object(scene, ar, v3d, v3da->base, v3da->flag);
1493                         BLI_remlink(&v3d->afterdraw, v3da);
1494                         MEM_freeN(v3da);
1495                 }
1496         }
1497         v3d->transp= FALSE;
1498         
1499         glDepthMask(1);
1500         
1501 }
1502
1503 /* *********************** */
1504
1505 /*
1506         In most cases call draw_dupli_objects,
1507         draw_dupli_objects_color was added because when drawing set dupli's
1508         we need to force the color
1509  */
1510 static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int color)
1511 {       
1512         RegionView3D *rv3d= ar->regiondata;
1513         ListBase *lb;
1514         DupliObject *dob;
1515         Base tbase;
1516         BoundBox *bb= NULL;
1517         GLuint displist=0;
1518         short transflag, use_displist= -1;      /* -1 is initialize */
1519         char dt, dtx;
1520         
1521         if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
1522         
1523         tbase.flag= OB_FROMDUPLI|base->flag;
1524         lb= object_duplilist(scene, base->object);
1525         
1526         for(dob= lb->first; dob; dob= dob->next) {
1527                 if(dob->no_draw);
1528                 else {
1529                         tbase.object= dob->ob;
1530                         
1531                         /* extra service: draw the duplicator in drawtype of parent */
1532                         /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
1533                         dt= tbase.object->dt;   tbase.object->dt= MIN2(tbase.object->dt, base->object->dt);
1534                         dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
1535                         
1536                         /* negative scale flag has to propagate */
1537                         transflag= tbase.object->transflag;
1538                         if(base->object->transflag & OB_NEG_SCALE)
1539                                 tbase.object->transflag ^= OB_NEG_SCALE;
1540                         
1541                         UI_ThemeColorBlend(color, TH_BACK, 0.5);
1542                         
1543                         /* generate displist, test for new object */
1544                         if(use_displist==1 && dob->prev && dob->prev->ob!=dob->ob) {
1545                                 use_displist= -1;
1546                                 glDeleteLists(displist, 1);
1547                         }
1548                         /* generate displist */
1549                         if(use_displist == -1) {
1550                                 
1551                                 /* lamp drawing messes with matrices, could be handled smarter... but this works */
1552                                 if(dob->ob->type==OB_LAMP || dob->type==OB_DUPLIGROUP)
1553                                         use_displist= 0;
1554                                 else {
1555                                         /* disable boundbox check for list creation */
1556                                         object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
1557                                         /* need this for next part of code */
1558                                         bb= object_get_boundbox(dob->ob);
1559                                         
1560                                         Mat4One(dob->ob->obmat);        /* obmat gets restored */
1561                                         
1562                                         displist= glGenLists(1);
1563                                         glNewList(displist, GL_COMPILE);
1564                                         draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
1565                                         glEndList();
1566                                         
1567                                         use_displist= 1;
1568                                         object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
1569                                 }
1570                         }
1571                         if(use_displist) {
1572                                 wmMultMatrix(dob->mat);
1573                                 if(boundbox_clip(rv3d, dob->mat, bb))
1574                                         glCallList(displist);
1575                                 wmLoadMatrix(rv3d->viewmat);
1576                         }
1577                         else {
1578                                 Mat4CpyMat4(dob->ob->obmat, dob->mat);
1579                                 draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
1580                         }
1581                         
1582                         tbase.object->dt= dt;
1583                         tbase.object->dtx= dtx;
1584                         tbase.object->transflag= transflag;
1585                 }
1586         }
1587         
1588         /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
1589         
1590         free_object_duplilist(lb);      /* does restore */
1591         
1592         if(use_displist)
1593                 glDeleteLists(displist, 1);
1594 }
1595
1596 static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
1597 {
1598         /* define the color here so draw_dupli_objects_color can be called
1599         * from the set loop */
1600         
1601         int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
1602         /* debug */
1603         if(base->object->dup_group && base->object->dup_group->id.us<1)
1604                 color= TH_REDALERT;
1605         
1606         draw_dupli_objects_color(scene, ar, v3d, base, color);
1607 }
1608
1609
1610 void view3d_update_depths(ARegion *ar, View3D *v3d)
1611 {
1612         RegionView3D *rv3d= ar->regiondata;
1613         
1614         /* Create storage for, and, if necessary, copy depth buffer */
1615         if(!rv3d->depths) rv3d->depths= MEM_callocN(sizeof(ViewDepths),"ViewDepths");
1616         if(rv3d->depths) {
1617                 ViewDepths *d= rv3d->depths;
1618                 if(d->w != ar->winx ||
1619                    d->h != ar->winy ||
1620                    !d->depths) {
1621                         d->w= ar->winx;
1622                         d->h= ar->winy;
1623                         if(d->depths)
1624                                 MEM_freeN(d->depths);
1625                         d->depths= MEM_mallocN(sizeof(float)*d->w*d->h,"View depths");
1626                         d->damaged= 1;
1627                 }
1628                 
1629                 if(d->damaged) {
1630                         glReadPixels(ar->winrct.xmin,ar->winrct.ymin,d->w,d->h,
1631                                                  GL_DEPTH_COMPONENT,GL_FLOAT, d->depths);
1632                         
1633                         glGetDoublev(GL_DEPTH_RANGE,d->depth_range);
1634                         
1635                         d->damaged= 0;
1636                 }
1637         }
1638 }
1639
1640 /* Enable sculpting in wireframe mode by drawing sculpt object only to the depth buffer */
1641 static void draw_sculpt_depths(Scene *scene, ARegion *ar, View3D *v3d)
1642 {
1643         Object *ob = OBACT;
1644         
1645         int dt= MIN2(v3d->drawtype, ob->dt);
1646         if(v3d->zbuf==0 && dt>OB_WIRE)
1647                 dt= OB_WIRE;
1648         if(dt == OB_WIRE) {
1649                 GLboolean depth_on;
1650                 int orig_vdt = v3d->drawtype;
1651                 int orig_zbuf = v3d->zbuf;
1652                 int orig_odt = ob->dt;
1653                 
1654                 glGetBooleanv(GL_DEPTH_TEST, &depth_on);
1655                 v3d->drawtype = ob->dt = OB_SOLID;
1656                 v3d->zbuf = 1;
1657                 
1658                 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1659                 glEnable(GL_DEPTH_TEST);
1660                 draw_object(scene, ar, v3d, BASACT, 0);
1661                 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1662                 if(!depth_on)
1663                         glDisable(GL_DEPTH_TEST);
1664                 
1665                 v3d->drawtype = orig_vdt;
1666                 v3d->zbuf = orig_zbuf;
1667                 ob->dt = orig_odt;
1668         }
1669 }
1670
1671 void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *))
1672 {
1673         RegionView3D *rv3d= ar->regiondata;
1674         Base *base;
1675         Scene *sce;
1676         short zbuf, flag;
1677         float glalphaclip;
1678         /* temp set drawtype to solid */
1679         
1680         /* Setting these temporarily is not nice */
1681         zbuf = v3d->zbuf;
1682         flag = v3d->flag;
1683         glalphaclip = U.glalphaclip;
1684         
1685         U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
1686         v3d->flag &= ~V3D_SELECT_OUTLINE;
1687         
1688         setwinmatrixview3d(ar, v3d, NULL);      /* 0= no pick rect */
1689         setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
1690         
1691         Mat4MulMat4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
1692         Mat4Invert(rv3d->persinv, rv3d->persmat);
1693         Mat4Invert(rv3d->viewinv, rv3d->viewmat);
1694         
1695         glClear(GL_DEPTH_BUFFER_BIT);
1696         
1697         wmLoadMatrix(rv3d->viewmat);
1698 //      persp(PERSP_STORE);  // store correct view for persp(PERSP_VIEW) calls
1699         
1700         if(rv3d->rflag & RV3D_CLIPPING) {
1701                 view3d_set_clipping(rv3d);
1702         }
1703         
1704         v3d->zbuf= TRUE;
1705         glEnable(GL_DEPTH_TEST);
1706         
1707         /* draw set first */
1708         if(scene->set) {
1709                 for(SETLOOPER(scene->set, base)) {
1710                         if(v3d->lay & base->lay) {
1711                                 if (func == NULL || func(base)) {
1712                                         draw_object(scene, ar, v3d, base, 0);
1713                                         if(base->object->transflag & OB_DUPLI) {
1714                                                 draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
1715                                         }
1716                                 }
1717                         }
1718                 }
1719         }
1720         
1721         for(base= scene->base.first; base; base= base->next) {
1722                 if(v3d->lay & base->lay) {
1723                         if (func == NULL || func(base)) {
1724                                 /* dupli drawing */
1725                                 if(base->object->transflag & OB_DUPLI) {
1726                                         draw_dupli_objects(scene, ar, v3d, base);
1727                                 }
1728                                 draw_object(scene, ar, v3d, base, 0);
1729                         }
1730                 }
1731         }
1732         
1733         /* this isnt that nice, draw xray objects as if they are normal */
1734         if (v3d->afterdraw.first) {
1735                 View3DAfter *v3da, *next;
1736                 int num = 0;
1737                 v3d->xray= TRUE;
1738                 
1739                 glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
1740                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
1741                         next= v3da->next;
1742                         if(v3da->type==V3D_XRAY) {
1743                                 draw_object(scene, ar, v3d, v3da->base, 0);
1744                                 num++;
1745                         }
1746                         /* dont remove this time */
1747                 }
1748                 v3d->xray= FALSE;
1749                 
1750                 glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
1751                 for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
1752                         next= v3da->next;
1753                         if(v3da->type==V3D_XRAY) {
1754                                 v3d->xray= TRUE; v3d->transp= FALSE;  
1755                         } else if (v3da->type==V3D_TRANSP) {
1756                                 v3d->xray= FALSE; v3d->transp= TRUE;
1757                         }
1758                         
1759                         draw_object(scene, ar, v3d, v3da->base, 0); /* Draw Xray or Transp objects normally */
1760                         BLI_remlink(&v3d->afterdraw, v3da);
1761                         MEM_freeN(v3da);
1762                 }
1763                 v3d->xray= FALSE;
1764                 v3d->transp= FALSE;
1765         }
1766         
1767         v3d->zbuf = zbuf;
1768         U.glalphaclip = glalphaclip;
1769         v3d->flag = flag;
1770 }
1771
1772 typedef struct View3DShadow {
1773         struct View3DShadow *next, *prev;
1774         GPULamp *lamp;
1775 } View3DShadow;
1776
1777 static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows)
1778 {
1779         GPULamp *lamp;
1780         Lamp *la = (Lamp*)ob->data;
1781         View3DShadow *shadow;
1782         
1783         lamp = GPU_lamp_from_blender(scene, ob, par);
1784         
1785         if(lamp) {
1786                 GPU_lamp_update(lamp, ob->lay, obmat);
1787                 GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
1788                 
1789                 if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) {
1790                         shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow");
1791                         shadow->lamp = lamp;
1792                         BLI_addtail(shadows, shadow);
1793                 }
1794         }
1795 }
1796
1797 static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
1798 {
1799         ListBase shadows;
1800         View3DShadow *shadow;
1801         Scene *sce;
1802         Base *base;
1803         Object *ob;
1804         
1805         shadows.first= shadows.last= NULL;
1806         
1807         /* update lamp transform and gather shadow lamps */
1808         for(SETLOOPER(scene, base)) {
1809                 ob= base->object;
1810                 
1811                 if(ob->type == OB_LAMP)
1812                         gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows);
1813                 
1814                 if (ob->transflag & OB_DUPLI) {
1815                         DupliObject *dob;
1816                         ListBase *lb = object_duplilist(scene, ob);
1817                         
1818                         for(dob=lb->first; dob; dob=dob->next)
1819                                 if(dob->ob->type==OB_LAMP)
1820                                         gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows);
1821                         
1822                         free_object_duplilist(lb);
1823                 }
1824         }
1825         
1826         /* render shadows after updating all lamps, nested object_duplilist
1827                 * don't work correct since it's replacing object matrices */
1828         for(shadow=shadows.first; shadow; shadow=shadow->next) {
1829                 /* this needs to be done better .. */
1830                 float viewmat[4][4], winmat[4][4];
1831                 int drawtype, lay, winsize, flag2;
1832                 
1833                 drawtype= v3d->drawtype;
1834                 lay= v3d->lay;
1835                 flag2= v3d->flag2 & V3D_SOLID_TEX;
1836                 
1837                 v3d->drawtype = OB_SOLID;
1838                 v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
1839                 v3d->flag2 &= ~V3D_SOLID_TEX;
1840                 
1841                 GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
1842 // XXX          drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1);
1843                 GPU_lamp_shadow_buffer_unbind(shadow->lamp);
1844                 
1845                 v3d->drawtype= drawtype;
1846                 v3d->lay= lay;
1847                 v3d->flag2 |= flag2;
1848         }
1849         
1850         BLI_freelistN(&shadows);
1851 }
1852
1853 /* *********************** customdata **************** */
1854
1855 /* goes over all modes and view3d settings */
1856 static CustomDataMask get_viewedit_datamask(bScreen *screen)
1857 {
1858         CustomDataMask mask = CD_MASK_BAREMESH;
1859         ScrArea *sa;
1860         
1861         /* check if we need tfaces & mcols due to face select or texture paint */
1862         if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT)
1863                 mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
1864         
1865         /* check if we need tfaces & mcols due to view mode */
1866         for(sa = screen->areabase.first; sa; sa = sa->next) {
1867                 if(sa->spacetype == SPACE_VIEW3D) {
1868                         View3D *view = sa->spacedata.first;
1869                         if(view->drawtype == OB_SHADED) {
1870                                 /* this includes normals for mesh_create_shadedColors */
1871                                 mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO;
1872                         }
1873                         if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
1874                                 mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
1875                                 
1876                                 if((G.fileflags & G_FILE_GAME_MAT) &&
1877                                    (G.fileflags & G_FILE_GAME_MAT_GLSL)) {
1878                                         mask |= CD_MASK_ORCO;
1879                                 }
1880                         }
1881                 }
1882         }
1883         
1884         /* check if we need mcols due to vertex paint or weightpaint */
1885         if(G.f & G_VERTEXPAINT)
1886                 mask |= CD_MASK_MCOL;
1887         if(G.f & G_WEIGHTPAINT)
1888                 mask |= CD_MASK_WEIGHT_MCOL;
1889         
1890         if(G.f & G_SCULPTMODE)
1891                 mask |= CD_MASK_MDISPS;
1892         
1893         return mask;
1894 }
1895
1896 void view3d_main_area_draw(const bContext *C, ARegion *ar)
1897 {
1898         Scene *scene= CTX_data_scene(C);
1899         View3D *v3d = CTX_wm_view3d(C);
1900         RegionView3D *rv3d= CTX_wm_region_view3d(C);
1901         Scene *sce;
1902         Base *base;
1903         Object *ob;
1904         int retopo= 0, sculptparticle= 0;
1905         Object *obact = OBACT;
1906         char *grid_unit= NULL;
1907         
1908         /* from now on all object derived meshes check this */
1909         v3d->customdata_mask= get_viewedit_datamask(CTX_wm_screen(C));
1910         
1911         /* shadow buffers, before we setup matrices */
1912         if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
1913                 gpu_update_lamps_shadows(scene, v3d);
1914         
1915         setwinmatrixview3d(ar, v3d, NULL);      /* 0= no pick rect */
1916         setviewmatrixview3d(scene, v3d, rv3d);  /* note: calls where_is_object for camera... */
1917         
1918         Mat4MulMat4(rv3d->persmat, rv3d->viewmat, rv3d->winmat);
1919         Mat4Invert(rv3d->persinv, rv3d->persmat);
1920         Mat4Invert(rv3d->viewinv, rv3d->viewmat);
1921         
1922         /* calculate pixelsize factor once, is used for lamps and obcenters */
1923         {
1924                 float len1, len2, vec[3];
1925                 
1926                 VECCOPY(vec, rv3d->persinv[0]);
1927                 len1= Normalize(vec);
1928                 VECCOPY(vec, rv3d->persinv[1]);
1929                 len2= Normalize(vec);
1930                 
1931                 rv3d->pixsize= 2.0f*(len1>len2?len1:len2);
1932                 
1933                 /* correct for window size */
1934                 if(ar->winx > ar->winy) rv3d->pixsize/= (float)ar->winx;
1935                 else rv3d->pixsize/= (float)ar->winy;
1936         }
1937         
1938         if(v3d->drawtype > OB_WIRE) {
1939                 float col[3];
1940                 UI_GetThemeColor3fv(TH_BACK, col);
1941                 glClearColor(col[0], col[1], col[2], 0.0); 
1942                 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1943                 
1944                 glLoadIdentity();
1945         }
1946         else {
1947                 float col[3];
1948                 UI_GetThemeColor3fv(TH_BACK, col);
1949                 glClearColor(col[0], col[1], col[2], 0.0);
1950                 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1951         }
1952         
1953         wmLoadMatrix(rv3d->viewmat);
1954         
1955         if(rv3d->rflag & RV3D_CLIPPING)
1956                 view3d_draw_clipping(rv3d);
1957         
1958         /* set zbuffer after we draw clipping region */
1959         if(v3d->drawtype > OB_WIRE) {
1960                 v3d->zbuf= TRUE;
1961                 glEnable(GL_DEPTH_TEST);
1962         }
1963         
1964         // needs to be done always, gridview is adjusted in drawgrid() now
1965         v3d->gridview= v3d->grid;
1966         
1967         if(rv3d->view==0 || rv3d->persp!=0) {
1968                 drawfloor(scene, v3d);
1969                 if(rv3d->persp==2) {
1970                         if(scene->world) {
1971                                 if(scene->world->mode & WO_STARS) {
1972                                         RE_make_stars(NULL, scene, star_stuff_init_func, star_stuff_vertex_func,
1973                                                                   star_stuff_term_func);
1974                                 }
1975                         }
1976                         if(v3d->flag & V3D_DISPBGPIC) draw_bgpic(scene, ar, v3d);
1977                 }
1978         }
1979         else {
1980                 ED_region_pixelspace(ar);
1981                 drawgrid(&scene->unit, ar, v3d, &grid_unit);
1982                 /* XXX make function? replaces persp(1) */
1983                 glMatrixMode(GL_PROJECTION);
1984                 wmLoadMatrix(rv3d->winmat);
1985                 glMatrixMode(GL_MODELVIEW);
1986                 wmLoadMatrix(rv3d->viewmat);
1987                 
1988                 if(v3d->flag & V3D_DISPBGPIC) {
1989                         draw_bgpic(scene, ar, v3d);
1990                 }
1991         }
1992         
1993         if(rv3d->rflag & RV3D_CLIPPING)
1994                 view3d_set_clipping(rv3d);
1995         
1996         /* draw set first */
1997         if(scene->set) {
1998                 for(SETLOOPER(scene->set, base)) {
1999                         
2000                         if(v3d->lay & base->lay) {
2001                                 
2002                                 UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
2003                                 draw_object(scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET);
2004                                 
2005                                 if(base->object->transflag & OB_DUPLI) {
2006                                         draw_dupli_objects_color(scene, ar, v3d, base, TH_WIRE);
2007                                 }
2008                         }
2009                 }
2010                 
2011                 /* Transp and X-ray afterdraw stuff for sets is done later */
2012         }
2013         
2014         /* extra service in layerbuttons, showing used layers */
2015         v3d->lay_used = 0;
2016         
2017         /* then draw not selected and the duplis, but skip editmode object */
2018         for(base= scene->base.first; base; base= base->next) {
2019                 v3d->lay_used |= base->lay;
2020                 
2021                 if(v3d->lay & base->lay) {
2022                         
2023                         /* dupli drawing */
2024                         if(base->object->transflag & OB_DUPLI) {
2025                                 draw_dupli_objects(scene, ar, v3d, base);
2026                         }
2027                         if((base->flag & SELECT)==0) {
2028                                 if(base->object!=scene->obedit) 
2029                                         draw_object(scene, ar, v3d, base, 0);
2030                         }
2031                 }
2032         }
2033
2034 //      retopo= retopo_mesh_check() || retopo_curve_check();
2035         sculptparticle= (G.f & (G_SCULPTMODE|G_PARTICLEEDIT)) && !scene->obedit;
2036         if(retopo)
2037                 view3d_update_depths(ar, v3d);
2038         
2039         /* draw selected and editmode */
2040         for(base= scene->base.first; base; base= base->next) {
2041                 if(v3d->lay & base->lay) {
2042                         if (base->object==scene->obedit || ( base->flag & SELECT) ) 
2043                                 draw_object(scene, ar, v3d, base, 0);
2044                 }
2045         }
2046         
2047         if(!retopo && sculptparticle && !(obact && (obact->dtx & OB_DRAWXRAY))) {
2048                 if(G.f & G_SCULPTMODE)
2049                         draw_sculpt_depths(scene, ar, v3d);
2050                 view3d_update_depths(ar, v3d);
2051         }
2052         
2053         ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST);
2054         
2055 //      REEB_draw();
2056         
2057 //      if(scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID);
2058         
2059         /* Transp and X-ray afterdraw stuff */
2060         view3d_draw_transp(scene, ar, v3d);
2061         view3d_draw_xray(scene, ar, v3d, 1);    // clears zbuffer if it is used!
2062         
2063         if(!retopo && sculptparticle && (obact && (OBACT->dtx & OB_DRAWXRAY))) {
2064                 if(G.f & G_SCULPTMODE)
2065                         draw_sculpt_depths(scene, ar, v3d);
2066                 view3d_update_depths(ar, v3d);
2067         }
2068         
2069         if(rv3d->rflag & RV3D_CLIPPING)
2070                 view3d_clr_clipping();
2071         
2072         BIF_draw_manipulator(C);
2073         
2074         if(v3d->zbuf) {
2075                 v3d->zbuf= FALSE;
2076                 glDisable(GL_DEPTH_TEST);
2077         }
2078         
2079         /* draw grease-pencil stuff */
2080 //      if (v3d->flag2 & V3D_DISPGP)
2081 //              draw_gpencil_3dview(ar, 1);
2082         
2083         BDR_drawSketch(C);
2084         
2085         ED_region_pixelspace(ar);
2086         
2087         /* Draw Sculpt Mode brush XXX (removed) */
2088         
2089 //      retopo_paint_view_update(v3d);
2090 //      retopo_draw_paint_lines();
2091         
2092         /* Draw particle edit brush XXX (removed) */
2093         
2094         if(rv3d->persp>1) drawviewborder(scene, ar, v3d);
2095         if(rv3d->rflag & RV3D_FLYMODE) drawviewborder_flymode(ar);
2096         
2097         /* draw grease-pencil stuff */
2098 //      if (v3d->flag2 & V3D_DISPGP)
2099 //              draw_gpencil_3dview(ar, 0);
2100
2101         drawcursor(scene, ar, v3d);
2102         
2103         if(U.uiflag & USER_SHOW_ROTVIEWICON)
2104                 draw_view_axis(rv3d);
2105         else    
2106                 draw_view_icon(rv3d);
2107         
2108         /* XXX removed viewport fps */
2109         if(U.uiflag & USER_SHOW_VIEWPORTNAME) {
2110                 draw_viewport_name(ar, v3d);
2111         }
2112         if (grid_unit) { /* draw below the viewport name */
2113                 UI_ThemeColor(TH_TEXT_HI);
2114                 BLF_draw_default(10,  ar->winy-(USER_SHOW_VIEWPORTNAME?40:20), 0.0f, grid_unit);
2115         }
2116
2117         ob= OBACT;
2118         if(U.uiflag & USER_DRAWVIEWINFO) 
2119                 draw_selected_name(scene, ob, v3d);
2120         
2121         /* XXX here was the blockhandlers for floating panels */
2122
2123         if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || G.f & G_TEXTUREPAINT) {
2124                 v3d->flag |= V3D_NEEDBACKBUFDRAW;
2125                 // XXX addafterqueue(ar->win, BACKBUFDRAW, 1);
2126         }
2127
2128         if((G.f & G_PARTICLEEDIT) && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) {
2129                 v3d->flag |= V3D_NEEDBACKBUFDRAW;
2130                 // XXX addafterqueue(ar->win, BACKBUFDRAW, 1);
2131         }
2132
2133         // test for backbuf select
2134         if(scene->obedit && v3d->drawtype>OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) {
2135                 
2136                 v3d->flag |= V3D_NEEDBACKBUFDRAW;
2137                 // XXX if(afterqtest(ar->win, BACKBUFDRAW)==0) {
2138                 //      addafterqueue(ar->win, BACKBUFDRAW, 1);
2139                 //}
2140         }
2141 }
2142
2143